Skip to content

Commit 79e7a30

Browse files
authored
Merge pull request #519 from arcnmx/variant-types
dynamic type function variants for Variants and Values
2 parents 60bc47f + ca031ed commit 79e7a30

File tree

2 files changed

+95
-12
lines changed

2 files changed

+95
-12
lines changed

glib/src/value.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,15 @@ impl Value {
450450
/// or is a sub-type of `T`.
451451
#[inline]
452452
pub fn is<T: StaticType>(&self) -> bool {
453-
self.type_().is_a(T::static_type())
453+
self.is_type(T::static_type())
454+
}
455+
456+
// rustdoc-stripper-ignore-next
457+
/// Returns `true` if the type of the value corresponds to `type_`
458+
/// or is a sub-type of `type_`.
459+
#[inline]
460+
pub fn is_type(&self, type_: Type) -> bool {
461+
self.type_().is_a(type_)
454462
}
455463

456464
// rustdoc-stripper-ignore-next
@@ -475,8 +483,15 @@ impl Value {
475483
/// Tries to transform the value into a value of the target type
476484
#[doc(alias = "g_value_transform")]
477485
pub fn transform<T: ValueType>(&self) -> Result<Value, crate::BoolError> {
486+
self.transform_with_type(T::Type::static_type())
487+
}
488+
489+
// rustdoc-stripper-ignore-next
490+
/// Tries to transform the value into a value of the target type
491+
#[doc(alias = "g_value_transform")]
492+
pub fn transform_with_type(&self, type_: Type) -> Result<Value, crate::BoolError> {
478493
unsafe {
479-
let mut dest = Value::for_value_type::<T>();
494+
let mut dest = Value::from_type(type_);
480495
if from_glib(gobject_ffi::g_value_transform(
481496
self.to_glib_none().0,
482497
dest.to_glib_none_mut().0,
@@ -486,7 +501,7 @@ impl Value {
486501
Err(crate::bool_error!(
487502
"Can't transform value of type '{}' into '{}'",
488503
self.type_(),
489-
T::Type::static_type()
504+
type_
490505
))
491506
}
492507
}

glib/src/variant.rs

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,20 @@ impl Variant {
236236
#[inline]
237237
#[doc(alias = "g_variant_is_of_type")]
238238
pub fn is<T: StaticVariantType>(&self) -> bool {
239+
self.is_type(&T::static_variant_type())
240+
}
241+
242+
// rustdoc-stripper-ignore-next
243+
/// Returns `true` if the type of the value corresponds to `type_`.
244+
///
245+
/// This is equivalent to [`self.type_().is_subtype_of(type_)`](VariantTy::is_subtype_of).
246+
#[inline]
247+
#[doc(alias = "g_variant_is_of_type")]
248+
pub fn is_type(&self, type_: &VariantTy) -> bool {
239249
unsafe {
240250
from_glib(ffi::g_variant_is_of_type(
241251
self.to_glib_none().0,
242-
T::static_variant_type().to_glib_none().0,
252+
type_.to_glib_none().0,
243253
))
244254
}
245255
}
@@ -415,8 +425,20 @@ impl Variant {
415425
pub fn array_from_iter<T: StaticVariantType, I: IntoIterator<Item = Variant>>(
416426
children: I,
417427
) -> Self {
418-
let type_ = T::static_variant_type();
428+
Self::array_from_iter_with_type(&T::static_variant_type(), children)
429+
}
419430

431+
// rustdoc-stripper-ignore-next
432+
/// Creates a new Variant array from children with the specified type.
433+
///
434+
/// # Panics
435+
///
436+
/// This function panics if not all variants are of type `type_`.
437+
#[doc(alias = "g_variant_new_array")]
438+
pub fn array_from_iter_with_type<I: IntoIterator<Item = Variant>>(
439+
type_: &VariantTy,
440+
children: I,
441+
) -> Self {
420442
unsafe {
421443
let mut builder = mem::MaybeUninit::uninit();
422444
ffi::g_variant_builder_init(builder.as_mut_ptr(), type_.as_array().to_glib_none().0);
@@ -426,7 +448,7 @@ impl Variant {
426448
== ffi::GFALSE
427449
{
428450
ffi::g_variant_builder_clear(&mut builder);
429-
assert!(value.is::<T>());
451+
assert!(value.is_type(type_));
430452
}
431453

432454
ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
@@ -471,22 +493,55 @@ impl Variant {
471493
#[doc(alias = "g_variant_new_maybe")]
472494
pub fn from_maybe<T: StaticVariantType>(child: Option<&Variant>) -> Self {
473495
let type_ = T::static_variant_type();
474-
let ptr = match child {
496+
match child {
475497
Some(child) => {
476498
assert_eq!(type_, child.type_());
477499

478-
child.to_glib_none().0
500+
Self::from_some(child)
479501
}
480-
None => std::ptr::null(),
481-
};
502+
None => Self::from_none(&type_),
503+
}
504+
}
505+
506+
// rustdoc-stripper-ignore-next
507+
/// Creates a new maybe Variant from a child.
508+
#[doc(alias = "g_variant_new_maybe")]
509+
pub fn from_some(child: &Variant) -> Self {
482510
unsafe {
483511
from_glib_none(ffi::g_variant_new_maybe(
484-
type_.as_ptr() as *const _,
485-
ptr as *mut ffi::GVariant,
512+
ptr::null(),
513+
child.to_glib_none().0,
486514
))
487515
}
488516
}
489517

518+
// rustdoc-stripper-ignore-next
519+
/// Creates a new maybe Variant with Nothing.
520+
#[doc(alias = "g_variant_new_maybe")]
521+
pub fn from_none(type_: &VariantTy) -> Self {
522+
unsafe {
523+
from_glib_none(ffi::g_variant_new_maybe(
524+
type_.to_glib_none().0,
525+
ptr::null_mut(),
526+
))
527+
}
528+
}
529+
530+
// rustdoc-stripper-ignore-next
531+
/// Extract the value of a maybe Variant.
532+
///
533+
/// Returns the child value, or `None` if the value is Nothing.
534+
///
535+
/// # Panics
536+
///
537+
/// Panics if compiled with `debug_assertions` and the variant is not maybe-typed.
538+
#[inline]
539+
pub fn as_maybe(&self) -> Option<Variant> {
540+
debug_assert!(self.type_().is_maybe());
541+
542+
unsafe { from_glib_full(ffi::g_variant_get_maybe(self.to_glib_none().0)) }
543+
}
544+
490545
// rustdoc-stripper-ignore-next
491546
/// Constructs a new serialized-mode GVariant instance.
492547
#[doc(alias = "g_variant_new_from_bytes")]
@@ -1923,6 +1978,19 @@ mod tests {
19231978
assert_eq!(a.get::<()>(), Some(()));
19241979
}
19251980

1981+
#[test]
1982+
fn test_maybe() {
1983+
assert!(<Option<()>>::static_variant_type().is_maybe());
1984+
let m1 = Some(()).to_variant();
1985+
assert_eq!(m1.type_().as_str(), "m()");
1986+
1987+
assert_eq!(m1.get::<Option<()>>(), Some(Some(())));
1988+
assert!(m1.as_maybe().is_some());
1989+
1990+
let m2 = None::<()>.to_variant();
1991+
assert!(m2.as_maybe().is_none());
1992+
}
1993+
19261994
#[test]
19271995
fn test_btreemap() {
19281996
assert_eq!(

0 commit comments

Comments
 (0)