From b93d961745627f5504aeddf024da668ef5071e49 Mon Sep 17 00:00:00 2001 From: SeaDve Date: Mon, 6 Mar 2023 22:50:38 +0800 Subject: [PATCH] glib-macros: support higher level types on ValueDelegate --- glib-macros/src/value_delegate_derive.rs | 16 +++-- glib-macros/tests/value_delegate_derive.rs | 73 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 glib-macros/tests/value_delegate_derive.rs diff --git a/glib-macros/src/value_delegate_derive.rs b/glib-macros/src/value_delegate_derive.rs index e80d3826236e..f151fe99a37d 100644 --- a/glib-macros/src/value_delegate_derive.rs +++ b/glib-macros/src/value_delegate_derive.rs @@ -123,7 +123,9 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result quote!(#delegated_ty::from(this)), + DeriveMode::From => { + quote!(<#delegated_ty as std::convert::From<_>>::from(this)) + } DeriveMode::Private => quote!(this.0), }; @@ -142,14 +144,18 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result quote!(#ident::from(#delegated_ty::from_value(value))), - DeriveMode::Private => quote!(#ident(#delegated_ty::from_value(value))), + DeriveMode::From => { + quote!(#ident::from(<#delegated_ty as #crate_ident::value::FromValue<'a>>::from_value(value))) + } + DeriveMode::Private => { + quote!(#ident(<#delegated_ty as #crate_ident::value::FromValue<'a>>::from_value(value))) + } }; let res = quote! { impl #crate_ident::types::StaticType for #ident { fn static_type() -> glib::types::Type { - #delegated_ty::static_type() + <#delegated_ty as #crate_ident::types::StaticType>::static_type() } } impl #crate_ident::value::ToValue for #ident { @@ -179,7 +185,7 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result::BuilderFn; fn param_spec_builder() -> Self::BuilderFn { - #delegated_ty::param_spec_builder() + <#delegated_ty as #crate_ident::HasParamSpec>::param_spec_builder() } } }; diff --git a/glib-macros/tests/value_delegate_derive.rs b/glib-macros/tests/value_delegate_derive.rs new file mode 100644 index 000000000000..22d28190b915 --- /dev/null +++ b/glib-macros/tests/value_delegate_derive.rs @@ -0,0 +1,73 @@ +use glib::{value::FromValue, HasParamSpec, StaticType, ToValue}; + +#[test] +fn higher_level_types() { + #[derive(Debug, glib::ValueDelegate)] + pub struct MyVec(Vec); + + #[derive(Debug, glib::ValueDelegate)] + #[value_delegate(from = Option)] + struct MyVecManualFrom(Vec); + + impl From> for MyVecManualFrom { + fn from(v: Option) -> Self { + Self(v.into_iter().collect::>()) + } + } + impl<'a> From<&'a MyVecManualFrom> for Option { + fn from(v: &'a MyVecManualFrom) -> Self { + v.0.iter().next().cloned() + } + } + + let vec = vec!["foo".to_string(), "bar".to_string()]; + let vec_value = vec.to_value(); + let my_vec_value = MyVec(vec.clone()).to_value(); + + assert_eq!(MyVec::static_type(), Vec::::static_type()); + assert_eq!( + vec_value.get::>().unwrap(), + my_vec_value.get::>().unwrap(), + ); + assert_eq!(vec_value.value_type(), my_vec_value.value_type()); + assert_eq!(unsafe { Vec::::from_value(&vec_value) }, unsafe { + MyVec::from_value(&vec_value).0 + }); + assert_eq!( + unsafe { Vec::::from_value(&my_vec_value) }, + unsafe { MyVec::from_value(&my_vec_value).0 } + ); + + let opt = Some("foo".to_string()); + let opt_value = opt.to_value(); + let my_vec_manual_from_value = MyVecManualFrom::from(opt).to_value(); + + assert_eq!( + MyVecManualFrom::static_type(), + Option::::static_type() + ); + assert_eq!( + opt_value.get::>().unwrap(), + my_vec_manual_from_value.get::>().unwrap(), + ); + assert_eq!( + opt_value.value_type(), + my_vec_manual_from_value.value_type() + ); + assert_eq!( + unsafe { + Option::::from_value(&opt_value) + .into_iter() + .collect::>() + }, + unsafe { MyVecManualFrom::from_value(&opt_value).0 } + ); + assert_eq!( + unsafe { + Option::::from_value(&my_vec_manual_from_value) + .into_iter() + .collect::>() + }, + unsafe { MyVecManualFrom::from_value(&my_vec_manual_from_value).0 } + ); +}