Skip to main content

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