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