Skip to content

Commit 1067617

Browse files
committed
glib: impl From<T> for Variant to move into variants
1 parent a859829 commit 1067617

File tree

3 files changed

+379
-33
lines changed

3 files changed

+379
-33
lines changed

glib-macros/src/variant_derive.rs

Lines changed: 110 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ fn derive_variant_for_struct(
3737
data_struct: syn::DataStruct,
3838
) -> TokenStream {
3939
let glib = crate_ident_new();
40+
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
4041
let (static_variant_type, to_variant, from_variant) = match data_struct.fields {
4142
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
4243
let types = unnamed
@@ -49,7 +50,7 @@ fn derive_variant_for_struct(
4950
let idents_len = idents.len();
5051

5152
let static_variant_type = quote! {
52-
impl #generics #glib::StaticVariantType for #ident #generics {
53+
impl #impl_generics #glib::StaticVariantType for #ident #type_generics #where_clause {
5354
fn static_variant_type() -> ::std::borrow::Cow<'static, #glib::VariantTy> {
5455
static TYP: #glib::once_cell::sync::Lazy<#glib::VariantType> = #glib::once_cell::sync::Lazy::new(|| {
5556

@@ -72,7 +73,7 @@ fn derive_variant_for_struct(
7273
};
7374

7475
let to_variant = quote! {
75-
impl #generics #glib::ToVariant for #ident #generics {
76+
impl #impl_generics #glib::ToVariant for #ident #type_generics #where_clause {
7677
fn to_variant(&self) -> #glib::Variant {
7778
#glib::Variant::tuple_from_iter(::std::array::IntoIter::<#glib::Variant, #idents_len>::new([
7879
#(
@@ -81,10 +82,20 @@ fn derive_variant_for_struct(
8182
]))
8283
}
8384
}
85+
86+
impl #impl_generics ::std::convert::From<#ident #type_generics> for #glib::Variant #where_clause {
87+
fn from(v: #ident #type_generics) -> #glib::Variant {
88+
#glib::Variant::tuple_from_iter(::std::array::IntoIter::<#glib::Variant, #idents_len>::new([
89+
#(
90+
<#glib::Variant as ::std::convert::From<_>>::from(v.#idents)
91+
),*
92+
]))
93+
}
94+
}
8495
};
8596

8697
let from_variant = quote! {
87-
impl #generics #glib::FromVariant for #ident #generics {
98+
impl #impl_generics #glib::FromVariant for #ident #type_generics #where_clause {
8899
fn from_variant(variant: &#glib::Variant) -> ::core::option::Option<Self> {
89100
if !variant.is_container() {
90101
return None;
@@ -115,7 +126,7 @@ fn derive_variant_for_struct(
115126
let counts = (0..types.len()).map(syn::Index::from).collect::<Vec<_>>();
116127

117128
let static_variant_type = quote! {
118-
impl #generics #glib::StaticVariantType for #ident #generics {
129+
impl #impl_generics #glib::StaticVariantType for #ident #type_generics #where_clause {
119130
fn static_variant_type() -> ::std::borrow::Cow<'static, #glib::VariantTy> {
120131
static TYP: #glib::once_cell::sync::Lazy<#glib::VariantType> = #glib::once_cell::sync::Lazy::new(|| unsafe {
121132
let ptr = #glib::ffi::g_string_sized_new(16);
@@ -144,7 +155,7 @@ fn derive_variant_for_struct(
144155
};
145156

146157
let to_variant = quote! {
147-
impl #generics #glib::ToVariant for #ident #generics {
158+
impl #impl_generics #glib::ToVariant for #ident #type_generics #where_clause {
148159
fn to_variant(&self) -> #glib::Variant {
149160
#glib::Variant::tuple_from_iter(::std::iter::IntoIterator::into_iter([
150161
#(
@@ -153,10 +164,20 @@ fn derive_variant_for_struct(
153164
]))
154165
}
155166
}
167+
168+
impl #impl_generics ::std::convert::From<#ident #type_generics> for #glib::Variant #where_clause {
169+
fn from(v: #ident #type_generics) -> #glib::Variant {
170+
#glib::Variant::tuple_from_iter(::std::iter::IntoIterator::into_iter([
171+
#(
172+
<#glib::Variant as ::std::convert::From<_>>::from(v.#idents)
173+
),*
174+
]))
175+
}
176+
}
156177
};
157178

