glib-macros 0.17.4

Rust bindings for the GLib library, proc macros crate
Documentation
use glib::{value::FromValue, HasParamSpec, StaticType, ToValue};

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

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

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

    impl From<Option<String>> for MyVecManualFrom {
        fn from(v: Option<String>) -> Self {
            Self(v.into_iter().collect::<Vec<_>>())
        }
    }
    impl<'a> From<&'a MyVecManualFrom> for Option<String> {
        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::<String>::static_type());
    assert_eq!(
        vec_value.get::<Vec<String>>().unwrap(),
        my_vec_value.get::<Vec<String>>().unwrap(),
    );
    assert_eq!(vec_value.value_type(), my_vec_value.value_type());
    assert_eq!(unsafe { Vec::<String>::from_value(&vec_value) }, unsafe {
        MyVec::from_value(&vec_value).0
    });
    assert_eq!(
        unsafe { Vec::<String>::from_value(&my_vec_value) },
        unsafe { MyVec::from_value(&my_vec_value).0 }
    );

    let string = "foo".to_string();
    let string_value = string.to_value();
    let my_string_value = MyString(string.into()).to_value();
    assert_eq!(MyString::static_type(), Box::<str>::static_type());
    assert_eq!(
        string_value.get::<Box<str>>().unwrap(),
        my_string_value.get::<Box<str>>().unwrap(),
    );
    assert_eq!(string_value.value_type(), my_string_value.value_type());
    assert_eq!(unsafe { Box::<str>::from_value(&string_value) }, unsafe {
        MyString::from_value(&string_value).0
    });
    assert_eq!(
        unsafe { Box::<str>::from_value(&my_string_value) },
        unsafe { MyString::from_value(&my_string_value).0 }
    );

    let string_some = Some("foo".to_string());
    let string_some_value = string_some.to_value();
    let string_none_value = None::<String>.to_value();
    let my_string_some_value = MyString(string_some.unwrap().into()).to_value();
    let my_string_none_value = None::<MyString>.to_value();
    assert_eq!(
        Option::<MyString>::static_type(),
        Option::<Box<str>>::static_type()
    );
    assert_eq!(
        string_some_value
            .get::<Option<Box<str>>>()
            .unwrap()
            .unwrap(),
        my_string_some_value
            .get::<Option<Box<str>>>()
            .unwrap()
            .unwrap(),
    );
    assert_eq!(
        string_none_value
            .get::<Option<Box<str>>>()
            .unwrap()
            .is_none(),
        my_string_none_value
            .get::<Option<Box<str>>>()
            .unwrap()
            .is_none(),
    );
    assert_eq!(
        string_some_value.value_type(),
        my_string_some_value.value_type()
    );
    assert_eq!(
        string_none_value.value_type(),
        my_string_none_value.value_type()
    );
    assert_eq!(
        unsafe { Option::<Box<str>>::from_value(&string_some_value).unwrap() },
        unsafe {
            Option::<MyString>::from_value(&string_some_value)
                .unwrap()
                .0
        }
    );
    assert_eq!(
        unsafe { Option::<Box<str>>::from_value(&string_none_value).is_none() },
        unsafe { Option::<MyString>::from_value(&string_none_value).is_none() }
    );
    assert_eq!(
        unsafe { Option::<Box<str>>::from_value(&my_string_some_value).unwrap() },
        unsafe {
            Option::<MyString>::from_value(&my_string_some_value)
                .unwrap()
                .0
        }
    );
    assert_eq!(
        unsafe { Option::<Box<str>>::from_value(&my_string_none_value).is_none() },
        unsafe { Option::<MyString>::from_value(&my_string_none_value).is_none() }
    );

    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::<String>::static_type()
    );
    assert_eq!(
        opt_value.get::<Option<String>>().unwrap(),
        my_vec_manual_from_value.get::<Option<String>>().unwrap(),
    );
    assert_eq!(
        opt_value.value_type(),
        my_vec_manual_from_value.value_type()
    );
    assert_eq!(
        unsafe {
            Option::<String>::from_value(&opt_value)
                .into_iter()
                .collect::<Vec<_>>()
        },
        unsafe { MyVecManualFrom::from_value(&opt_value).0 }
    );
    assert_eq!(
        unsafe {
            Option::<String>::from_value(&my_vec_manual_from_value)
                .into_iter()
                .collect::<Vec<_>>()
        },
        unsafe { MyVecManualFrom::from_value(&my_vec_manual_from_value).0 }
    );
}