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