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}