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