glib/
value.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! `Value` binding and helper traits.
5//!
6//! The type of a [`Value`](struct.Value.html) is dynamic in that it generally
7//! isn't known at compile time but once created a `Value` can't change its
8//! type.
9//!
10//! [`SendValue`](struct.SendValue.html) is a version of [`Value`](struct.Value.html)
11//! that can only store types that implement `Send` and as such implements `Send` itself. It
12//! dereferences to `Value` so it can be used everywhere `Value` references are accepted.
13//!
14//! Supported types are `bool`, `i8`, `u8`, `i32`, `u32`, `i64`, `u64`, `f32`,
15//! `f64`, `String` and objects (`T: IsA<Object>`).
16//!
17//! # Examples
18//!
19//! ```
20//! use glib::prelude::*; // or `use gtk::prelude::*;`
21//! use glib::Value;
22//!
23//! // Value implement From<&i32>, From<&str> and From<Option<&str>>.
24//! // Another option is the `ToValue` trait.
25//! let mut num = 10.to_value();
26//! let mut hello = Value::from("Hello!");
27//! let none: Option<&str> = None;
28//! let str_none = none.to_value();
29//!
30//! // `is` tests the type of the value.
31//! assert!(num.is::<i32>());
32//! assert!(hello.is::<String>());
33//!
34//! // `get` tries to get an optional value of the specified type
35//! // and returns an `Err` if the type doesn't match.
36//! assert_eq!(num.get(), Ok(10));
37//! assert!(num.get::<String>().is_err());
38//! assert_eq!(hello.get(), Ok(String::from("Hello!")));
39//! assert_eq!(hello.get::<String>(), Ok(String::from("Hello!")));
40//! assert_eq!(str_none.get::<Option<String>>(), Ok(None));
41//! ```
42
43use std::{
44    convert::Infallible,
45    error,
46    ffi::CStr,
47    fmt, mem,
48    num::{NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU32, NonZeroU64, NonZeroU8},
49    ops::Deref,
50    path::{Path, PathBuf},
51    ptr,
52};
53
54use libc::{c_char, c_void};
55
56use crate::{
57    ffi, gobject_ffi,
58    gstring::GString,
59    prelude::*,
60    translate::*,
61    types::{Pointee, Pointer, Type},
62    GStr,
63};
64
65// rustdoc-stripper-ignore-next
66/// A type that can be stored in `Value`s.
67pub trait ValueType: ToValue + for<'a> FromValue<'a> + 'static {
68    // rustdoc-stripper-ignore-next
69    /// Type to get the `Type` from.
70    ///
71    /// This exists only for handling optional types.
72    // FIXME: Should default to Self once associated type defaults are stabilized
73    // https://github.com/rust-lang/rust/issues/29661
74    type Type: StaticType;
75}
76
77// rustdoc-stripper-ignore-next
78/// A type that can be stored in `Value`s and is optional.
79///
80/// These are types were storing an `Option` is valid. Examples are `String` and all object types.
81pub trait ValueTypeOptional:
82    ValueType + ToValueOptional + FromValueOptional<'static> + StaticType
83{
84}
85
86impl<T, C, E> ValueType for Option<T>
87where
88    T: for<'a> FromValue<'a, Checker = C> + ValueTypeOptional + StaticType + 'static,
89    C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
90    E: error::Error + Send + Sized + 'static,
91{
92    type Type = T::Type;
93}
94
95// rustdoc-stripper-ignore-next
96/// Trait for `Value` type checkers.
97pub unsafe trait ValueTypeChecker {
98    type Error: error::Error + Send + Sized + 'static;
99
100    fn check(value: &Value) -> Result<(), Self::Error>;
101}
102
103// rustdoc-stripper-ignore-next
104/// An error returned from the [`get`](struct.Value.html#method.get) function
105/// on a [`Value`](struct.Value.html) for non-optional types an `Option`.
106#[derive(Clone, PartialEq, Eq, Debug)]
107pub struct ValueTypeMismatchError {
108    actual: Type,
109    requested: Type,
110}
111
112impl ValueTypeMismatchError {
113    pub fn new(actual: Type, requested: Type) -> Self {
114        Self { actual, requested }
115    }
116}
117
118impl ValueTypeMismatchError {
119    pub fn actual_type(&self) -> Type {
120        self.actual
121    }
122
123    pub fn requested_type(&self) -> Type {
124        self.requested
125    }
126}
127
128impl fmt::Display for ValueTypeMismatchError {
129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130        write!(
131            f,
132            "Value type mismatch. Actual {:?}, requested {:?}",
133            self.actual_type(),
134            self.requested_type(),
135        )
136    }
137}
138
139impl error::Error for ValueTypeMismatchError {}
140
141impl From<Infallible> for ValueTypeMismatchError {
142    fn from(e: Infallible) -> Self {
143        match e {}
144    }
145}
146
147// rustdoc-stripper-ignore-next
148/// Generic `Value` type checker for types.
149pub struct GenericValueTypeChecker<T>(std::marker::PhantomData<T>);
150
151unsafe impl<T: StaticType> ValueTypeChecker for GenericValueTypeChecker<T> {
152    type Error = ValueTypeMismatchError;
153
154    #[doc(alias = "g_type_check_value_holds")]
155    #[inline]
156    fn check(value: &Value) -> Result<(), Self::Error> {
157        unsafe {
158            if gobject_ffi::g_type_check_value_holds(&value.inner, T::static_type().into_glib())
159                == ffi::GFALSE
160            {
161                Err(ValueTypeMismatchError::new(
162                    Type::from_glib(value.inner.g_type),
163                    T::static_type(),
164                ))
165            } else {
166                Ok(())
167            }
168        }
169    }
170}
171
172pub struct CharTypeChecker();
173unsafe impl ValueTypeChecker for CharTypeChecker {
174    type Error = InvalidCharError;
175
176    #[inline]
177    fn check(value: &Value) -> Result<(), Self::Error> {
178        let v = value.get::<u32>()?;
179        match char::from_u32(v) {
180            Some(_) => Ok(()),
181            None => Err(InvalidCharError::CharConversionError),
182        }
183    }
184}
185
186// rustdoc-stripper-ignore-next
187/// An error returned from the [`get`](struct.Value.html#method.get) function
188/// on a [`Value`](struct.Value.html) for char (which are internally u32) types.
189#[derive(Clone, PartialEq, Eq, Debug)]
190pub enum InvalidCharError {
191    WrongValueType(ValueTypeMismatchError),
192    CharConversionError,
193}
194impl fmt::Display for InvalidCharError {
195    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196        match self {
197            Self::WrongValueType(err) => err.fmt(f),
198            Self::CharConversionError => {
199                write!(f, "couldn't convert to char, invalid u32 contents")
200            }
201        }
202    }
203}
204impl error::Error for InvalidCharError {}
205
206impl From<ValueTypeMismatchError> for InvalidCharError {
207    fn from(err: ValueTypeMismatchError) -> Self {
208        Self::WrongValueType(err)
209    }
210}
211
212impl From<Infallible> for InvalidCharError {
213    fn from(e: Infallible) -> Self {
214        match e {}
215    }
216}
217
218// rustdoc-stripper-ignore-next
219/// An error returned from the [`get`](struct.Value.html#method.get)
220/// function on a [`Value`](struct.Value.html) for optional types.
221#[derive(Clone, PartialEq, Eq, Debug)]
222pub enum ValueTypeMismatchOrNoneError<E: error::Error> {
223    WrongValueType(E),
224    UnexpectedNone,
225}
226
227impl<E: error::Error> fmt::Display for ValueTypeMismatchOrNoneError<E> {
228    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
229        match self {
230            Self::WrongValueType(err) => <E as fmt::Display>::fmt(err, f),
231            Self::UnexpectedNone => write!(f, "Unexpected None",),
232        }
233    }
234}
235
236impl<E: error::Error> error::Error for ValueTypeMismatchOrNoneError<E> {}
237
238impl<E: error::Error> From<E> for ValueTypeMismatchOrNoneError<E> {
239    fn from(err: E) -> Self {
240        Self::WrongValueType(err)
241    }
242}
243
244// rustdoc-stripper-ignore-next
245/// Generic `Value` type checker for optional types.
246pub struct GenericValueTypeOrNoneChecker<T>(std::marker::PhantomData<T>);
247
248unsafe impl<T: StaticType> ValueTypeChecker for GenericValueTypeOrNoneChecker<T> {
249    type Error = ValueTypeMismatchOrNoneError<ValueTypeMismatchError>;
250
251    #[inline]
252    fn check(value: &Value) -> Result<(), Self::Error> {
253        GenericValueTypeChecker::<T>::check(value)?;
254
255        unsafe {
256            // Values are always zero-initialized so even if pointers are only 32 bits then the
257            // whole 64 bit value will be 0 for NULL pointers.
258            if value.inner.data[0].v_uint64 == 0 {
259                return Err(Self::Error::UnexpectedNone);
260            }
261        }
262
263        Ok(())
264    }
265}
266
267// rustdoc-stripper-ignore-next
268/// Trait to retrieve the contained value from a `Value`.
269///
270/// Usually this would not be used directly but from the [`get`](struct.Value.html#method.get)
271/// function on a [`Value`](struct.Value.html)
272pub unsafe trait FromValue<'a>: Sized {
273    // rustdoc-stripper-ignore-next
274    /// Value type checker.
275    type Checker: ValueTypeChecker;
276
277    // rustdoc-stripper-ignore-next
278    /// Get the contained value from a `Value`.
279    ///
280    /// # Safety
281    /// `Self::Checker::check()` must be called first and must not fail.
282    unsafe fn from_value(value: &'a Value) -> Self;
283}
284
285// rustdoc-stripper-ignore-next
286/// Trait for types that implement `FromValue` and are Optional.
287///
288/// This trait is auto-implemented for the appropriate types and is sealed.
289pub trait FromValueOptional<'a>: private::FromValueOptionalSealed<'a> {}
290
291impl<'a, T, C, E> FromValueOptional<'a> for T
292where
293    T: FromValue<'a, Checker = C>,
294    C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
295    E: error::Error + Send + Sized + 'static,
296{
297}
298
299mod private {
300    pub trait FromValueOptionalSealed<'a> {}
301
302    impl<'a, T, C, E> FromValueOptionalSealed<'a> for T
303    where
304        T: super::FromValue<'a, Checker = C>,
305        C: super::ValueTypeChecker<Error = super::ValueTypeMismatchOrNoneError<E>>,
306        E: super::error::Error + Send + Sized + 'static,
307    {
308    }
309}
310
311// rustdoc-stripper-ignore-next
312/// Wrapped `Value` type checker for optional types.
313pub struct ValueTypeOrNoneChecker<T, C, E>(std::marker::PhantomData<(T, C, E)>);
314
315unsafe impl<'a, T, C, E> ValueTypeChecker for ValueTypeOrNoneChecker<T, C, E>
316where
317    T: FromValue<'a, Checker = C> + StaticType,
318    C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
319    E: error::Error + Send + Sized + 'static,
320{
321    type Error = E;
322
323    #[inline]
324    fn check(value: &Value) -> Result<(), Self::Error> {
325        match T::Checker::check(value) {
326            Err(ValueTypeMismatchOrNoneError::UnexpectedNone) => Ok(()),
327            Err(ValueTypeMismatchOrNoneError::WrongValueType(err)) => Err(err),
328            Ok(_) => Ok(()),
329        }
330    }
331}
332
333// rustdoc-stripper-ignore-next
334/// Blanket implementation for all optional types.
335unsafe impl<'a, T, C, E> FromValue<'a> for Option<T>
336where
337    T: FromValue<'a, Checker = C> + StaticType,
338    C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
339    E: error::Error + Send + Sized + 'static,
340{
341    type Checker = ValueTypeOrNoneChecker<T, C, E>;
342
343    #[inline]
344    unsafe fn from_value(value: &'a Value) -> Self {
345        match T::Checker::check(value) {
346            Err(ValueTypeMismatchOrNoneError::UnexpectedNone) => None,
347            Err(ValueTypeMismatchOrNoneError::WrongValueType(_err)) => {
348                // This should've been caught by the caller already.
349                unreachable!();
350            }
351            Ok(_) => Some(T::from_value(value)),
352        }
353    }
354}
355
356// rustdoc-stripper-ignore-next
357/// Trait to convert a value to a `Value`.
358///
359/// Similar to other common conversion traits, the following invariants are guaranteed:
360///
361/// - **Invertibility**: `x.to_value().get().unwrap() == x`. In words, [`FromValue`] is the inverse of `ToValue`.
362/// - **Idempotence**: `x.to_value() == x.to_value().to_value()`.
363///   In words, applying `ToValue` multiple times yields the same result as applying it once.
364///   Idempotence also applies the other way around: `value.get::<Value>()` is a no-op.
365///
366/// There is also the possibility to wrap values within values, see [`BoxedValue`]. All (un-)boxing needs to be done
367/// manually, and will be preserved under the conversion methods.
368///
369/// The conversion methods may cause values to be cloned, which may result in reference counter changes or heap allocations depending
370/// on the source and target type.
371pub trait ToValue {
372    // rustdoc-stripper-ignore-next
373    /// Convert a value to a `Value`.
374    fn to_value(&self) -> Value;
375
376    // rustdoc-stripper-ignore-next
377    /// Returns the type identifier of `self`.
378    ///
379    /// This is the type of the value to be returned by `to_value`.
380    fn value_type(&self) -> Type;
381}
382
383// rustdoc-stripper-ignore-next
384/// Blanket implementation for all references.
385impl<T: ToValue + StaticType> ToValue for &T {
386    #[inline]
387    fn to_value(&self) -> Value {
388        T::to_value(*self)
389    }
390
391    #[inline]
392    fn value_type(&self) -> Type {
393        T::static_type()
394    }
395}
396
397// rustdoc-stripper-ignore-next
398/// Trait to convert an `Option` to a `Value` for optional types.
399pub trait ToValueOptional {
400    // rustdoc-stripper-ignore-next
401    /// Convert an `Option` to a `Value`.
402    #[allow(clippy::wrong_self_convention)]
403    fn to_value_optional(s: Option<&Self>) -> Value;
404}
405
406// rustdoc-stripper-ignore-next
407/// Blanket implementation for all optional types.
408impl<T: ToValueOptional + StaticType> ToValue for Option<T> {
409    #[inline]
410    fn to_value(&self) -> Value {
411        T::to_value_optional(self.as_ref())
412    }
413
414    #[inline]
415    fn value_type(&self) -> Type {
416        T::static_type()
417    }
418}
419
420impl<T: Into<Value> + ToValueOptional> From<Option<T>> for Value {
421    #[inline]
422    fn from(t: Option<T>) -> Self {
423        match t {
424            None => T::to_value_optional(None),
425            Some(t) => t.into(),
426        }
427    }
428}
429
430impl<T: ToValueOptional + StaticType> StaticType for Option<T> {
431    #[inline]
432    fn static_type() -> Type {
433        T::static_type()
434    }
435}
436
437impl<T: ToValueOptional + StaticType + ?Sized> ToValueOptional for &T {
438    #[inline]
439    fn to_value_optional(s: Option<&Self>) -> Value {
440        <T as ToValueOptional>::to_value_optional(s.as_ref().map(|s| **s))
441    }
442}
443
444#[inline]
445unsafe fn copy_value(value: *const gobject_ffi::GValue) -> *mut gobject_ffi::GValue {
446    let copy = ffi::g_malloc0(mem::size_of::<gobject_ffi::GValue>()) as *mut gobject_ffi::GValue;
447    copy_into_value(copy, value);
448    copy
449}
450
451#[inline]
452unsafe fn free_value(value: *mut gobject_ffi::GValue) {
453    clear_value(value);
454    ffi::g_free(value as *mut _);
455}
456
457#[inline]
458unsafe fn init_value(value: *mut gobject_ffi::GValue) {
459    ptr::write(value, mem::zeroed());
460}
461
462#[inline]
463unsafe fn copy_into_value(dest: *mut gobject_ffi::GValue, src: *const gobject_ffi::GValue) {
464    gobject_ffi::g_value_init(dest, (*src).g_type);
465    gobject_ffi::g_value_copy(src, dest);
466}
467
468#[inline]
469unsafe fn clear_value(value: *mut gobject_ffi::GValue) {
470    // Before GLib 2.48, unsetting a zeroed GValue would give critical warnings
471    // https://bugzilla.gnome.org/show_bug.cgi?id=755766
472    if (*value).g_type != gobject_ffi::G_TYPE_INVALID {
473        gobject_ffi::g_value_unset(value);
474    }
475}
476
477// TODO: Should use impl !Send for Value {} once stable
478crate::wrapper! {
479    // rustdoc-stripper-ignore-next
480    /// A generic value capable of carrying various types.
481    ///
482    /// Once created the type of the value can't be changed.
483    ///
484    /// Some types (e.g. `String` and objects) support `None` values while others
485    /// (e.g. numeric types) don't.
486    ///
487    /// `Value` does not implement the `Send` trait, but [`SendValue`](struct.SendValue.html) can be
488    /// used instead.
489    ///
490    /// See the [module documentation](index.html) for more details.
491    #[doc(alias = "GValue")]
492    pub struct Value(BoxedInline<gobject_ffi::GValue>);
493
494    match fn {
495        copy => |ptr| copy_value(ptr),
496        free => |ptr| free_value(ptr),
497        init => |ptr| init_value(ptr),
498        copy_into => |dest, src| copy_into_value(dest, src),
499        clear => |ptr| clear_value(ptr),
500    }
501}
502
503impl Value {
504    // rustdoc-stripper-ignore-next
505    /// Creates a new `Value` that is initialized with `type_`.
506    ///
507    /// # Panics
508    ///
509    /// If `type_` can't be stored in a `Value` this function panics.
510    pub fn from_type(type_: Type) -> Self {
511        unsafe {
512            assert_eq!(
513                gobject_ffi::g_type_check_is_value_type(type_.into_glib()),
514                ffi::GTRUE
515            );
516            Self::from_type_unchecked(type_)
517        }
518    }
519
520    // rustdoc-stripper-ignore-next
521    /// Creates a new `Value` that is initialized with `type_`.
522    ///
523    /// # SAFETY
524    ///
525    /// This must be called with a valid `type_` that can be stored in `Value`s.
526    #[inline]
527    pub unsafe fn from_type_unchecked(type_: Type) -> Self {
528        unsafe {
529            let mut value = Value::uninitialized();
530            gobject_ffi::g_value_init(value.to_glib_none_mut().0, type_.into_glib());
531            value
532        }
533    }
534
535    // rustdoc-stripper-ignore-next
536    /// Creates a new `Value` that is initialized for a given `ValueType`.
537    #[inline]
538    pub fn for_value_type<T: ValueType>() -> Self {
539        unsafe { Value::from_type_unchecked(T::Type::static_type()) }
540    }
541
542    // rustdoc-stripper-ignore-next
543    /// Creates a new `String`-typed `Value` from a `'static` string.
544    #[inline]
545    #[doc(alias = "g_value_set_static_string")]
546    pub fn from_static_str(s: &'static GStr) -> Self {
547        unsafe {
548            let mut v = Self::from_type_unchecked(Type::STRING);
549            gobject_ffi::g_value_set_static_string(v.to_glib_none_mut().0, s.as_ptr());
550            v
551        }
552    }
553
554    #[cfg(feature = "v2_66")]
555    #[cfg_attr(docsrs, doc(cfg(feature = "v2_66")))]
556    // rustdoc-stripper-ignore-next
557    /// Creates a new `String`-typed `Value` from a `'static` string that is also assumed to be
558    /// interned.
559    #[inline]
560    #[doc(alias = "g_value_set_interned_string")]
561    pub fn from_interned_str(s: &'static GStr) -> Self {
562        unsafe {
563            let mut v = Self::from_type_unchecked(Type::STRING);
564            gobject_ffi::g_value_set_interned_string(v.to_glib_none_mut().0, s.as_ptr());
565            v
566        }
567    }
568
569    // rustdoc-stripper-ignore-next
570    /// Tries to get a value of type `T`.
571    ///
572    /// Returns `Ok` if the type is correct.
573    #[inline]
574    pub fn get<'a, T>(
575        &'a self,
576    ) -> Result<T, <<T as FromValue<'a>>::Checker as ValueTypeChecker>::Error>
577    where
578        T: FromValue<'a>,
579    {
580        unsafe {
581            T::Checker::check(self)?;
582            Ok(T::from_value(self))
583        }
584    }
585
586    // rustdoc-stripper-ignore-next
587    /// Tries to get a value of an owned type `T`.
588    #[inline]
589    pub fn get_owned<T>(
590        &self,
591    ) -> Result<T, <<T as FromValue<'_>>::Checker as ValueTypeChecker>::Error>
592    where
593        T: for<'b> FromValue<'b> + 'static,
594    {
595        unsafe {
596            T::Checker::check(self)?;
597            Ok(FromValue::from_value(self))
598        }
599    }
600
601    // rustdoc-stripper-ignore-next
602    /// Returns `true` if the type of the value corresponds to `T`
603    /// or is a sub-type of `T`.
604    #[inline]
605    pub fn is<T: StaticType>(&self) -> bool {
606        self.is_type(T::static_type())
607    }
608
609    // rustdoc-stripper-ignore-next
610    /// Returns `true` if the type of the value corresponds to `type_`
611    /// or is a sub-type of `type_`.
612    #[inline]
613    pub fn is_type(&self, type_: Type) -> bool {
614        self.type_().is_a(type_)
615    }
616
617    // rustdoc-stripper-ignore-next
618    /// Returns the type of the value.
619    #[inline]
620    pub fn type_(&self) -> Type {
621        unsafe { from_glib(self.inner.g_type) }
622    }
623
624    // rustdoc-stripper-ignore-next
625    /// Returns whether `Value`s of type `src` can be transformed to type `dst`.
626    #[doc(alias = "g_value_type_transformable")]
627    pub fn type_transformable(src: Type, dst: Type) -> bool {
628        unsafe {
629            from_glib(gobject_ffi::g_value_type_transformable(
630                src.into_glib(),
631                dst.into_glib(),
632            ))
633        }
634    }
635
636    // rustdoc-stripper-ignore-next
637    /// Tries to transform the value into a value of the target type
638    #[doc(alias = "g_value_transform")]
639    pub fn transform<T: ValueType>(&self) -> Result<Value, crate::BoolError> {
640        self.transform_with_type(T::Type::static_type())
641    }
642
643    // rustdoc-stripper-ignore-next
644    /// Tries to transform the value into a value of the target type
645    #[doc(alias = "g_value_transform")]
646    pub fn transform_with_type(&self, type_: Type) -> Result<Value, crate::BoolError> {
647        unsafe {
648            let mut dest = Value::from_type(type_);
649            if from_glib(gobject_ffi::g_value_transform(
650                self.to_glib_none().0,
651                dest.to_glib_none_mut().0,
652            )) {
653                Ok(dest)
654            } else {
655                Err(crate::bool_error!(
656                    "Can't transform value of type '{}' into '{}'",
657                    self.type_(),
658                    type_
659                ))
660            }
661        }
662    }
663
664    // rustdoc-stripper-ignore-next
665    /// Consumes `Value` and returns the corresponding `GValue`.
666    #[inline]
667    pub fn into_raw(self) -> gobject_ffi::GValue {
668        unsafe {
669            let s = mem::ManuallyDrop::new(self);
670            ptr::read(&s.inner)
671        }
672    }
673
674    // rustdoc-stripper-ignore-next
675    /// Converts a `Value` into a `SendValue`. This fails if `self` does not store a value of type
676    /// `T`. It is required for `T` to be `Send` to call this function.
677    #[inline]
678    pub fn try_into_send_value<T: Send + StaticType>(self) -> Result<SendValue, Self> {
679        if self.type_().is_a(T::static_type()) {
680            unsafe { Ok(SendValue::unsafe_from(self.into_raw())) }
681        } else {
682            Err(self)
683        }
684    }
685
686    // rustdoc-stripper-ignore-next
687    /// Converts a `Value` into a `SendValue`.
688    ///
689    /// # Safety
690    ///
691    /// The type of the value contained in `self` must be `Send`.
692    #[inline]
693    pub unsafe fn into_send_value(self) -> SendValue {
694        SendValue::unsafe_from(self.into_raw())
695    }
696
697    fn content_debug_string(&self) -> GString {
698        unsafe { from_glib_full(gobject_ffi::g_strdup_value_contents(self.to_glib_none().0)) }
699    }
700}
701
702impl fmt::Debug for Value {
703    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
704        write!(f, "({}) {}", self.type_(), self.content_debug_string())
705    }
706}
707
708impl<'a, T: ?Sized + ToValue> From<&'a T> for Value {
709    #[inline]
710    fn from(value: &'a T) -> Self {
711        value.to_value()
712    }
713}
714
715impl From<SendValue> for Value {
716    #[inline]
717    fn from(value: SendValue) -> Self {
718        unsafe { Value::unsafe_from(value.into_raw()) }
719    }
720}
721
722impl ToValue for Value {
723    #[inline]
724    fn to_value(&self) -> Value {
725        self.clone()
726    }
727
728    #[inline]
729    fn value_type(&self) -> Type {
730        self.type_()
731    }
732}
733
734impl ToValue for &Value {
735    #[inline]
736    fn to_value(&self) -> Value {
737        (*self).clone()
738    }
739
740    #[inline]
741    fn value_type(&self) -> Type {
742        self.type_()
743    }
744}
745
746pub struct NopChecker;
747
748unsafe impl ValueTypeChecker for NopChecker {
749    type Error = Infallible;
750
751    #[inline]
752    fn check(_value: &Value) -> Result<(), Self::Error> {
753        Ok(())
754    }
755}
756
757unsafe impl<'a> FromValue<'a> for Value {
758    type Checker = NopChecker;
759
760    #[inline]
761    unsafe fn from_value(value: &'a Value) -> Self {
762        value.clone()
763    }
764}
765
766unsafe impl<'a> FromValue<'a> for &'a Value {
767    type Checker = NopChecker;
768
769    #[inline]
770    unsafe fn from_value(value: &'a Value) -> Self {
771        value
772    }
773}
774
775impl ToValue for SendValue {
776    #[inline]
777    fn to_value(&self) -> Value {
778        unsafe { from_glib_none(self.to_glib_none().0) }
779    }
780
781    #[inline]
782    fn value_type(&self) -> Type {
783        self.type_()
784    }
785}
786
787impl ToValue for &SendValue {
788    #[inline]
789    fn to_value(&self) -> Value {
790        unsafe { from_glib_none(self.to_glib_none().0) }
791    }
792
793    #[inline]
794    fn value_type(&self) -> Type {
795        self.type_()
796    }
797}
798
799impl StaticType for BoxedValue {
800    #[inline]
801    fn static_type() -> Type {
802        unsafe { from_glib(gobject_ffi::g_value_get_type()) }
803    }
804}
805
806crate::wrapper! {
807    // rustdoc-stripper-ignore-next
808    /// A version of [`Value`](struct.Value.html) for storing `Send` types, that implements Send
809    /// itself.
810    ///
811    /// See the [module documentation](index.html) for more details.
812    #[doc(alias = "GValue")]
813    pub struct SendValue(BoxedInline<gobject_ffi::GValue>);
814
815    match fn {
816        copy => |ptr| copy_value(ptr),
817        free => |ptr| free_value(ptr),
818        init => |ptr| init_value(ptr),
819        copy_into => |dest, src| copy_into_value(dest, src),
820        clear => |ptr| clear_value(ptr),
821    }
822}
823
824unsafe impl Send for SendValue {}
825
826impl SendValue {
827    // rustdoc-stripper-ignore-next
828    /// Consumes `SendValue` and returns the corresponding `GValue`.
829    #[inline]
830    pub fn into_raw(self) -> gobject_ffi::GValue {
831        unsafe {
832            let s = mem::ManuallyDrop::new(self);
833            ptr::read(&s.inner)
834        }
835    }
836    #[inline]
837    pub fn from_owned<T: Send + Into<Value>>(t: T) -> Self {
838        unsafe { Self::unsafe_from(t.into().into_raw()) }
839    }
840}
841
842impl fmt::Debug for SendValue {
843    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
844        write!(f, "({}) {}", self.type_(), self.content_debug_string())
845    }
846}
847
848impl Deref for SendValue {
849    type Target = Value;
850
851    #[inline]
852    fn deref(&self) -> &Value {
853        unsafe { &*(self as *const SendValue as *const Value) }
854    }
855}
856
857impl<'a, T: ?Sized + ToSendValue> From<&'a T> for SendValue {
858    #[inline]
859    fn from(value: &'a T) -> Self {
860        value.to_send_value()
861    }
862}
863
864// rustdoc-stripper-ignore-next
865/// Converts to `SendValue`.
866pub trait ToSendValue: Send + ToValue {
867    // rustdoc-stripper-ignore-next
868    /// Returns a `SendValue` clone of `self`.
869    fn to_send_value(&self) -> SendValue;
870}
871
872impl<T: Send + ToValue + ?Sized> ToSendValue for T {
873    #[inline]
874    fn to_send_value(&self) -> SendValue {
875        unsafe { SendValue::unsafe_from(self.to_value().into_raw()) }
876    }
877}
878
879unsafe impl<'a> FromValue<'a> for &'a str {
880    type Checker = GenericValueTypeOrNoneChecker<Self>;
881
882    #[inline]
883    unsafe fn from_value(value: &'a Value) -> Self {
884        let ptr = gobject_ffi::g_value_get_string(value.to_glib_none().0);
885        CStr::from_ptr(ptr).to_str().expect("Invalid UTF-8")
886    }
887}
888
889impl ToValue for str {
890    fn to_value(&self) -> Value {
891        unsafe {
892            let mut value = Value::for_value_type::<String>();
893
894            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
895
896            value
897        }
898    }
899
900    fn value_type(&self) -> Type {
901        String::static_type()
902    }
903}
904
905impl ToValue for &str {
906    fn to_value(&self) -> Value {
907        (*self).to_value()
908    }
909
910    fn value_type(&self) -> Type {
911        String::static_type()
912    }
913}
914
915impl ToValueOptional for str {
916    fn to_value_optional(s: Option<&Self>) -> Value {
917        let mut value = Value::for_value_type::<String>();
918        unsafe {
919            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
920        }
921
922        value
923    }
924}
925
926impl ValueType for String {
927    type Type = String;
928}
929
930impl ValueTypeOptional for String {}
931
932unsafe impl<'a> FromValue<'a> for String {
933    type Checker = GenericValueTypeOrNoneChecker<Self>;
934
935    unsafe fn from_value(value: &'a Value) -> Self {
936        String::from(<&str>::from_value(value))
937    }
938}
939
940impl ToValue for String {
941    fn to_value(&self) -> Value {
942        <&str>::to_value(&self.as_str())
943    }
944
945    fn value_type(&self) -> Type {
946        String::static_type()
947    }
948}
949
950impl From<String> for Value {
951    #[inline]
952    fn from(s: String) -> Self {
953        s.to_value()
954    }
955}
956
957impl ToValueOptional for String {
958    fn to_value_optional(s: Option<&Self>) -> Value {
959        <str>::to_value_optional(s.as_ref().map(|s| s.as_str()))
960    }
961}
962
963impl ValueType for Box<str> {
964    type Type = String;
965}
966
967impl ValueTypeOptional for Box<str> {}
968
969unsafe impl<'a> FromValue<'a> for Box<str> {
970    type Checker = GenericValueTypeOrNoneChecker<Self>;
971
972    unsafe fn from_value(value: &'a Value) -> Self {
973        Box::<str>::from(<&str>::from_value(value))
974    }
975}
976
977impl StaticType for Box<str> {
978    fn static_type() -> Type {
979        String::static_type()
980    }
981}
982
983impl ToValue for Box<str> {
984    fn to_value(&self) -> Value {
985        <&str>::to_value(&self.as_ref())
986    }
987
988    fn value_type(&self) -> Type {
989        String::static_type()
990    }
991}
992
993impl From<Box<str>> for Value {
994    #[inline]
995    fn from(s: Box<str>) -> Self {
996        s.to_value()
997    }
998}
999
1000impl ToValueOptional for Box<str> {
1001    fn to_value_optional(s: Option<&Self>) -> Value {
1002        <str>::to_value_optional(s.as_ref().map(|s| s.as_ref()))
1003    }
1004}
1005
1006impl ValueType for Vec<String> {
1007    type Type = Vec<String>;
1008}
1009
1010unsafe impl<'a> FromValue<'a> for Vec<String> {
1011    type Checker = GenericValueTypeChecker<Self>;
1012
1013    unsafe fn from_value(value: &'a Value) -> Self {
1014        let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
1015        FromGlibPtrContainer::from_glib_none(ptr)
1016    }
1017}
1018
1019impl ToValue for Vec<String> {
1020    fn to_value(&self) -> Value {
1021        unsafe {
1022            let mut value = Value::for_value_type::<Self>();
1023            let ptr: *mut *mut c_char = self.to_glib_full();
1024            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1025            value
1026        }
1027    }
1028
1029    fn value_type(&self) -> Type {
1030        <Vec<String>>::static_type()
1031    }
1032}
1033
1034impl From<Vec<String>> for Value {
1035    #[inline]
1036    fn from(s: Vec<String>) -> Self {
1037        s.to_value()
1038    }
1039}
1040
1041impl ToValue for [&'_ str] {
1042    fn to_value(&self) -> Value {
1043        unsafe {
1044            let mut value = Value::for_value_type::<Vec<String>>();
1045            let ptr: *mut *mut c_char = self.to_glib_full();
1046            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1047            value
1048        }
1049    }
1050
1051    fn value_type(&self) -> Type {
1052        <Vec<String>>::static_type()
1053    }
1054}
1055
1056impl ToValue for &'_ [&'_ str] {
1057    fn to_value(&self) -> Value {
1058        unsafe {
1059            let mut value = Value::for_value_type::<Vec<String>>();
1060            let ptr: *mut *mut c_char = self.to_glib_full();
1061            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1062            value
1063        }
1064    }
1065
1066    fn value_type(&self) -> Type {
1067        <Vec<String>>::static_type()
1068    }
1069}
1070
1071impl ToValue for Path {
1072    fn to_value(&self) -> Value {
1073        unsafe {
1074            let mut value = Value::for_value_type::<PathBuf>();
1075
1076            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
1077
1078            value
1079        }
1080    }
1081
1082    fn value_type(&self) -> Type {
1083        PathBuf::static_type()
1084    }
1085}
1086
1087impl ToValue for &Path {
1088    fn to_value(&self) -> Value {
1089        (*self).to_value()
1090    }
1091
1092    fn value_type(&self) -> Type {
1093        PathBuf::static_type()
1094    }
1095}
1096
1097impl ToValueOptional for Path {
1098    fn to_value_optional(s: Option<&Self>) -> Value {
1099        let mut value = Value::for_value_type::<PathBuf>();
1100        unsafe {
1101            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
1102        }
1103
1104        value
1105    }
1106}
1107
1108impl ValueType for PathBuf {
1109    type Type = PathBuf;
1110}
1111
1112impl ValueTypeOptional for PathBuf {}
1113
1114unsafe impl<'a> FromValue<'a> for PathBuf {
1115    type Checker = GenericValueTypeOrNoneChecker<Self>;
1116
1117    unsafe fn from_value(value: &'a Value) -> Self {
1118        from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0))
1119    }
1120}
1121
1122impl ToValue for PathBuf {
1123    fn to_value(&self) -> Value {
1124        <&Path>::to_value(&self.as_path())
1125    }
1126
1127    fn value_type(&self) -> Type {
1128        PathBuf::static_type()
1129    }
1130}
1131
1132impl From<PathBuf> for Value {
1133    #[inline]
1134    fn from(s: PathBuf) -> Self {
1135        s.to_value()
1136    }
1137}
1138
1139impl ToValueOptional for PathBuf {
1140    fn to_value_optional(s: Option<&Self>) -> Value {
1141        <Path>::to_value_optional(s.as_ref().map(|s| s.as_path()))
1142    }
1143}
1144
1145impl ValueType for bool {
1146    type Type = Self;
1147}
1148
1149unsafe impl<'a> FromValue<'a> for bool {
1150    type Checker = GenericValueTypeChecker<Self>;
1151
1152    #[inline]
1153    unsafe fn from_value(value: &'a Value) -> Self {
1154        from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0))
1155    }
1156}
1157
1158impl ToValue for bool {
1159    #[inline]
1160    fn to_value(&self) -> Value {
1161        let mut value = Value::for_value_type::<Self>();
1162        unsafe {
1163            gobject_ffi::g_value_set_boolean(&mut value.inner, self.into_glib());
1164        }
1165        value
1166    }
1167
1168    #[inline]
1169    fn value_type(&self) -> Type {
1170        Self::static_type()
1171    }
1172}
1173
1174impl From<bool> for Value {
1175    #[inline]
1176    fn from(v: bool) -> Self {
1177        v.to_value()
1178    }
1179}
1180
1181impl ValueType for Pointer {
1182    type Type = Self;
1183}
1184
1185unsafe impl<'a> FromValue<'a> for Pointer {
1186    type Checker = GenericValueTypeChecker<Self>;
1187
1188    #[inline]
1189    unsafe fn from_value(value: &'a Value) -> Self {
1190        gobject_ffi::g_value_get_pointer(value.to_glib_none().0)
1191    }
1192}
1193
1194impl ToValue for Pointer {
1195    #[inline]
1196    fn to_value(&self) -> Value {
1197        let mut value = Value::for_value_type::<Self>();
1198        unsafe {
1199            gobject_ffi::g_value_set_pointer(&mut value.inner, *self);
1200        }
1201        value
1202    }
1203
1204    #[inline]
1205    fn value_type(&self) -> Type {
1206        <<Self as ValueType>::Type as StaticType>::static_type()
1207    }
1208}
1209
1210impl From<Pointer> for Value {
1211    #[inline]
1212    fn from(v: Pointer) -> Self {
1213        v.to_value()
1214    }
1215}
1216
1217impl ValueType for ptr::NonNull<Pointee> {
1218    type Type = Pointer;
1219}
1220
1221unsafe impl<'a> FromValue<'a> for ptr::NonNull<Pointee> {
1222    type Checker = GenericValueTypeOrNoneChecker<Self>;
1223
1224    #[inline]
1225    unsafe fn from_value(value: &'a Value) -> Self {
1226        ptr::NonNull::new_unchecked(Pointer::from_value(value))
1227    }
1228}
1229
1230impl ToValue for ptr::NonNull<Pointee> {
1231    #[inline]
1232    fn to_value(&self) -> Value {
1233        self.as_ptr().to_value()
1234    }
1235
1236    #[inline]
1237    fn value_type(&self) -> Type {
1238        <<Self as ValueType>::Type as StaticType>::static_type()
1239    }
1240}
1241
1242impl From<ptr::NonNull<Pointee>> for Value {
1243    #[inline]
1244    fn from(v: ptr::NonNull<Pointee>) -> Self {
1245        v.to_value()
1246    }
1247}
1248
1249impl ToValueOptional for ptr::NonNull<Pointee> {
1250    #[inline]
1251    fn to_value_optional(p: Option<&Self>) -> Value {
1252        p.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()).to_value()
1253    }
1254}
1255
1256macro_rules! numeric {
1257    ($name:ty, $get:expr, $set:expr) => {
1258        impl ValueType for $name {
1259            type Type = Self;
1260        }
1261
1262        unsafe impl<'a> FromValue<'a> for $name {
1263            type Checker = GenericValueTypeChecker<Self>;
1264
1265            #[inline]
1266            #[allow(clippy::redundant_closure_call)]
1267            unsafe fn from_value(value: &'a Value) -> Self {
1268                $get(value.to_glib_none().0)
1269            }
1270        }
1271
1272        impl ToValue for $name {
1273            #[inline]
1274            #[allow(clippy::redundant_closure_call)]
1275            fn to_value(&self) -> Value {
1276                let mut value = Value::for_value_type::<Self>();
1277                unsafe {
1278                    $set(&mut value.inner, *self);
1279                }
1280                value
1281            }
1282
1283            #[inline]
1284            fn value_type(&self) -> Type {
1285                Self::static_type()
1286            }
1287        }
1288
1289        impl From<$name> for Value {
1290            #[inline]
1291            fn from(v: $name) -> Self {
1292                v.to_value()
1293            }
1294        }
1295    };
1296}
1297macro_rules! not_zero {
1298    ($name:ty, $num:ty) => {
1299        impl ValueType for $name {
1300            type Type = $name;
1301        }
1302
1303        unsafe impl<'a> FromValue<'a> for $name {
1304            // Works because it returns `UnexpectedNone` if the value is NULL
1305            // by checking it against `0`.
1306            type Checker = GenericValueTypeOrNoneChecker<Self>;
1307
1308            #[inline]
1309            unsafe fn from_value(value: &'a Value) -> Self {
1310                let res = <$num>::from_value(value);
1311                Self::try_from(res).unwrap()
1312            }
1313        }
1314
1315        impl ToValue for $name {
1316            #[inline]
1317            fn to_value(&self) -> Value {
1318                <$num>::to_value(&<$num>::from(*self))
1319            }
1320
1321            #[inline]
1322            fn value_type(&self) -> Type {
1323                Self::static_type()
1324            }
1325        }
1326
1327        impl From<$name> for Value {
1328            #[inline]
1329            fn from(v: $name) -> Self {
1330                v.to_value()
1331            }
1332        }
1333
1334        impl ToValueOptional for $name {
1335            fn to_value_optional(s: Option<&Self>) -> Value {
1336                match s {
1337                    Some(x) => x.to_value(),
1338                    None => <$num>::to_value(&0),
1339                }
1340            }
1341        }
1342    };
1343}
1344
1345numeric!(
1346    i8,
1347    gobject_ffi::g_value_get_schar,
1348    gobject_ffi::g_value_set_schar
1349);
1350not_zero!(NonZeroI8, i8);
1351numeric!(
1352    u8,
1353    gobject_ffi::g_value_get_uchar,
1354    gobject_ffi::g_value_set_uchar
1355);
1356not_zero!(NonZeroU8, u8);
1357numeric!(
1358    i32,
1359    gobject_ffi::g_value_get_int,
1360    gobject_ffi::g_value_set_int
1361);
1362not_zero!(NonZeroI32, i32);
1363numeric!(
1364    u32,
1365    gobject_ffi::g_value_get_uint,
1366    gobject_ffi::g_value_set_uint
1367);
1368not_zero!(NonZeroU32, u32);
1369numeric!(
1370    i64,
1371    gobject_ffi::g_value_get_int64,
1372    gobject_ffi::g_value_set_int64
1373);
1374not_zero!(NonZeroI64, i64);
1375numeric!(
1376    u64,
1377    gobject_ffi::g_value_get_uint64,
1378    gobject_ffi::g_value_set_uint64
1379);
1380not_zero!(NonZeroU64, u64);
1381numeric!(
1382    crate::ILong,
1383    |v| gobject_ffi::g_value_get_long(v).into(),
1384    |v, i: crate::ILong| gobject_ffi::g_value_set_long(v, i.0)
1385);
1386numeric!(
1387    crate::ULong,
1388    |v| gobject_ffi::g_value_get_ulong(v).into(),
1389    |v, i: crate::ULong| gobject_ffi::g_value_set_ulong(v, i.0)
1390);
1391numeric!(
1392    f32,
1393    gobject_ffi::g_value_get_float,
1394    gobject_ffi::g_value_set_float
1395);
1396numeric!(
1397    f64,
1398    gobject_ffi::g_value_get_double,
1399    gobject_ffi::g_value_set_double
1400);
1401
1402impl ValueType for char {
1403    type Type = u32;
1404}
1405
1406unsafe impl<'a> FromValue<'a> for char {
1407    type Checker = CharTypeChecker;
1408
1409    #[inline]
1410    unsafe fn from_value(value: &'a Value) -> Self {
1411        let res: u32 = gobject_ffi::g_value_get_uint(value.to_glib_none().0);
1412        // safe because the check is done by `Self::Checker`
1413        char::from_u32_unchecked(res)
1414    }
1415}
1416
1417impl ToValue for char {
1418    #[inline]
1419    fn to_value(&self) -> Value {
1420        let mut value = Value::for_value_type::<Self>();
1421        unsafe {
1422            gobject_ffi::g_value_set_uint(&mut value.inner, *self as u32);
1423        }
1424        value
1425    }
1426
1427    #[inline]
1428    fn value_type(&self) -> Type {
1429        crate::Type::U32
1430    }
1431}
1432
1433impl From<char> for Value {
1434    #[inline]
1435    fn from(v: char) -> Self {
1436        v.to_value()
1437    }
1438}
1439
1440// rustdoc-stripper-ignore-next
1441/// A [`Value`] containing another [`Value`].
1442pub struct BoxedValue(pub Value);
1443
1444impl Deref for BoxedValue {
1445    type Target = Value;
1446
1447    #[inline]
1448    fn deref(&self) -> &Value {
1449        &self.0
1450    }
1451}
1452
1453impl ValueType for BoxedValue {
1454    type Type = BoxedValue;
1455}
1456
1457impl ValueTypeOptional for BoxedValue {}
1458
1459unsafe impl<'a> FromValue<'a> for BoxedValue {
1460    type Checker = GenericValueTypeOrNoneChecker<Self>;
1461
1462    #[inline]
1463    unsafe fn from_value(value: &'a Value) -> Self {
1464        let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1465        BoxedValue(from_glib_none(ptr as *const gobject_ffi::GValue))
1466    }
1467}
1468
1469impl ToValue for BoxedValue {
1470    #[inline]
1471    fn to_value(&self) -> Value {
1472        unsafe {
1473            let mut value = Value::for_value_type::<BoxedValue>();
1474
1475            gobject_ffi::g_value_set_boxed(
1476                value.to_glib_none_mut().0,
1477                self.0.to_glib_none().0 as ffi::gconstpointer,
1478            );
1479
1480            value
1481        }
1482    }
1483
1484    #[inline]
1485    fn value_type(&self) -> Type {
1486        BoxedValue::static_type()
1487    }
1488}
1489
1490impl From<BoxedValue> for Value {
1491    #[inline]
1492    fn from(v: BoxedValue) -> Self {
1493        unsafe {
1494            let mut value = Value::for_value_type::<BoxedValue>();
1495
1496            gobject_ffi::g_value_take_boxed(
1497                value.to_glib_none_mut().0,
1498                v.0.to_glib_full() as ffi::gconstpointer,
1499            );
1500
1501            value
1502        }
1503    }
1504}
1505
1506impl ToValueOptional for BoxedValue {
1507    #[inline]
1508    fn to_value_optional(s: Option<&Self>) -> Value {
1509        let mut value = Value::for_value_type::<Self>();
1510        unsafe {
1511            gobject_ffi::g_value_set_boxed(
1512                value.to_glib_none_mut().0,
1513                s.map(|s| &s.0).to_glib_none().0 as ffi::gconstpointer,
1514            );
1515        }
1516
1517        value
1518    }
1519}
1520
1521#[cfg(test)]
1522mod tests {
1523    use std::num::NonZeroI32;
1524
1525    use super::*;
1526
1527    #[test]
1528    fn test_send_value() {
1529        use std::thread;
1530
1531        let v = SendValue::from(&1i32);
1532
1533        // Must compile, while it must fail with Value
1534        thread::spawn(move || drop(v)).join().unwrap();
1535    }
1536
1537    #[test]
1538    fn test_strv() {
1539        let v = ["123", "456"].to_value();
1540        assert_eq!(
1541            v.get::<Vec<GString>>(),
1542            Ok(vec![GString::from("123"), GString::from("456")])
1543        );
1544
1545        let v = vec![String::from("123"), String::from("456")].to_value();
1546        assert_eq!(
1547            v.get::<Vec<GString>>(),
1548            Ok(vec![GString::from("123"), GString::from("456")])
1549        );
1550    }
1551
1552    #[test]
1553    fn test_from_to_value() {
1554        let v = 123.to_value();
1555        assert_eq!(v.get(), Ok(123));
1556        assert_eq!(
1557            v.get::<&str>(),
1558            Err(ValueTypeMismatchError::new(Type::I32, Type::STRING).into())
1559        );
1560        assert_eq!(
1561            v.get::<bool>(),
1562            Err(ValueTypeMismatchError::new(Type::I32, Type::BOOL))
1563        );
1564
1565        // Check if &str / str / Option<&str> etc can be converted and retrieved
1566        let v_str = "test".to_value();
1567        assert_eq!(v_str.get::<&str>(), Ok("test"));
1568        assert_eq!(v_str.get::<Option<&str>>(), Ok(Some("test")));
1569        assert_eq!(
1570            v_str.get::<i32>(),
1571            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1572        );
1573
1574        let some_v = Some("test").to_value();
1575        assert_eq!(some_v.get::<&str>(), Ok("test"));
1576        assert_eq!(some_v.get_owned::<String>(), Ok("test".to_string()));
1577        assert_eq!(
1578            some_v.get_owned::<Option<String>>(),
1579            Ok(Some("test".to_string()))
1580        );
1581        assert_eq!(some_v.get::<Option<&str>>(), Ok(Some("test")));
1582        assert_eq!(
1583            some_v.get::<i32>(),
1584            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1585        );
1586
1587        let none_str: Option<&str> = None;
1588        let none_v = none_str.to_value();
1589        assert_eq!(none_v.get::<Option<&str>>(), Ok(None));
1590        assert_eq!(
1591            none_v.get::<i32>(),
1592            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1593        );
1594
1595        // Check if owned T and Option<T> can be converted and retrieved
1596        let v_str = String::from("test").to_value();
1597        assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1598        assert_eq!(
1599            v_str.get::<Option<String>>(),
1600            Ok(Some(String::from("test")))
1601        );
1602        assert_eq!(
1603            v_str.get::<i32>(),
1604            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1605        );
1606
1607        let some_v = Some(String::from("test")).to_value();
1608        assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1609        assert_eq!(
1610            some_v.get::<Option<String>>(),
1611            Ok(Some(String::from("test")))
1612        );
1613        assert_eq!(
1614            some_v.get::<i32>(),
1615            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1616        );
1617
1618        let none_str: Option<String> = None;
1619        let none_v = none_str.to_value();
1620        assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1621        assert_eq!(
1622            none_v.get::<i32>(),
1623            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1624        );
1625
1626        let c_v = 'c'.to_value();
1627        assert_eq!(c_v.get::<char>(), Ok('c'));
1628
1629        let c_v = 0xFFFFFFFFu32.to_value();
1630        assert_eq!(
1631            c_v.get::<char>(),
1632            Err(InvalidCharError::CharConversionError)
1633        );
1634
1635        // Check if &T and Option<&T> can be converted and retrieved
1636        let v_str = String::from("test").to_value();
1637        assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1638        assert_eq!(
1639            v_str.get::<Option<String>>(),
1640            Ok(Some(String::from("test")))
1641        );
1642        assert_eq!(
1643            v_str.get::<i32>(),
1644            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1645        );
1646
1647        let some_v = Some(&String::from("test")).to_value();
1648        assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1649        assert_eq!(
1650            some_v.get::<Option<String>>(),
1651            Ok(Some(String::from("test")))
1652        );
1653        assert_eq!(
1654            some_v.get::<i32>(),
1655            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1656        );
1657
1658        let none_str: Option<&String> = None;
1659        let none_v = none_str.to_value();
1660        assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1661        assert_eq!(
1662            none_v.get::<i32>(),
1663            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1664        );
1665
1666        // Check handling of NonZeroT
1667        let v = NonZeroI32::new(123).unwrap().to_value();
1668        assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1669
1670        let v = 123i32.to_value();
1671        assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1672
1673        let v = 0i32.to_value();
1674        assert_eq!(
1675            v.get::<NonZeroI32>(),
1676            Err(ValueTypeMismatchOrNoneError::UnexpectedNone)
1677        );
1678
1679        assert_eq!(v.get::<Option<NonZeroI32>>(), Ok(None));
1680    }
1681
1682    #[test]
1683    fn test_transform() {
1684        let v = 123.to_value();
1685        let v2 = v
1686            .transform::<String>()
1687            .expect("Failed to transform to string");
1688        assert_eq!(v2.get::<&str>(), Ok("123"));
1689    }
1690
1691    #[test]
1692    fn test_into_raw() {
1693        unsafe {
1694            let mut v = 123.to_value().into_raw();
1695            assert_eq!(gobject_ffi::g_type_check_value(&v), ffi::GTRUE);
1696            assert_eq!(gobject_ffi::g_value_get_int(&v), 123);
1697            gobject_ffi::g_value_unset(&mut v);
1698        }
1699    }
1700
1701    #[test]
1702    fn test_debug() {
1703        fn value_debug_string<T: ToValue>(val: T) -> String {
1704            format!("{:?}", val.to_value())
1705        }
1706
1707        assert_eq!(value_debug_string(1u32), "(guint) 1");
1708        assert_eq!(value_debug_string(2i32), "(gint) 2");
1709        assert_eq!(value_debug_string(false), "(gboolean) FALSE");
1710        assert_eq!(value_debug_string("FooBar"), r#"(gchararray) "FooBar""#);
1711    }
1712}