158179
let from_variant = quote! {
159-
impl #generics #glib::FromVariant for #ident #generics {
180+
impl #impl_generics #glib::FromVariant for #ident #type_generics #where_clause {
160181
fn from_variant(variant: &#glib::Variant) -> ::core::option::Option<Self> {
161182
if !variant.is_container() {
162183
return None;
@@ -177,23 +198,32 @@ fn derive_variant_for_struct(
177198
}
178199
Fields::Unit => {
179200
let static_variant_type = quote! {
180-
impl #generics #glib::StaticVariantType for #ident #generics {
201+
impl #impl_generics #glib::StaticVariantType for #ident #type_generics #where_clause {
202+
#[inline]
181203
fn static_variant_type() -> ::std::borrow::Cow<'static, #glib::VariantTy> {
182204
::std::borrow::Cow::Borrowed(#glib::VariantTy::UNIT)
183205
}
184206
}
185207
};
186208

187209
let to_variant = quote! {
188-
impl #generics #glib::ToVariant for #ident #generics {
210+
impl #impl_generics #glib::ToVariant for #ident #type_generics #where_clause {
211+
#[inline]
189212
fn to_variant(&self) -> #glib::Variant {
190213
#glib::ToVariant::to_variant(&())
191214
}
192215
}
216+
217+
impl #impl_generics ::std::convert::From<#ident #type_generics> for #glib::Variant #where_clause {
218+
#[inline]
219+
fn from(v: #ident #type_generics) -> #glib::Variant {
220+
#glib::ToVariant::to_variant(&())
221+
}
222+
}
193223
};
194224

