Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

Commit

Permalink
Variant support for Option (Maybe type of GVariant)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeenix committed Sep 3, 2020
1 parent c12edc6 commit 2c9df92
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <Option<String>>::from_variant(&variant).unwrap();
//! assert_eq!(s.unwrap(), "hello");
//! s = None;
//! let variant = s.to_variant();
//! assert_eq!(variant.n_children(), 0);
//! let s = <Option<String>>::from_variant(&variant).unwrap();
//! assert!(s.is_none());
//! ```

use bytes::Bytes;
Expand Down Expand Up @@ -245,6 +256,25 @@ impl Variant {
}
}

/// Creates a new maybe Variant.
pub fn new_maybe<T: StaticVariantType>(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<T: StaticVariantType>(bytes: &Bytes) -> Self {
unsafe {
Expand Down Expand Up @@ -500,6 +530,40 @@ impl<T: ToVariant> From<T> for Variant {
}
}

impl<T: StaticVariantType> StaticVariantType for Option<T> {
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<T: StaticVariantType + ToVariant> ToVariant for Option<T> {
fn to_variant(&self) -> Variant {
Variant::new_maybe::<T>(self.as_ref().map(|m| m.to_variant()).as_ref())
}
}

impl<T: StaticVariantType + FromVariant> FromVariant for Option<T> {
fn from_variant(variant: &Variant) -> Option<Self> {
unsafe {
if variant.is::<Self>() {
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<T: StaticVariantType> StaticVariantType for [T] {
fn static_variant_type() -> Cow<'static, VariantTy> {
let child_type = T::static_variant_type();
Expand Down

0 comments on commit 2c9df92

Please sign in to comment.