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