From ae6ddabc153c07115d1a03a57048c712aa67c654 Mon Sep 17 00:00:00 2001 From: SeaDve Date: Tue, 14 Mar 2023 20:24:22 +0800 Subject: [PATCH] glib-macros: generate "From for Value" on ValueDelegate This allows `Ident` to be allowed on functions that take in Into. --- glib-macros/src/lib.rs | 8 +++ glib-macros/src/value_delegate_derive.rs | 7 +++ glib-macros/tests/value_delegate_derive.rs | 66 ++++++++++++++++++++-- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/glib-macros/src/lib.rs b/glib-macros/src/lib.rs index 38813fb9985d..c11dc351d6bd 100644 --- a/glib-macros/src/lib.rs +++ b/glib-macros/src/lib.rs @@ -1013,6 +1013,14 @@ pub fn derive_props(input: TokenStream) -> TokenStream { /// } /// } /// } +/// impl From for u32 { +/// fn from(v: MyEnum) -> Self { +/// match v { +/// MyEnum::Zero => 0, +/// MyEnum::NotZero(x) => x +/// } +/// } +/// } /// /// let myv = MyEnum::NotZero(34); /// let convertedv = myv.to_value(); diff --git a/glib-macros/src/value_delegate_derive.rs b/glib-macros/src/value_delegate_derive.rs index f151fe99a37d..dd5b5a409528 100644 --- a/glib-macros/src/value_delegate_derive.rs +++ b/glib-macros/src/value_delegate_derive.rs @@ -158,6 +158,7 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result::static_type() } } + impl #crate_ident::value::ToValue for #ident { fn to_value(&self) -> #crate_ident::value::Value { let this = self; @@ -169,6 +170,12 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result for #crate_ident::value::Value { + fn from(this: #ident) -> Self { + #crate_ident::value::Value::from(#delegate_value) + } + } + #to_value_optional unsafe impl<'a> #crate_ident::value::FromValue<'a> for #ident { diff --git a/glib-macros/tests/value_delegate_derive.rs b/glib-macros/tests/value_delegate_derive.rs index 8f1a8522ec65..e50fe59e5641 100644 --- a/glib-macros/tests/value_delegate_derive.rs +++ b/glib-macros/tests/value_delegate_derive.rs @@ -1,15 +1,68 @@ -use glib::{value::FromValue, HasParamSpec, StaticType, ToValue}; +use glib::{value::FromValue, HasParamSpec, StaticType, ToValue, Value, ValueDelegate}; + +#[test] +fn into_value() { + fn test_func(_: impl Into) {} + + #[derive(ValueDelegate)] + pub struct Test(i32); + + #[derive(ValueDelegate)] + #[value_delegate(from = i64)] + pub struct TestManualFrom(i32); + + impl From for TestManualFrom { + fn from(v: i64) -> Self { + Self(v as i32) + } + } + impl<'a> From<&'a TestManualFrom> for i64 { + fn from(v: &'a TestManualFrom) -> Self { + v.0 as i64 + } + } + impl From for i64 { + fn from(v: TestManualFrom) -> Self { + v.0 as i64 + } + } + + test_func(&Test(123)); + test_func(Test(123)); + test_func(&TestManualFrom(123)); + test_func(TestManualFrom(123)); + + let value = Test(123).to_value(); + let value = TestManualFrom(123).to_value(); + + assert_eq!(glib::Value::from(Test(123)).get::().unwrap().0, 123); + assert_eq!(glib::Value::from(123).get::().unwrap().0, 123); + assert_eq!( + glib::Value::from(TestManualFrom(123)) + .get::() + .unwrap() + .0, + 123 + ); + assert_eq!( + glib::Value::from(123_i64) + .get::() + .unwrap() + .0, + 123 + ); +} #[test] fn higher_level_types() { - #[derive(Debug, glib::ValueDelegate)] + #[derive(Debug, ValueDelegate)] pub struct MyVec(Vec); - #[derive(Debug, glib::ValueDelegate)] + #[derive(Debug, ValueDelegate)] #[value_delegate(nullable)] pub struct MyString(Box); - #[derive(Debug, glib::ValueDelegate)] + #[derive(Debug, ValueDelegate)] #[value_delegate(from = Option)] struct MyVecManualFrom(Vec); @@ -23,6 +76,11 @@ fn higher_level_types() { v.0.iter().next().cloned() } } + impl From for Option { + fn from(v: MyVecManualFrom) -> Self { + v.0.into_iter().next() + } + } let vec = vec!["foo".to_string(), "bar".to_string()]; let vec_value = vec.to_value();