195225
let from_variant = quote! {
196-
impl #generics #glib::FromVariant for #ident #generics {
226+
impl #impl_generics #glib::FromVariant for #ident #type_generics #where_clause {
197227
fn from_variant(variant: &#glib::Variant) -> ::core::option::Option<Self> {
198228
Some(Self)
199229
}
@@ -262,6 +292,7 @@ fn derive_variant_for_enum(
262292
) -> TokenStream {
263293
let glib = crate_ident_new();
264294
let static_variant_type = format!("({}v)", mode.tag_type());
295+
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
265296

266297
let to = data_enum.variants.iter().enumerate().map(|(index, v)| {
267298
let ident = &v.ident;
@@ -319,6 +350,54 @@ fn derive_variant_for_enum(
319350
},
320351
}
321352
});
353+
let into = data_enum.variants.iter().enumerate().map(|(index, v)| {
354+
let field_ident = &v.ident;
355+
let tag = match &mode {
356+
EnumMode::String => {
357+
let nick = ToKebabCase::to_kebab_case(field_ident.to_string().as_str());
358+
quote! { #nick }
359+
}
360+
EnumMode::Repr(repr) => quote! { #index as #repr },
361+
_ => unimplemented!(),
362+
};
363+
match &v.fields {
364+
syn::Fields::Named(FieldsNamed { named, .. }) => {
365+
let field_names = named.iter().map(|f| f.ident.as_ref().unwrap());
366+
let field_names2 = field_names.clone();
367+
quote! {
368+
#ident::#field_ident { #(#field_names),* } => #glib::ToVariant::to_variant(&(
369+
#tag,
370+
#glib::Variant::tuple_from_iter(::std::iter::IntoIterator::into_iter([
371+
#(<#glib::Variant as ::std::convert::From<_>>::from(#field_names2)),*
372+
]))
373+
))
374+
}
375+
}
376+
syn::Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
377+
let field_names = unnamed
378+
.iter()
379+
.enumerate()
380+
.map(|(i, _)| format_ident!("field{}", i));
381+
let field_names2 = field_names.clone();
382+
quote! {
383+
#ident::#field_ident(#(#field_names),*) => #glib::ToVariant::to_variant(&(
384+
#tag,
385+
#glib::Variant::tuple_from_iter(::std::iter::IntoIterator::into_iter([
386+
#(<#glib::Variant as ::std::convert::From<_>>::from(#field_names2)),*
387+
]))
388+
))
389+
}
390+
}
391+
syn::Fields::Unit => {
392+
quote! {
393+
#ident::#field_ident => #glib::ToVariant::to_variant(&(
394+
#tag,
395+
#glib::ToVariant::to_variant(&())
396+
))
397+
}
398+
}
399+
}
400+
});
322401
let from = data_enum.variants.iter().enumerate().map(|(index, v)| {
323402
let ident = &v.ident;
324403
let tag = match &mode {
@@ -368,7 +447,7 @@ fn derive_variant_for_enum(
368447
};
369448

370449
let derived = quote! {
371-
impl #generics #glib::StaticVariantType for #ident #generics {
450+
impl #impl_generics #glib::StaticVariantType for #ident #type_generics #where_clause {
372451
fn static_variant_type() -> ::std::borrow::Cow<'static, #glib::VariantTy> {
373452
::std::borrow::Cow::Borrowed(
374453
unsafe {
@@ -378,15 +457,23 @@ fn derive_variant_for_enum(
378457
}
379458
}
380459

381-
impl #generics #glib::ToVariant for #ident #generics {
460+
impl #impl_generics #glib::ToVariant for #ident #type_generics #where_clause {
382461
fn to_variant(&self) -> #glib::Variant {
383462
match self {
384463
#(#to),*
385464
}
386465
}
387466
}
388467

389-
impl #generics #glib::FromVariant for #ident #generics {
468+
impl #impl_generics ::std::convert::From<#ident #type_generics> for #glib::Variant #where_clause {
469+
fn from(v: #ident #type_generics) -> #glib::Variant {
470+
match v {
471+
#(#into),*
472+
}
473+
}
474+
}
475+
476+
impl #impl_generics #glib::FromVariant for #ident #type_generics #where_clause {
390477
fn from_variant(variant: &#glib::Variant) -> ::std::option::Option<Self> {
391478
let (tag, value) = <(#repr, #glib::Variant) as #glib::FromVariant>::from_variant(&variant)?;
392479
if !#glib::VariantTy::is_tuple(#glib::Variant::type_(&value)) {
@@ -410,6 +497,7 @@ fn derive_variant_for_c_enum(
410497
) -> TokenStream {
411498
let glib = crate_ident_new();
412499
let static_variant_type = mode.tag_type().to_string();
500+
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
413501

414502
let (to_variant, from_variant) = match mode {
415503
EnumMode::String => {
@@ -508,7 +596,7 @@ fn derive_variant_for_c_enum(
508596
};
509597

510598
let derived = quote! {
511-
impl #generics #glib::StaticVariantType for #ident #generics {
599+
impl #impl_generics #glib::StaticVariantType for #ident #type_generics #where_clause {
512600
fn static_variant_type() -> ::std::borrow::Cow<'static, #glib::VariantTy> {
513601
::std::borrow::Cow::Borrowed(
514602
unsafe {
@@ -518,13 +606,20 @@ fn derive_variant_for_c_enum(
518606
}
519607
}
520608

521-
impl #generics #glib::ToVariant for #ident #generics {
609+
impl #impl_generics #glib::ToVariant for #ident #type_generics #where_clause {
522610
fn to_variant(&self) -> #glib::Variant {
523611
#to_variant
524612
}
525613
}
526614

527-
impl #generics #glib::FromVariant for #ident #generics {
615+
impl #impl_generics ::std::convert::From<#ident #type_generics> for #glib::Variant #where_clause {
616+
#[inline]
617+
fn from(v: #ident #type_generics) -> #glib::Variant {
618+
<#ident #type_generics as #glib::ToVariant>::to_variant(&v)
619+
}
620+
}
621+
622+
impl #impl_generics #glib::FromVariant for #ident #type_generics #where_clause {
528623
fn from_variant(variant: &#glib::Variant) -> ::std::option::Option<Self> {
529624
#from_variant
530625
}

0 commit comments

Comments
 (0)