From 4a9a20318331ba03561127f82f6ff8078c1d2a85 Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Date: Thu, 3 Sep 2020 15:19:15 +0200 Subject: [PATCH] Variant support for Option (Maybe type of GVariant) --- src/variant.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/variant.rs b/src/variant.rs index c4f1978e..d749ffa6 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -74,6 +74,17 @@ //! assert_eq!(tuple.0, "hello"); //! assert_eq!(tuple.1, 42); //! assert_eq!(tuple.2, &[ "there", "you"]); +//! +//! // `Option` is supported as well, through maybe types +//! let variant = Some("hello").to_variant(); +//! assert_eq!(variant.n_children(), 1); +//! let mut s = >::from_variant(&variant).unwrap(); +//! assert_eq!(s.unwrap(), "hello"); +//! s = None; +//! let variant = s.to_variant(); +//! assert_eq!(variant.n_children(), 0); +//! let s = >::from_variant(&variant).unwrap(); +//! assert!(s.is_none()); //! ``` use bytes::Bytes; @@ -244,6 +255,25 @@ impl Variant { } } + /// Creates a new maybe Variant. + pub fn new_maybe(child: Option<&Variant>) -> Self { + let type_ = T::static_variant_type(); + let ptr = match child { + Some(child) => { + assert_eq!(type_, child.type_()); + + child.to_glib_none().0 + } + None => std::ptr::null(), + }; + unsafe { + from_glib_none(glib_sys::g_variant_new_maybe( + type_.as_ptr() as *const _, + ptr as *mut glib_sys::GVariant, + )) + } + } + /// Constructs a new serialised-mode GVariant instance. pub fn from_bytes(bytes: &Bytes) -> Self { unsafe { @@ -499,6 +529,42 @@ impl From for Variant { } } +impl StaticVariantType for Option { + fn static_variant_type() -> Cow<'static, VariantTy> { + let child_type = T::static_variant_type(); + let signature = format!("m{}", child_type.to_str()); + + VariantType::new(&signature) + .expect("incorrect signature") + .into() + } +} + +impl ToVariant for Option { + fn to_variant(&self) -> Variant { + Variant::new_maybe::(self.as_ref().map(|m| m.to_variant()).as_ref()) + } +} + +impl FromVariant for Option { + fn from_variant(variant: &Variant) -> Option { + unsafe { + if variant.is::() { + let c_child = glib_sys::g_variant_get_maybe(variant.to_glib_none().0); + if !c_child.is_null() { + let child: Variant = from_glib_full(c_child); + + Some(T::from_variant(&child)) + } else { + Some(None) + } + } else { + None + } + } + } +} + impl StaticVariantType for [T] { fn static_variant_type() -> Cow<'static, VariantTy> { let child_type = T::static_variant_type();