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    // rustdoc-stripper-ignore-next-stop
504    /// An opaque structure used to hold different types of values.
505    ///
506    /// Before it can be used, a `GValue` has to be initialized to a specific type by
507    /// calling [method[`Object`][crate::Object].init] on it.
508    ///
509    /// Many types which are stored within a `GValue` need to allocate data on the
510    /// heap, so [method[`Object`][crate::Object].unset] must always be called on a `GValue` to
511    /// free any such data once you’re finished with the `GValue`, even if the
512    /// `GValue` itself is stored on the stack.
513    ///
514    /// The data within the structure has protected scope: it is accessible only
515    /// to functions within a [struct[`Object`][crate::Object]] structure, or
516    /// implementations of the `g_value_*()` API. That is, code which implements new
517    /// fundamental types.
518    ///
519    /// `GValue` users cannot make any assumptions about how data is stored
520    /// within the 2 element `data` union, and the `g_type` member should
521    /// only be accessed through the [func[`Object`][crate::Object]] macro and related
522    /// macros.
523    #[doc(alias = "GValue")]
524    pub struct Value(BoxedInline<gobject_ffi::GValue>);
525
526    match fn {
527        copy => |ptr| copy_value(ptr),
528        free => |ptr| free_value(ptr),
529        init => |ptr| init_value(ptr),
530        copy_into => |dest, src| copy_into_value(dest, src),
531        clear => |ptr| clear_value(ptr),
532    }
533}
534
535impl Value {
536    // rustdoc-stripper-ignore-next
537    /// Creates a new `Value` that is initialized with `type_`.
538    ///
539    /// # Panics
540    ///
541    /// If `type_` can't be stored in a `Value` this function panics.
542    pub fn from_type(type_: Type) -> Self {
543        unsafe {
544            assert_eq!(
545                gobject_ffi::g_type_check_is_value_type(type_.into_glib()),
546                ffi::GTRUE
547            );
548            Self::from_type_unchecked(type_)
549        }
550    }
551
552    // rustdoc-stripper-ignore-next
553    /// Creates a new `Value` that is initialized with `type_`.
554    ///
555    /// # SAFETY
556    ///
557    /// This must be called with a valid `type_` that can be stored in `Value`s.
558    #[inline]
559    pub unsafe fn from_type_unchecked(type_: Type) -> Self {
560        unsafe {
561            let mut value = Value::uninitialized();
562            gobject_ffi::g_value_init(value.to_glib_none_mut().0, type_.into_glib());
563            value
564        }
565    }
566
567    // rustdoc-stripper-ignore-next
568    /// Creates a new `Value` that is initialized for a given `ValueType`.
569    #[inline]
570    pub fn for_value_type<T: ValueType>() -> Self {
571        unsafe { Value::from_type_unchecked(T::Type::static_type()) }
572    }
573
574    // rustdoc-stripper-ignore-next
575    /// Creates a new `String`-typed `Value` from a `'static` string.
576    #[inline]
577    #[doc(alias = "g_value_set_static_string")]
578    pub fn from_static_str(s: &'static GStr) -> Self {
579        unsafe {
580            let mut v = Self::from_type_unchecked(Type::STRING);
581            gobject_ffi::g_value_set_static_string(v.to_glib_none_mut().0, s.as_ptr());
582            v
583        }
584    }
585
586    #[cfg(feature = "v2_66")]
587    #[cfg_attr(docsrs, doc(cfg(feature = "v2_66")))]
588    // rustdoc-stripper-ignore-next
589    /// Creates a new `String`-typed `Value` from a `'static` string that is also assumed to be
590    /// interned.
591    #[inline]
592    #[doc(alias = "g_value_set_interned_string")]
593    pub fn from_interned_str(s: &'static GStr) -> Self {
594        unsafe {
595            let mut v = Self::from_type_unchecked(Type::STRING);
596            gobject_ffi::g_value_set_interned_string(v.to_glib_none_mut().0, s.as_ptr());
597            v
598        }
599    }
600
601    // rustdoc-stripper-ignore-next
602    /// Tries to get a value of type `T`.
603    ///
604    /// Returns `Ok` if the type is correct.
605    #[inline]
606    pub fn get<'a, T>(
607        &'a self,
608    ) -> Result<T, <<T as FromValue<'a>>::Checker as ValueTypeChecker>::Error>
609    where
610        T: FromValue<'a>,
611    {
612        unsafe {
613            T::Checker::check(self)?;
614            Ok(T::from_value(self))
615        }
616    }
617
618    // rustdoc-stripper-ignore-next
619    /// Tries to get a value of an owned type `T`.
620    #[inline]
621    pub fn get_owned<T>(
622        &self,
623    ) -> Result<T, <<T as FromValue<'_>>::Checker as ValueTypeChecker>::Error>
624    where
625        T: for<'b> FromValue<'b> + 'static,
626    {
627        unsafe {
628            T::Checker::check(self)?;
629            Ok(FromValue::from_value(self))
630        }
631    }
632
633    // rustdoc-stripper-ignore-next
634    /// Returns `true` if the type of the value corresponds to `T`
635    /// or is a sub-type of `T`.
636    #[inline]
637    pub fn is<T: StaticType>(&self) -> bool {
638        self.is_type(T::static_type())
639    }
640
641    // rustdoc-stripper-ignore-next
642    /// Returns `true` if the type of the value corresponds to `type_`
643    /// or is a sub-type of `type_`.
644    #[inline]
645    pub fn is_type(&self, type_: Type) -> bool {
646        self.type_().is_a(type_)
647    }
648
649    // rustdoc-stripper-ignore-next
650    /// Returns the type of the value.
651    #[inline]
652    pub fn type_(&self) -> Type {
653        unsafe { from_glib(self.inner.g_type) }
654    }
655
656    // rustdoc-stripper-ignore-next
657    /// Returns whether `Value`s of type `src` can be transformed to type `dst`.
658    // rustdoc-stripper-ignore-next-stop
659    /// Checks whether [method[`Object`][crate::Object].transform] is able to transform values
660    /// of type `src_type` into values of type `dest_type`.
661    ///
662    /// Note that for the types to be transformable, they must be compatible or a
663    /// transformation function must be registered using
664    /// [func[`Object`][crate::Object].register_transform_func].
665    /// ## `src_type`
666    /// source type
667    /// ## `dest_type`
668    /// target type
669    ///
670    /// # Returns
671    ///
672    /// true if the transformation is possible; false otherwise
673    /// Flags describing what parts of the URI to hide in
674    /// g_uri_to_string_partial(). Note that [`PASSWORD`][Self::PASSWORD] and
675    /// [`AUTH_PARAMS`][Self::AUTH_PARAMS] will only work if the #GUri was parsed with
676    /// the corresponding flags.
677    #[doc(alias = "g_value_type_transformable")]
678    pub fn type_transformable(src: Type, dst: Type) -> bool {
679        unsafe {
680            from_glib(gobject_ffi::g_value_type_transformable(
681                src.into_glib(),
682                dst.into_glib(),
683            ))
684        }
685    }
686
687    // rustdoc-stripper-ignore-next
688    /// Tries to transform the value into a value of the target type
689    // rustdoc-stripper-ignore-next-stop
690    /// Tries to cast the contents of `self` into a type appropriate
691    /// to store in `dest_value`.
692    ///
693    /// If a transformation is not possible, `dest_value` is not modified.
694    ///
695    /// For example, this could transform a `G_TYPE_INT` value into a `G_TYPE_FLOAT`
696    /// value.
697    ///
698    /// Performing transformations between value types might incur precision loss.
699    /// Especially transformations into strings might reveal seemingly arbitrary
700    /// results and the format of particular transformations to strings is not
701    /// guaranteed over time.
702    /// ## `dest_value`
703    /// target value
704    ///
705    /// # Returns
706    ///
707    /// true on success; false otherwise
708    #[doc(alias = "g_value_transform")]
709    pub fn transform<T: ValueType>(&self) -> Result<Value, crate::BoolError> {
710        self.transform_with_type(T::Type::static_type())
711    }
712
713    // rustdoc-stripper-ignore-next
714    /// Tries to transform the value into a value of the target type
715    #[doc(alias = "g_value_transform")]
716    pub fn transform_with_type(&self, type_: Type) -> Result<Value, crate::BoolError> {
717        unsafe {
718            let mut dest = Value::from_type(type_);
719            if from_glib(gobject_ffi::g_value_transform(
720                self.to_glib_none().0,
721                dest.to_glib_none_mut().0,
722            )) {
723                Ok(dest)
724            } else {
725                Err(crate::bool_error!(
726                    "Can't transform value of type '{}' into '{}'",
727                    self.type_(),
728                    type_
729                ))
730            }
731        }
732    }
733
734    // rustdoc-stripper-ignore-next
735    /// Consumes `Value` and returns the corresponding `GValue`.
736    #[inline]
737    pub fn into_raw(self) -> gobject_ffi::GValue {
738        unsafe {
739            let s = mem::ManuallyDrop::new(self);
740            ptr::read(&s.inner)
741        }
742    }
743
744    // rustdoc-stripper-ignore-next
745    /// Converts a `Value` into a `SendValue`. This fails if `self` does not store a value of type
746    /// `T`. It is required for `T` to be `Send` to call this function.
747    #[inline]
748    pub fn try_into_send_value<T: Send + StaticType>(self) -> Result<SendValue, Self> {
749        if self.type_().is_a(T::static_type()) {
750            unsafe { Ok(SendValue::unsafe_from(self.into_raw())) }
751        } else {
752            Err(self)
753        }
754    }
755
756    // rustdoc-stripper-ignore-next
757    /// Converts a `Value` into a `SendValue`.
758    ///
759    /// # Safety
760    ///
761    /// The type of the value contained in `self` must be `Send`.
762    #[inline]
763    pub unsafe fn into_send_value(self) -> SendValue {
764        unsafe { SendValue::unsafe_from(self.into_raw()) }
765    }
766
767    fn content_debug_string(&self) -> GString {
768        unsafe { from_glib_full(gobject_ffi::g_strdup_value_contents(self.to_glib_none().0)) }
769    }
770}
771
772impl fmt::Debug for Value {
773    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
774        write!(f, "({}) {}", self.type_(), self.content_debug_string())
775    }
776}
777
778impl<'a, T: ?Sized + ToValue> From<&'a T> for Value {
779    #[inline]
780    fn from(value: &'a T) -> Self {
781        value.to_value()
782    }
783}
784
785impl From<SendValue> for Value {
786    #[inline]
787    fn from(value: SendValue) -> Self {
788        unsafe { Value::unsafe_from(value.into_raw()) }
789    }
790}
791
792impl ToValue for Value {
793    #[inline]
794    fn to_value(&self) -> Value {
795        self.clone()
796    }
797
798    #[inline]
799    fn value_type(&self) -> Type {
800        self.type_()
801    }
802}
803
804impl ToValue for &Value {
805    #[inline]
806    fn to_value(&self) -> Value {
807        (*self).clone()
808    }
809
810    #[inline]
811    fn value_type(&self) -> Type {
812        self.type_()
813    }
814}
815
816pub struct NopChecker;
817
818unsafe impl ValueTypeChecker for NopChecker {
819    type Error = Infallible;
820
821    #[inline]
822    fn check(_value: &Value) -> Result<(), Self::Error> {
823        Ok(())
824    }
825}
826
827unsafe impl<'a> FromValue<'a> for Value {
828    type Checker = NopChecker;
829
830    #[inline]
831    unsafe fn from_value(value: &'a Value) -> Self {
832        value.clone()
833    }
834}
835
836unsafe impl<'a> FromValue<'a> for &'a Value {
837    type Checker = NopChecker;
838
839    #[inline]
840    unsafe fn from_value(value: &'a Value) -> Self {
841        value
842    }
843}
844
845impl ToValue for SendValue {
846    #[inline]
847    fn to_value(&self) -> Value {
848        unsafe { from_glib_none(self.to_glib_none().0) }
849    }
850
851    #[inline]
852    fn value_type(&self) -> Type {
853        self.type_()
854    }
855}
856
857impl ToValue for &SendValue {
858    #[inline]
859    fn to_value(&self) -> Value {
860        unsafe { from_glib_none(self.to_glib_none().0) }
861    }
862
863    #[inline]
864    fn value_type(&self) -> Type {
865        self.type_()
866    }
867}
868
869impl StaticType for BoxedValue {
870    #[inline]
871    fn static_type() -> Type {
872        unsafe { from_glib(gobject_ffi::g_value_get_type()) }
873    }
874}
875
876crate::wrapper! {
877    // rustdoc-stripper-ignore-next
878    /// A version of [`Value`](struct.Value.html) for storing `Send` types, that implements Send
879    /// itself.
880    ///
881    /// See the [module documentation](index.html) for more details.
882    #[doc(alias = "GValue")]
883    pub struct SendValue(BoxedInline<gobject_ffi::GValue>);
884
885    match fn {
886        copy => |ptr| copy_value(ptr),
887        free => |ptr| free_value(ptr),
888        init => |ptr| init_value(ptr),
889        copy_into => |dest, src| copy_into_value(dest, src),
890        clear => |ptr| clear_value(ptr),
891    }
892}
893
894unsafe impl Send for SendValue {}
895
896impl SendValue {
897    // rustdoc-stripper-ignore-next
898    /// Consumes `SendValue` and returns the corresponding `GValue`.
899    #[inline]
900    pub fn into_raw(self) -> gobject_ffi::GValue {
901        unsafe {
902            let s = mem::ManuallyDrop::new(self);
903            ptr::read(&s.inner)
904        }
905    }
906    #[inline]
907    pub fn from_owned<T: Send + Into<Value>>(t: T) -> Self {
908        unsafe { Self::unsafe_from(t.into().into_raw()) }
909    }
910}
911
912impl fmt::Debug for SendValue {
913    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
914        write!(f, "({}) {}", self.type_(), self.content_debug_string())
915    }
916}
917
918impl Deref for SendValue {
919    type Target = Value;
920
921    #[inline]
922    fn deref(&self) -> &Value {
923        unsafe { &*(self as *const SendValue as *const Value) }
924    }
925}
926
927impl<'a, T: ?Sized + ToSendValue> From<&'a T> for SendValue {
928    #[inline]
929    fn from(value: &'a T) -> Self {
930        value.to_send_value()
931    }
932}
933
934// rustdoc-stripper-ignore-next
935/// Converts to `SendValue`.
936pub trait ToSendValue: Send + ToValue {
937    // rustdoc-stripper-ignore-next
938    /// Returns a `SendValue` clone of `self`.
939    fn to_send_value(&self) -> SendValue;
940}
941
942impl<T: Send + ToValue + ?Sized> ToSendValue for T {
943    #[inline]
944    fn to_send_value(&self) -> SendValue {
945        unsafe { SendValue::unsafe_from(self.to_value().into_raw()) }
946    }
947}
948
949unsafe impl<'a> FromValue<'a> for &'a str {
950    type Checker = GenericValueTypeOrNoneChecker<Self>;
951
952    #[inline]
953    unsafe fn from_value(value: &'a Value) -> Self {
954        unsafe {
955            let ptr = gobject_ffi::g_value_get_string(value.to_glib_none().0);
956            CStr::from_ptr(ptr).to_str().expect("Invalid UTF-8")
957        }
958    }
959}
960
961impl ToValue for str {
962    fn to_value(&self) -> Value {
963        unsafe {
964            let mut value = Value::for_value_type::<String>();
965
966            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
967
968            value
969        }
970    }
971
972    fn value_type(&self) -> Type {
973        String::static_type()
974    }
975}
976
977impl ToValue for &str {
978    fn to_value(&self) -> Value {
979        (*self).to_value()
980    }
981
982    fn value_type(&self) -> Type {
983        String::static_type()
984    }
985}
986
987impl ToValueOptional for str {
988    fn to_value_optional(s: Option<&Self>) -> Value {
989        let mut value = Value::for_value_type::<String>();
990        unsafe {
991            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
992        }
993
994        value
995    }
996}
997
998impl ValueType for String {
999    type Type = String;
1000}
1001
1002impl ValueTypeOptional for String {}
1003
1004unsafe impl<'a> FromValue<'a> for String {
1005    type Checker = GenericValueTypeOrNoneChecker<Self>;
1006
1007    unsafe fn from_value(value: &'a Value) -> Self {
1008        unsafe { String::from(<&str>::from_value(value)) }
1009    }
1010}
1011
1012impl ToValue for String {
1013    fn to_value(&self) -> Value {
1014        <&str>::to_value(&self.as_str())
1015    }
1016
1017    fn value_type(&self) -> Type {
1018        String::static_type()
1019    }
1020}
1021
1022impl From<String> for Value {
1023    #[inline]
1024    fn from(s: String) -> Self {
1025        s.to_value()
1026    }
1027}
1028
1029impl ToValueOptional for String {
1030    fn to_value_optional(s: Option<&Self>) -> Value {
1031        <str>::to_value_optional(s.as_ref().map(|s| s.as_str()))
1032    }
1033}
1034
1035impl ValueType for Box<str> {
1036    type Type = String;
1037}
1038
1039impl ValueTypeOptional for Box<str> {}
1040
1041unsafe impl<'a> FromValue<'a> for Box<str> {
1042    type Checker = GenericValueTypeOrNoneChecker<Self>;
1043
1044    unsafe fn from_value(value: &'a Value) -> Self {
1045        unsafe { Box::<str>::from(<&str>::from_value(value)) }
1046    }
1047}
1048
1049impl StaticType for Box<str> {
1050    fn static_type() -> Type {
1051        String::static_type()
1052    }
1053}
1054
1055impl ToValue for Box<str> {
1056    fn to_value(&self) -> Value {
1057        <&str>::to_value(&self.as_ref())
1058    }
1059
1060    fn value_type(&self) -> Type {
1061        String::static_type()
1062    }
1063}
1064
1065impl From<Box<str>> for Value {
1066    #[inline]
1067    fn from(s: Box<str>) -> Self {
1068        s.to_value()
1069    }
1070}
1071
1072impl ToValueOptional for Box<str> {
1073    fn to_value_optional(s: Option<&Self>) -> Value {
1074        <str>::to_value_optional(s.as_ref().map(|s| s.as_ref()))
1075    }
1076}
1077
1078impl ValueType for Vec<String> {
1079    type Type = Vec<String>;
1080}
1081
1082unsafe impl<'a> FromValue<'a> for Vec<String> {
1083    type Checker = GenericValueTypeChecker<Self>;
1084
1085    unsafe fn from_value(value: &'a Value) -> Self {
1086        unsafe {
1087            let ptr =
1088                gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
1089            FromGlibPtrContainer::from_glib_none(ptr)
1090        }
1091    }
1092}
1093
1094impl ToValue for Vec<String> {
1095    fn to_value(&self) -> Value {
1096        unsafe {
1097            let mut value = Value::for_value_type::<Self>();
1098            let ptr: *mut *mut c_char = self.to_glib_full();
1099            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1100            value
1101        }
1102    }
1103
1104    fn value_type(&self) -> Type {
1105        <Vec<String>>::static_type()
1106    }
1107}
1108
1109impl From<Vec<String>> for Value {
1110    #[inline]
1111    fn from(s: Vec<String>) -> Self {
1112        s.to_value()
1113    }
1114}
1115
1116impl ToValue for [&'_ str] {
1117    fn to_value(&self) -> Value {
1118        unsafe {
1119            let mut value = Value::for_value_type::<Vec<String>>();
1120            let ptr: *mut *mut c_char = self.to_glib_full();
1121            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1122            value
1123        }
1124    }
1125
1126    fn value_type(&self) -> Type {
1127        <Vec<String>>::static_type()
1128    }
1129}
1130
1131impl ToValue for &'_ [&'_ str] {
1132    fn to_value(&self) -> Value {
1133        unsafe {
1134            let mut value = Value::for_value_type::<Vec<String>>();
1135            let ptr: *mut *mut c_char = self.to_glib_full();
1136            gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1137            value
1138        }
1139    }
1140
1141    fn value_type(&self) -> Type {
1142        <Vec<String>>::static_type()
1143    }
1144}
1145
1146impl ToValue for Path {
1147    fn to_value(&self) -> Value {
1148        unsafe {
1149            let mut value = Value::for_value_type::<PathBuf>();
1150
1151            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
1152
1153            value
1154        }
1155    }
1156
1157    fn value_type(&self) -> Type {
1158        PathBuf::static_type()
1159    }
1160}
1161
1162impl ToValue for &Path {
1163    fn to_value(&self) -> Value {
1164        (*self).to_value()
1165    }
1166
1167    fn value_type(&self) -> Type {
1168        PathBuf::static_type()
1169    }
1170}
1171
1172impl ToValueOptional for Path {
1173    fn to_value_optional(s: Option<&Self>) -> Value {
1174        let mut value = Value::for_value_type::<PathBuf>();
1175        unsafe {
1176            gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
1177        }
1178
1179        value
1180    }
1181}
1182
1183impl ValueType for PathBuf {
1184    type Type = PathBuf;
1185}
1186
1187impl ValueTypeOptional for PathBuf {}
1188
1189unsafe impl<'a> FromValue<'a> for PathBuf {
1190    type Checker = GenericValueTypeOrNoneChecker<Self>;
1191
1192    unsafe fn from_value(value: &'a Value) -> Self {
1193        unsafe { from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0)) }
1194    }
1195}
1196
1197impl ToValue for PathBuf {
1198    fn to_value(&self) -> Value {
1199        <&Path>::to_value(&self.as_path())
1200    }
1201
1202    fn value_type(&self) -> Type {
1203        PathBuf::static_type()
1204    }
1205}
1206
1207impl From<PathBuf> for Value {
1208    #[inline]
1209    fn from(s: PathBuf) -> Self {
1210        s.to_value()
1211    }
1212}
1213
1214impl ToValueOptional for PathBuf {
1215    fn to_value_optional(s: Option<&Self>) -> Value {
1216        <Path>::to_value_optional(s.as_ref().map(|s| s.as_path()))
1217    }
1218}
1219
1220impl ValueType for bool {
1221    type Type = Self;
1222}
1223
1224unsafe impl<'a> FromValue<'a> for bool {
1225    type Checker = GenericValueTypeChecker<Self>;
1226
1227    #[inline]
1228    unsafe fn from_value(value: &'a Value) -> Self {
1229        unsafe { from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0)) }
1230    }
1231}
1232
1233impl ToValue for bool {
1234    #[inline]
1235    fn to_value(&self) -> Value {
1236        let mut value = Value::for_value_type::<Self>();
1237        unsafe {
1238            gobject_ffi::g_value_set_boolean(&mut value.inner, self.into_glib());
1239        }
1240        value
1241    }
1242
1243    #[inline]
1244    fn value_type(&self) -> Type {
1245        Self::static_type()
1246    }
1247}
1248
1249impl From<bool> for Value {
1250    #[inline]
1251    fn from(v: bool) -> Self {
1252        v.to_value()
1253    }
1254}
1255
1256impl ValueType for Pointer {
1257    type Type = Self;
1258}
1259
1260unsafe impl<'a> FromValue<'a> for Pointer {
1261    type Checker = GenericValueTypeChecker<Self>;
1262
1263    #[inline]
1264    unsafe fn from_value(value: &'a Value) -> Self {
1265        unsafe { gobject_ffi::g_value_get_pointer(value.to_glib_none().0) }
1266    }
1267}
1268
1269impl ToValue for Pointer {
1270    #[inline]
1271    fn to_value(&self) -> Value {
1272        let mut value = Value::for_value_type::<Self>();
1273        unsafe {
1274            gobject_ffi::g_value_set_pointer(&mut value.inner, *self);
1275        }
1276        value
1277    }
1278
1279    #[inline]
1280    fn value_type(&self) -> Type {
1281        <<Self as ValueType>::Type as StaticType>::static_type()
1282    }
1283}
1284
1285impl From<Pointer> for Value {
1286    #[inline]
1287    fn from(v: Pointer) -> Self {
1288        v.to_value()
1289    }
1290}
1291
1292impl ValueType for ptr::NonNull<Pointee> {
1293    type Type = Pointer;
1294}
1295
1296unsafe impl<'a> FromValue<'a> for ptr::NonNull<Pointee> {
1297    type Checker = GenericValueTypeOrNoneChecker<Self>;
1298
1299    #[inline]
1300    unsafe fn from_value(value: &'a Value) -> Self {
1301        unsafe { ptr::NonNull::new_unchecked(Pointer::from_value(value)) }
1302    }
1303}
1304
1305impl ToValue for ptr::NonNull<Pointee> {
1306    #[inline]
1307    fn to_value(&self) -> Value {
1308        self.as_ptr().to_value()
1309    }
1310
1311    #[inline]
1312    fn value_type(&self) -> Type {
1313        <<Self as ValueType>::Type as StaticType>::static_type()
1314    }
1315}
1316
1317impl From<ptr::NonNull<Pointee>> for Value {
1318    #[inline]
1319    fn from(v: ptr::NonNull<Pointee>) -> Self {
1320        v.to_value()
1321    }
1322}
1323
1324impl ToValueOptional for ptr::NonNull<Pointee> {
1325    #[inline]
1326    fn to_value_optional(p: Option<&Self>) -> Value {
1327        p.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()).to_value()
1328    }
1329}
1330
1331macro_rules! numeric {
1332    ($name:ty, $get:expr, $set:expr) => {
1333        impl ValueType for $name {
1334            type Type = Self;
1335        }
1336
1337        unsafe impl<'a> FromValue<'a> for $name {
1338            type Checker = GenericValueTypeChecker<Self>;
1339
1340            #[inline]
1341            #[allow(clippy::redundant_closure_call)]
1342            unsafe fn from_value(value: &'a Value) -> Self {
1343                unsafe { $get(value.to_glib_none().0) }
1344            }
1345        }
1346
1347        impl ToValue for $name {
1348            #[inline]
1349            #[allow(clippy::redundant_closure_call)]
1350            fn to_value(&self) -> Value {
1351                let mut value = Value::for_value_type::<Self>();
1352                unsafe {
1353                    $set(&mut value.inner, *self);
1354                }
1355                value
1356            }
1357
1358            #[inline]
1359            fn value_type(&self) -> Type {
1360                Self::static_type()
1361            }
1362        }
1363
1364        impl From<$name> for Value {
1365            #[inline]
1366            fn from(v: $name) -> Self {
1367                v.to_value()
1368            }
1369        }
1370    };
1371}
1372macro_rules! not_zero {
1373    ($name:ty, $num:ty) => {
1374        impl ValueType for $name {
1375            type Type = $name;
1376        }
1377
1378        unsafe impl<'a> FromValue<'a> for $name {
1379            // Works because it returns `UnexpectedNone` if the value is NULL
1380            // by checking it against `0`.
1381            type Checker = GenericValueTypeOrNoneChecker<Self>;
1382
1383            #[inline]
1384            unsafe fn from_value(value: &'a Value) -> Self {
1385                unsafe {
1386                    let res = <$num>::from_value(value);
1387                    Self::try_from(res).unwrap()
1388                }
1389            }
1390        }
1391
1392        impl ToValue for $name {
1393            #[inline]
1394            fn to_value(&self) -> Value {
1395                <$num>::to_value(&<$num>::from(*self))
1396            }
1397
1398            #[inline]
1399            fn value_type(&self) -> Type {
1400                Self::static_type()
1401            }
1402        }
1403
1404        impl From<$name> for Value {
1405            #[inline]
1406            fn from(v: $name) -> Self {
1407                v.to_value()
1408            }
1409        }
1410
1411        impl ToValueOptional for $name {
1412            fn to_value_optional(s: Option<&Self>) -> Value {
1413                match s {
1414                    Some(x) => x.to_value(),
1415                    None => <$num>::to_value(&0),
1416                }
1417            }
1418        }
1419    };
1420}
1421
1422numeric!(
1423    i8,
1424    gobject_ffi::g_value_get_schar,
1425    gobject_ffi::g_value_set_schar
1426);
1427not_zero!(NonZeroI8, i8);
1428numeric!(
1429    u8,
1430    gobject_ffi::g_value_get_uchar,
1431    gobject_ffi::g_value_set_uchar
1432);
1433not_zero!(NonZeroU8, u8);
1434numeric!(
1435    i32,
1436    gobject_ffi::g_value_get_int,
1437    gobject_ffi::g_value_set_int
1438);
1439not_zero!(NonZeroI32, i32);
1440numeric!(
1441    u32,
1442    gobject_ffi::g_value_get_uint,
1443    gobject_ffi::g_value_set_uint
1444);
1445not_zero!(NonZeroU32, u32);
1446numeric!(
1447    i64,
1448    gobject_ffi::g_value_get_int64,
1449    gobject_ffi::g_value_set_int64
1450);
1451not_zero!(NonZeroI64, i64);
1452numeric!(
1453    u64,
1454    gobject_ffi::g_value_get_uint64,
1455    gobject_ffi::g_value_set_uint64
1456);
1457not_zero!(NonZeroU64, u64);
1458numeric!(
1459    crate::ILong,
1460    |v| gobject_ffi::g_value_get_long(v).into(),
1461    |v, i: crate::ILong| gobject_ffi::g_value_set_long(v, i.0)
1462);
1463numeric!(
1464    crate::ULong,
1465    |v| gobject_ffi::g_value_get_ulong(v).into(),
1466    |v, i: crate::ULong| gobject_ffi::g_value_set_ulong(v, i.0)
1467);
1468numeric!(
1469    f32,
1470    gobject_ffi::g_value_get_float,
1471    gobject_ffi::g_value_set_float
1472);
1473numeric!(
1474    f64,
1475    gobject_ffi::g_value_get_double,
1476    gobject_ffi::g_value_set_double
1477);
1478
1479impl ValueType for char {
1480    type Type = u32;
1481}
1482
1483unsafe impl<'a> FromValue<'a> for char {
1484    type Checker = CharTypeChecker;
1485
1486    #[inline]
1487    unsafe fn from_value(value: &'a Value) -> Self {
1488        unsafe {
1489            let res: u32 = gobject_ffi::g_value_get_uint(value.to_glib_none().0);
1490            // safe because the check is done by `Self::Checker`
1491            char::from_u32_unchecked(res)
1492        }
1493    }
1494}
1495
1496impl ToValue for char {
1497    #[inline]
1498    fn to_value(&self) -> Value {
1499        let mut value = Value::for_value_type::<Self>();
1500        unsafe {
1501            gobject_ffi::g_value_set_uint(&mut value.inner, *self as u32);
1502        }
1503        value
1504    }
1505
1506    #[inline]
1507    fn value_type(&self) -> Type {
1508        crate::Type::U32
1509    }
1510}
1511
1512impl From<char> for Value {
1513    #[inline]
1514    fn from(v: char) -> Self {
1515        v.to_value()
1516    }
1517}
1518
1519// rustdoc-stripper-ignore-next
1520/// A [`Value`] containing another [`Value`].
1521pub struct BoxedValue(pub Value);
1522
1523impl Deref for BoxedValue {
1524    type Target = Value;
1525
1526    #[inline]
1527    fn deref(&self) -> &Value {
1528        &self.0
1529    }
1530}
1531
1532impl ValueType for BoxedValue {
1533    type Type = BoxedValue;
1534}
1535
1536impl ValueTypeOptional for BoxedValue {}
1537
1538unsafe impl<'a> FromValue<'a> for BoxedValue {
1539    type Checker = GenericValueTypeOrNoneChecker<Self>;
1540
1541    #[inline]
1542    unsafe fn from_value(value: &'a Value) -> Self {
1543        unsafe {
1544            let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1545            BoxedValue(from_glib_none(ptr as *const gobject_ffi::GValue))
1546        }
1547    }
1548}
1549
1550impl ToValue for BoxedValue {
1551    #[inline]
1552    fn to_value(&self) -> Value {
1553        unsafe {
1554            let mut value = Value::for_value_type::<BoxedValue>();
1555
1556            gobject_ffi::g_value_set_boxed(
1557                value.to_glib_none_mut().0,
1558                self.0.to_glib_none().0 as ffi::gconstpointer,
1559            );
1560
1561            value
1562        }
1563    }
1564
1565    #[inline]
1566    fn value_type(&self) -> Type {
1567        BoxedValue::static_type()
1568    }
1569}
1570
1571impl From<BoxedValue> for Value {
1572    #[inline]
1573    fn from(v: BoxedValue) -> Self {
1574        unsafe {
1575            let mut value = Value::for_value_type::<BoxedValue>();
1576
1577            gobject_ffi::g_value_take_boxed(
1578                value.to_glib_none_mut().0,
1579                v.0.to_glib_full() as ffi::gconstpointer,
1580            );
1581
1582            value
1583        }
1584    }
1585}
1586
1587impl ToValueOptional for BoxedValue {
1588    #[inline]
1589    fn to_value_optional(s: Option<&Self>) -> Value {
1590        let mut value = Value::for_value_type::<Self>();
1591        unsafe {
1592            gobject_ffi::g_value_set_boxed(
1593                value.to_glib_none_mut().0,
1594                s.map(|s| &s.0).to_glib_none().0 as ffi::gconstpointer,
1595            );
1596        }
1597
1598        value
1599    }
1600}
1601
1602#[cfg(test)]
1603mod tests {
1604    use std::num::NonZeroI32;
1605
1606    use super::*;
1607
1608    #[test]
1609    fn test_send_value() {
1610        use std::thread;
1611
1612        let v = SendValue::from(&1i32);
1613
1614        // Must compile, while it must fail with Value
1615        thread::spawn(move || drop(v)).join().unwrap();
1616    }
1617
1618    #[test]
1619    fn test_strv() {
1620        let v = ["123", "456"].to_value();
1621        assert_eq!(
1622            v.get::<Vec<GString>>(),
1623            Ok(vec![GString::from("123"), GString::from("456")])
1624        );
1625
1626        let v = vec![String::from("123"), String::from("456")].to_value();
1627        assert_eq!(
1628            v.get::<Vec<GString>>(),
1629            Ok(vec![GString::from("123"), GString::from("456")])
1630        );
1631    }
1632
1633    #[test]
1634    fn test_from_to_value() {
1635        let v = 123.to_value();
1636        assert_eq!(v.get(), Ok(123));
1637        assert_eq!(
1638            v.get::<&str>(),
1639            Err(ValueTypeMismatchError::new(Type::I32, Type::STRING).into())
1640        );
1641        assert_eq!(
1642            v.get::<bool>(),
1643            Err(ValueTypeMismatchError::new(Type::I32, Type::BOOL))
1644        );
1645
1646        // Check if &str / str / Option<&str> etc can be converted and retrieved
1647        let v_str = "test".to_value();
1648        assert_eq!(v_str.get::<&str>(), Ok("test"));
1649        assert_eq!(v_str.get::<Option<&str>>(), Ok(Some("test")));
1650        assert_eq!(
1651            v_str.get::<i32>(),
1652            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1653        );
1654
1655        let some_v = Some("test").to_value();
1656        assert_eq!(some_v.get::<&str>(), Ok("test"));
1657        assert_eq!(some_v.get_owned::<String>(), Ok("test".to_string()));
1658        assert_eq!(
1659            some_v.get_owned::<Option<String>>(),
1660            Ok(Some("test".to_string()))
1661        );
1662        assert_eq!(some_v.get::<Option<&str>>(), Ok(Some("test")));
1663        assert_eq!(
1664            some_v.get::<i32>(),
1665            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1666        );
1667
1668        let none_str: Option<&str> = None;
1669        let none_v = none_str.to_value();
1670        assert_eq!(none_v.get::<Option<&str>>(), Ok(None));
1671        assert_eq!(
1672            none_v.get::<i32>(),
1673            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1674        );
1675
1676        // Check if owned T and Option<T> can be converted and retrieved
1677        let v_str = String::from("test").to_value();
1678        assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1679        assert_eq!(
1680            v_str.get::<Option<String>>(),
1681            Ok(Some(String::from("test")))
1682        );
1683        assert_eq!(
1684            v_str.get::<i32>(),
1685            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1686        );
1687
1688        let some_v = Some(String::from("test")).to_value();
1689        assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1690        assert_eq!(
1691            some_v.get::<Option<String>>(),
1692            Ok(Some(String::from("test")))
1693        );
1694        assert_eq!(
1695            some_v.get::<i32>(),
1696            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1697        );
1698
1699        let none_str: Option<String> = None;
1700        let none_v = none_str.to_value();
1701        assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1702        assert_eq!(
1703            none_v.get::<i32>(),
1704            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1705        );
1706
1707        let c_v = 'c'.to_value();
1708        assert_eq!(c_v.get::<char>(), Ok('c'));
1709
1710        let c_v = 0xFFFFFFFFu32.to_value();
1711        assert_eq!(
1712            c_v.get::<char>(),
1713            Err(InvalidCharError::CharConversionError)
1714        );
1715
1716        // Check if &T and Option<&T> can be converted and retrieved
1717        let v_str = String::from("test").to_value();
1718        assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1719        assert_eq!(
1720            v_str.get::<Option<String>>(),
1721            Ok(Some(String::from("test")))
1722        );
1723        assert_eq!(
1724            v_str.get::<i32>(),
1725            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1726        );
1727
1728        let some_v = Some(&String::from("test")).to_value();
1729        assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1730        assert_eq!(
1731            some_v.get::<Option<String>>(),
1732            Ok(Some(String::from("test")))
1733        );
1734        assert_eq!(
1735            some_v.get::<i32>(),
1736            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1737        );
1738
1739        let none_str: Option<&String> = None;
1740        let none_v = none_str.to_value();
1741        assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1742        assert_eq!(
1743            none_v.get::<i32>(),
1744            Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1745        );
1746
1747        // Check handling of NonZeroT
1748        let v = NonZeroI32::new(123).unwrap().to_value();
1749        assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1750
1751        let v = 123i32.to_value();
1752        assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1753
1754        let v = 0i32.to_value();
1755        assert_eq!(
1756            v.get::<NonZeroI32>(),
1757            Err(ValueTypeMismatchOrNoneError::UnexpectedNone)
1758        );
1759
1760        assert_eq!(v.get::<Option<NonZeroI32>>(), Ok(None));
1761    }
1762
1763    #[test]
1764    fn test_transform() {
1765        let v = 123.to_value();
1766        let v2 = v
1767            .transform::<String>()
1768            .expect("Failed to transform to string");
1769        assert_eq!(v2.get::<&str>(), Ok("123"));
1770    }
1771
1772    #[test]
1773    fn test_into_raw() {
1774        unsafe {
1775            let mut v = 123.to_value().into_raw();
1776            assert_eq!(gobject_ffi::g_type_check_value(&v), ffi::GTRUE);
1777            assert_eq!(gobject_ffi::g_value_get_int(&v), 123);
1778            gobject_ffi::g_value_unset(&mut v);
1779        }
1780    }
1781
1782    #[test]
1783    fn test_debug() {
1784        fn value_debug_string<T: ToValue>(val: T) -> String {
1785            format!("{:?}", val.to_value())
1786        }
1787
1788        assert_eq!(value_debug_string(1u32), "(guint) 1");
1789        assert_eq!(value_debug_string(2i32), "(gint) 2");
1790        assert_eq!(value_debug_string(false), "(gboolean) FALSE");
1791        assert_eq!(value_debug_string("FooBar"), r#"(gchararray) "FooBar""#);
1792    }
1793}