Skip to content

Commit

Permalink
glib-macros: generate "From<Ident> for Value" on ValueDelegate
Browse files Browse the repository at this point in the history
This allows `Ident` to be allowed on functions that take in Into<Value>.
  • Loading branch information
SeaDve committed Mar 14, 2023
1 parent 4aa810d commit bd43ea6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
8 changes: 8 additions & 0 deletions glib-macros/src/lib.rs
Expand Up @@ -1013,6 +1013,14 @@ pub fn derive_props(input: TokenStream) -> TokenStream {
/// }
/// }
/// }
/// impl From<MyEnum> 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();
Expand Down
7 changes: 7 additions & 0 deletions glib-macros/src/value_delegate_derive.rs
Expand Up @@ -158,6 +158,7 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result<proc_macro:
<#delegated_ty as #crate_ident::types::StaticType>::static_type()
}
}

impl #crate_ident::value::ToValue for #ident {
fn to_value(&self) -> #crate_ident::value::Value {
let this = self;
Expand All @@ -169,6 +170,12 @@ pub fn impl_value_delegate(input: ValueDelegateInput) -> syn::Result<proc_macro:
}
}

impl From<#ident> 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 {
Expand Down
65 changes: 61 additions & 4 deletions glib-macros/tests/value_delegate_derive.rs
@@ -1,15 +1,67 @@
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<Value>) {}

#[derive(ValueDelegate)]
pub struct Test(i32);

#[derive(ValueDelegate)]
#[value_delegate(from = i64)]
pub struct TestManualFrom(i32);

impl From<i64> 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<TestManualFrom> 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));

assert_eq!(glib::Value::from(Test(123)).get::<Test>().unwrap().0, 123);
assert_eq!(glib::Value::from(123).get::<Test>().unwrap().0, 123);

assert_eq!(
glib::Value::from(TestManualFrom(123))
.get::<TestManualFrom>()
.unwrap()
.0,
123
);
assert_eq!(
glib::Value::from(123_i64)
.get::<TestManualFrom>()
.unwrap()
.0,
123
);
}

#[test]
fn higher_level_types() {
#[derive(Debug, glib::ValueDelegate)]
#[derive(Debug, ValueDelegate)]
pub struct MyVec(Vec<String>);

#[derive(Debug, glib::ValueDelegate)]
#[derive(Debug, ValueDelegate)]
#[value_delegate(nullable)]
pub struct MyString(Box<str>);

#[derive(Debug, glib::ValueDelegate)]
#[derive(Debug, ValueDelegate)]
#[value_delegate(from = Option<String>)]
struct MyVecManualFrom(Vec<String>);

Expand All @@ -23,6 +75,11 @@ fn higher_level_types() {
v.0.iter().next().cloned()
}
}
impl From<MyVecManualFrom> for Option<String> {
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();
Expand Down

0 comments on commit bd43ea6

Please sign in to comment.