glib/
value.rs

1// Copyright 2013-2016, The Gtk-rs Project Developers.
2// See the COPYRIGHT file at the top-level directory of this distribution.
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5//! `Value` binding and helper traits.
6//!
7//! The type of a [`Value`](struct.Value.html) is dynamic in that it generally
8//! isn't known at compile time but once created a `Value` can't change its
9//! type.
10//!
11//! [`TypedValue`](struct.TypedValue.html) has a statically known type and
12//! dereferences to `Value` so it can be used everywhere `Value` references are
13//! accepted.
14//!
15//! [`SendValue`](struct.SendValue.html) is a version of [`Value`](struct.Value.html)
16//! that can only store types that implement `Send` and as such implements `Send` itself. It
17//! dereferences to `Value` so it can be used everywhere `Value` references are accepted.
18//!
19//! Supported types are `bool`, `i8`, `u8`, `i32`, `u32`, `i64`, `u64`, `f32`,
20//! `f64`, `String` and objects (`T: IsA<Object>`).
21//!
22//! # Examples
23//!
24//! ```
25//! use glib::prelude::*; // or `use gtk::prelude::*;`
26//! use glib::{TypedValue, Value};
27//!
28//! // Value and TypedValue implement From<&i32>, From<&str>
29//! // and From<Option<&str>>. Another option is the `ToValue` trait.
30//! let mut num = 10.to_value();
31//! let mut hello = Value::from("Hello!");
32//! let none: Option<&str> = None;
33//! let str_none = Value::from(none.clone());
34//! let typed_str_none = TypedValue::from(none);
35//!
36//! // `is` tests the type of the value.
37//! assert!(num.is::<i32>());
38//! assert!(hello.is::<String>());
39//!
40//! // `get` tries to get a value of specific type and returns None
41//! // if the type doesn't match or the value is None.
42//! assert_eq!(num.get(), Some(10));
43//! assert_eq!(num.get::<String>(), None);
44//! assert_eq!(hello.get(), Some(String::from("Hello!")));
45//! assert_eq!(hello.get::<String>(), Some(String::from("Hello!")));
46//! assert_eq!(str_none.get::<String>(), None);
47//!
48//! // `typed` tries to convert a `Value` to `TypedValue`.
49//! let mut typed_num = num.downcast::<i32>().unwrap();
50//! let mut typed_hello = hello.downcast::<String>().unwrap();
51//!
52//! // `str_none` is not an `i32`
53//! assert!(str_none.downcast::<i32>().is_err());
54//!
55//! // `get`
56//! assert!(typed_hello.get().unwrap() == "Hello!");
57//! assert!(typed_str_none.get() == None);
58//!
59//! // Numeric types can't have value `None`, `get` always returns `Some`.
60//! // Such types have `get_some`, which avoids unnecessary `unwrap`ping.
61//! assert_eq!(typed_num.get().unwrap(), 10);
62//! assert_eq!(typed_num.get_some(), 10);
63//!
64//! // `set_none` sets the value to `None` if the type supports it.
65//! typed_hello.set_none();
66//! assert!(typed_hello.get().is_none());
67//!
68//! // `set` takes an optional reference for types that support `None`.
69//! typed_hello.set(Some("Hello again!"));
70//! assert!(typed_hello.get().unwrap() == "Hello again!");
71//!
72//! // `set_some` is the only setter for types that don't support `None`.
73//! typed_num.set_some(&20);
74//! assert_eq!(typed_num.get_some(), 20);
75//! ```
76
77use libc::{c_char, c_void};
78use std::borrow::Borrow;
79use std::ffi::CStr;
80use std::fmt;
81use std::marker::PhantomData;
82use std::mem;
83use std::ops::Deref;
84use std::ptr;
85
86use glib_sys;
87use gobject_sys;
88use gstring::GString;
89use translate::*;
90use types::{StaticType, Type};
91
92/// A generic value capable of carrying various types.
93///
94/// Once created the type of the value can't be changed.
95///
96/// Some types (e.g. `String` and objects) support `None` values while others
97/// (e.g. numeric types) don't.
98///
99/// `Value` does not implement the `Send` trait, but [`SendValue`](struct.SendValue.html) can be
100/// used instead.
101///
102/// See the [module documentation](index.html) for more details.
103// TODO: Should use impl !Send for Value {} once stable
104#[repr(C)]
105pub struct Value(pub(crate) gobject_sys::GValue, PhantomData<*const c_void>);
106
107impl Value {
108    /// Creates a new `Value` that is initialized with `type_`
109    pub fn from_type(type_: Type) -> Self {
110        unsafe {
111            assert_eq!(
112                gobject_sys::g_type_check_is_value_type(type_.to_glib()),
113                glib_sys::GTRUE
114            );
115            let mut value = Value::uninitialized();
116            gobject_sys::g_value_init(value.to_glib_none_mut().0, type_.to_glib());
117            value
118        }
119    }
120
121    /// Tries to downcast to a `TypedValue`.
122    ///
123    /// Returns `Ok(TypedValue<T>)` if the value carries a type corresponding
124    /// to `T` and `Err(self)` otherwise.
125    pub fn downcast<'a, T: FromValueOptional<'a> + SetValue>(self) -> Result<TypedValue<T>, Self> {
126        unsafe {
127            let ok = from_glib(gobject_sys::g_type_check_value_holds(
128                mut_override(self.to_glib_none().0),
129                T::static_type().to_glib(),
130            ));
131            if ok {
132                Ok(TypedValue(self, PhantomData))
133            } else {
134                Err(self)
135            }
136        }
137    }
138
139    /// Tries to downcast to a `&TypedValue`.
140    ///
141    /// Returns `Some(&TypedValue<T>)` if the value carries a type corresponding
142    /// to `T` and `None` otherwise.
143    pub fn downcast_ref<'a, T: FromValueOptional<'a> + SetValue>(&self) -> Option<&TypedValue<T>> {
144        unsafe {
145            let ok = from_glib(gobject_sys::g_type_check_value_holds(
146                mut_override(self.to_glib_none().0),
147                T::static_type().to_glib(),
148            ));
149            if ok {
150                // This transmute is safe because Value and TypedValue have the same
151                // representation: the only difference is the zero-sized phantom data
152                Some(&*(self as *const Value as *const TypedValue<T>))
153            } else {
154                None
155            }
156        }
157    }
158
159    /// Tries to get a value of type `T`.
160    ///
161    /// Returns `Some` if the type is correct and the value is not `None`.
162    ///
163    /// This function doesn't distinguish between type mismatches and correctly
164    /// typed `None` values. Use `downcast` or `is` for that.
165    pub fn get<'a, T: FromValueOptional<'a>>(&'a self) -> Option<T> {
166        unsafe {
167            let ok = from_glib(gobject_sys::g_type_check_value_holds(
168                mut_override(self.to_glib_none().0),
169                T::static_type().to_glib(),
170            ));
171            if ok {
172                T::from_value_optional(self)
173            } else {
174                None
175            }
176        }
177    }
178
179    /// Returns `true` if the type of the value corresponds to `T`
180    /// or is a sub-type of `T`.
181    #[inline]
182    pub fn is<'a, T: FromValueOptional<'a> + SetValue>(&self) -> bool {
183        self.type_().is_a(&T::static_type())
184    }
185
186    /// Returns the type of the value.
187    pub fn type_(&self) -> Type {
188        from_glib(self.0.g_type)
189    }
190
191    /// Returns whether `Value`s of type `src` can be transformed to type `dst`.
192    pub fn type_transformable(src: Type, dst: Type) -> bool {
193        unsafe {
194            from_glib(gobject_sys::g_value_type_transformable(
195                src.to_glib(),
196                dst.to_glib(),
197            ))
198        }
199    }
200
201    #[doc(hidden)]
202    pub fn into_raw(mut self) -> gobject_sys::GValue {
203        unsafe {
204            let ret = mem::replace(&mut self.0, mem::uninitialized());
205            mem::forget(self);
206            ret
207        }
208    }
209
210    pub fn try_into_send_value<'a, T: Send + FromValueOptional<'a> + SetValue>(
211        self,
212    ) -> Result<SendValue, Self> {
213        self.downcast::<T>().map(TypedValue::into_send_value)
214    }
215}
216
217impl Clone for Value {
218    fn clone(&self) -> Self {
219        unsafe {
220            let mut ret = Value::from_type(from_glib(self.0.g_type));
221            gobject_sys::g_value_copy(self.to_glib_none().0, ret.to_glib_none_mut().0);
222            ret
223        }
224    }
225}
226
227impl Drop for Value {
228    fn drop(&mut self) {
229        // Before GLib 2.48, unsetting a zeroed GValue would give critical warnings
230        // https://bugzilla.gnome.org/show_bug.cgi?id=755766
231        if self.type_() != Type::Invalid {
232            unsafe { gobject_sys::g_value_unset(self.to_glib_none_mut().0) }
233        }
234    }
235}
236
237impl fmt::Debug for Value {
238    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
239        unsafe {
240            let s: GString =
241                from_glib_full(gobject_sys::g_strdup_value_contents(self.to_glib_none().0));
242
243            f.debug_tuple("Value").field(&s).finish()
244        }
245    }
246}
247
248impl<'a, T: ?Sized + SetValueOptional> From<Option<&'a T>> for Value {
249    #[inline]
250    fn from(value: Option<&'a T>) -> Self {
251        value.to_value()
252    }
253}
254
255impl<'a, T: ?Sized + SetValue> From<&'a T> for Value {
256    #[inline]
257    fn from(value: &'a T) -> Self {
258        value.to_value()
259    }
260}
261
262impl<T> From<TypedValue<T>> for Value {
263    fn from(value: TypedValue<T>) -> Self {
264        value.0
265    }
266}
267
268impl From<SendValue> for Value {
269    fn from(value: SendValue) -> Self {
270        value.0
271    }
272}
273
274impl Uninitialized for Value {
275    unsafe fn uninitialized() -> Value {
276        Value(mem::zeroed(), PhantomData)
277    }
278}
279
280#[doc(hidden)]
281impl<'a> ToGlibPtr<'a, *const gobject_sys::GValue> for Value {
282    type Storage = &'a Value;
283
284    fn to_glib_none(&'a self) -> Stash<'a, *const gobject_sys::GValue, Self> {
285        Stash(&self.0, self)
286    }
287}
288
289#[doc(hidden)]
290impl<'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for Value {
291    type Storage = &'a mut Value;
292
293    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
294        StashMut(&mut self.0, self)
295    }
296}
297
298#[doc(hidden)]
299impl<'a> ToGlibPtr<'a, *mut gobject_sys::GValue> for &'a [&'a dyn ToValue] {
300    type Storage = ValueArray;
301
302    fn to_glib_none(&'a self) -> Stash<'a, *mut gobject_sys::GValue, Self> {
303        let mut values: Vec<gobject_sys::GValue> =
304            self.iter().map(|v| v.to_value().into_raw()).collect();
305        Stash(values.as_mut_ptr(), ValueArray(values))
306    }
307}
308
309#[doc(hidden)]
310impl<'a> ToGlibContainerFromSlice<'a, *mut gobject_sys::GValue> for &'a Value {
311    type Storage = &'a [&'a Value];
312
313    fn to_glib_none_from_slice(t: &'a [&'a Value]) -> (*mut gobject_sys::GValue, &'a [&'a Value]) {
314        (t.as_ptr() as *mut gobject_sys::GValue, t)
315    }
316
317    fn to_glib_container_from_slice(
318        t: &'a [&'a Value],
319    ) -> (*mut gobject_sys::GValue, &'a [&'a Value]) {
320        if t.is_empty() {
321            return (ptr::null_mut(), t);
322        }
323
324        unsafe {
325            let res = glib_sys::g_malloc(mem::size_of::<gobject_sys::GValue>() * t.len())
326                as *mut gobject_sys::GValue;
327            ptr::copy_nonoverlapping(t.as_ptr() as *const gobject_sys::GValue, res, t.len());
328            (res, t)
329        }
330    }
331
332    fn to_glib_full_from_slice(t: &[&'a Value]) -> *mut gobject_sys::GValue {
333        if t.is_empty() {
334            return ptr::null_mut();
335        }
336
337        unsafe {
338            let res = glib_sys::g_malloc(mem::size_of::<gobject_sys::GValue>() * t.len())
339                as *mut gobject_sys::GValue;
340            for (i, v) in t.iter().enumerate() {
341                gobject_sys::g_value_init(res.add(i), v.type_().to_glib());
342                gobject_sys::g_value_copy(v.to_glib_none().0, res.add(i));
343            }
344            res
345        }
346    }
347}
348
349#[doc(hidden)]
350impl<'a> ToGlibContainerFromSlice<'a, *const gobject_sys::GValue> for &'a Value {
351    type Storage = &'a [&'a Value];
352
353    fn to_glib_none_from_slice(
354        t: &'a [&'a Value],
355    ) -> (*const gobject_sys::GValue, &'a [&'a Value]) {
356        let (ptr, storage) =
357            ToGlibContainerFromSlice::<'a, *mut gobject_sys::GValue>::to_glib_none_from_slice(t);
358        (ptr as *const _, storage)
359    }
360
361    fn to_glib_container_from_slice(
362        _: &'a [&'a Value],
363    ) -> (*const gobject_sys::GValue, &'a [&'a Value]) {
364        unimplemented!()
365    }
366
367    fn to_glib_full_from_slice(_: &[&'a Value]) -> *const gobject_sys::GValue {
368        unimplemented!()
369    }
370}
371
372macro_rules! from_glib {
373    ($name:ident, $wrap:expr) => {
374        impl FromGlibPtrNone<*const gobject_sys::GValue> for $name {
375            unsafe fn from_glib_none(ptr: *const gobject_sys::GValue) -> Self {
376                let mut ret = Value::from_type(from_glib((*ptr).g_type));
377                gobject_sys::g_value_copy(ptr, ret.to_glib_none_mut().0);
378                $wrap(ret)
379            }
380        }
381
382        impl FromGlibPtrNone<*mut gobject_sys::GValue> for $name {
383            unsafe fn from_glib_none(ptr: *mut gobject_sys::GValue) -> Self {
384                from_glib_none(ptr as *const _)
385            }
386        }
387
388        impl FromGlibPtrFull<*mut gobject_sys::GValue> for $name {
389            unsafe fn from_glib_full(ptr: *mut gobject_sys::GValue) -> Self {
390                let mut ret = Value::uninitialized();
391                ptr::swap(&mut ret.0, ptr);
392                glib_sys::g_free(ptr as *mut c_void);
393                $wrap(ret)
394            }
395        }
396
397        impl FromGlibContainerAsVec<*mut gobject_sys::GValue, *mut *mut gobject_sys::GValue>
398            for $name
399        {
400            unsafe fn from_glib_none_num_as_vec(
401                ptr: *mut *mut gobject_sys::GValue,
402                num: usize,
403            ) -> Vec<Self> {
404                if num == 0 || ptr.is_null() {
405                    return Vec::new();
406                }
407
408                let mut res = Vec::with_capacity(num);
409                for i in 0..num {
410                    res.push(from_glib_none(ptr::read(ptr.add(i))));
411                }
412                res
413            }
414
415            unsafe fn from_glib_container_num_as_vec(
416                ptr: *mut *mut gobject_sys::GValue,
417                num: usize,
418            ) -> Vec<Self> {
419                let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
420                glib_sys::g_free(ptr as *mut _);
421                res
422            }
423
424            unsafe fn from_glib_full_num_as_vec(
425                ptr: *mut *mut gobject_sys::GValue,
426                num: usize,
427            ) -> Vec<Self> {
428                if num == 0 || ptr.is_null() {
429                    return Vec::new();
430                }
431
432                let mut res = Vec::with_capacity(num);
433                for i in 0..num {
434                    res.push(from_glib_full(ptr::read(ptr.add(i))));
435                }
436                glib_sys::g_free(ptr as *mut _);
437                res
438            }
439        }
440
441        impl FromGlibPtrArrayContainerAsVec<*mut gobject_sys::GValue, *mut *mut gobject_sys::GValue>
442            for $name
443        {
444            unsafe fn from_glib_none_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
445                FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
446            }
447
448            unsafe fn from_glib_container_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
449                FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
450            }
451
452            unsafe fn from_glib_full_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
453                FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
454            }
455        }
456
457        impl FromGlibContainerAsVec<*mut gobject_sys::GValue, *const *mut gobject_sys::GValue>
458            for $name
459        {
460            unsafe fn from_glib_none_num_as_vec(
461                ptr: *const *mut gobject_sys::GValue,
462                num: usize,
463            ) -> Vec<Self> {
464                FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
465            }
466
467            unsafe fn from_glib_container_num_as_vec(
468                _: *const *mut gobject_sys::GValue,
469                _: usize,
470            ) -> Vec<Self> {
471                // Can't free a *const
472                unimplemented!()
473            }
474
475            unsafe fn from_glib_full_num_as_vec(
476                _: *const *mut gobject_sys::GValue,
477                _: usize,
478            ) -> Vec<Self> {
479                // Can't free a *const
480                unimplemented!()
481            }
482        }
483
484        impl
485            FromGlibPtrArrayContainerAsVec<
486                *mut gobject_sys::GValue,
487                *const *mut gobject_sys::GValue,
488            > for $name
489        {
490            unsafe fn from_glib_none_as_vec(ptr: *const *mut gobject_sys::GValue) -> Vec<Self> {
491                FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
492            }
493
494            unsafe fn from_glib_container_as_vec(_: *const *mut gobject_sys::GValue) -> Vec<Self> {
495                // Can't free a *const
496                unimplemented!()
497            }
498
499            unsafe fn from_glib_full_as_vec(_: *const *mut gobject_sys::GValue) -> Vec<Self> {
500                // Can't free a *const
501                unimplemented!()
502            }
503        }
504    };
505}
506
507from_glib!(Value, |v| v);
508
509pub struct ValueArray(Vec<gobject_sys::GValue>);
510
511impl Drop for ValueArray {
512    fn drop(&mut self) {
513        unsafe {
514            for value in &mut self.0 {
515                // Before GLib 2.48, unsetting a zeroed GValue would give critical warnings
516                // https://bugzilla.gnome.org/show_bug.cgi?id=755766
517                if value.g_type != gobject_sys::G_TYPE_INVALID {
518                    gobject_sys::g_value_unset(value);
519                }
520            }
521        }
522    }
523}
524
525/// A statically typed [`Value`](struct.Value.html).
526///
527/// It dereferences to `Value` and can be used everywhere `Value` references are
528/// accepted.
529///
530/// See the [module documentation](index.html) for more details.
531#[derive(Clone)]
532#[repr(C)]
533pub struct TypedValue<T>(Value, PhantomData<*const T>);
534
535impl<'a, T: FromValueOptional<'a> + SetValue> TypedValue<T> {
536    /// Returns the value.
537    ///
538    /// Types that don't support a `None` value always return `Some`. See
539    /// `get_some`.
540    pub fn get(&'a self) -> Option<T> {
541        unsafe { T::from_value_optional(self) }
542    }
543
544    /// Returns the value.
545    ///
546    /// This method is only available for types that don't support a `None`
547    /// value.
548    pub fn get_some(&'a self) -> T
549    where
550        T: FromValue<'a>,
551    {
552        unsafe { T::from_value(self) }
553    }
554
555    /// Sets the value.
556    ///
557    /// This method is only available for types that support a `None` value.
558    pub fn set<U: ?Sized + SetValueOptional>(&mut self, value: Option<&U>)
559    where
560        T: Borrow<U>,
561    {
562        unsafe { SetValueOptional::set_value_optional(&mut self.0, value) }
563    }
564
565    /// Sets the value to `None`.
566    ///
567    /// This method is only available for types that support a `None` value.
568    pub fn set_none(&mut self)
569    where
570        T: SetValueOptional,
571    {
572        unsafe { T::set_value_optional(&mut self.0, None) }
573    }
574
575    /// Sets the value.
576    pub fn set_some<U: ?Sized + SetValue>(&mut self, value: &U)
577    where
578        T: Borrow<U>,
579    {
580        unsafe { SetValue::set_value(&mut self.0, value) }
581    }
582}
583
584impl<T> fmt::Debug for TypedValue<T> {
585    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
586        f.debug_tuple("TypedValue").field(&self.0).finish()
587    }
588}
589
590impl<'a, T: FromValueOptional<'a> + SetValue + Send> TypedValue<T> {
591    pub fn into_send_value(self) -> SendValue {
592        SendValue(self.0)
593    }
594}
595
596impl<T> Deref for TypedValue<T> {
597    type Target = Value;
598
599    fn deref(&self) -> &Value {
600        &self.0
601    }
602}
603
604impl<'a, T: FromValueOptional<'a> + SetValueOptional> From<Option<&'a T>> for TypedValue<T> {
605    fn from(value: Option<&'a T>) -> Self {
606        TypedValue(Value::from(value), PhantomData)
607    }
608}
609
610impl<'a, T: FromValueOptional<'a> + SetValue> From<&'a T> for TypedValue<T> {
611    fn from(value: &'a T) -> Self {
612        TypedValue(Value::from(value), PhantomData)
613    }
614}
615
616impl<'a> From<Option<&'a str>> for TypedValue<String> {
617    fn from(value: Option<&'a str>) -> Self {
618        TypedValue(Value::from(value), PhantomData)
619    }
620}
621
622impl<'a> From<&'a str> for TypedValue<String> {
623    fn from(value: &'a str) -> Self {
624        TypedValue(Value::from(value), PhantomData)
625    }
626}
627
628impl<'a> From<TypedValue<&'a str>> for TypedValue<String> {
629    fn from(value: TypedValue<&str>) -> Self {
630        TypedValue(value.0, PhantomData)
631    }
632}
633
634impl<'a> From<TypedValue<String>> for TypedValue<&'a str> {
635    fn from(value: TypedValue<String>) -> Self {
636        TypedValue(value.0, PhantomData)
637    }
638}
639
640#[doc(hidden)]
641impl<'a, T: 'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for TypedValue<T> {
642    type Storage = &'a mut TypedValue<T>;
643
644    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
645        StashMut(&mut (self.0).0, self)
646    }
647}
648
649/// Converts to `Value`.
650pub trait ToValue {
651    /// Returns a `Value` clone of `self`.
652    fn to_value(&self) -> Value;
653
654    /// Returns the type identifer of `self`.
655    ///
656    /// This is the type of the value to be returned by `to_value`.
657    fn to_value_type(&self) -> Type;
658}
659
660impl<T: SetValueOptional> ToValue for Option<T> {
661    fn to_value(&self) -> Value {
662        unsafe {
663            let mut ret = Value::from_type(T::static_type());
664            T::set_value_optional(&mut ret, self.as_ref());
665            ret
666        }
667    }
668
669    #[inline]
670    fn to_value_type(&self) -> Type {
671        T::static_type()
672    }
673}
674
675impl<T: ?Sized + SetValue> ToValue for T {
676    fn to_value(&self) -> Value {
677        unsafe {
678            let mut ret = Value::from_type(T::static_type());
679            T::set_value(&mut ret, self);
680            ret
681        }
682    }
683
684    #[inline]
685    fn to_value_type(&self) -> Type {
686        T::static_type()
687    }
688}
689
690impl ToValue for Value {
691    fn to_value(&self) -> Value {
692        self.clone()
693    }
694
695    fn to_value_type(&self) -> Type {
696        self.type_()
697    }
698}
699
700/// A version of [`Value`](struct.Value.html) for storing `Send` types, that implements Send
701/// itself.
702///
703/// See the [module documentation](index.html) for more details.
704#[derive(Clone)]
705#[repr(C)]
706pub struct SendValue(Value);
707unsafe impl Send for SendValue {}
708
709impl SendValue {
710    /// Tries to downcast to a `TypedValue`.
711    ///
712    /// Returns `Ok(TypedValue<T>)` if the value carries a type corresponding
713    /// to `T` and `Err(self)` otherwise.
714    pub fn downcast<'a, T: FromValueOptional<'a> + SetValue + Send>(
715        self,
716    ) -> Result<TypedValue<T>, Self> {
717        self.0.downcast().map_err(SendValue)
718    }
719
720    /// Tries to downcast to a `&TypedValue`.
721    ///
722    /// Returns `Some(&TypedValue<T>)` if the value carries a type corresponding
723    /// to `T` and `None` otherwise.
724    pub fn downcast_ref<'a, T: FromValueOptional<'a> + SetValue>(&self) -> Option<&TypedValue<T>> {
725        unsafe {
726            let ok = from_glib(gobject_sys::g_type_check_value_holds(
727                mut_override(self.to_glib_none().0),
728                T::static_type().to_glib(),
729            ));
730            if ok {
731                // This transmute is safe because SendValue and TypedValue have the same
732                // representation: the only difference is the zero-sized phantom data
733                Some(&*(self as *const SendValue as *const TypedValue<T>))
734            } else {
735                None
736            }
737        }
738    }
739
740    #[doc(hidden)]
741    pub fn into_raw(self) -> gobject_sys::GValue {
742        self.0.into_raw()
743    }
744}
745
746impl fmt::Debug for SendValue {
747    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
748        f.debug_tuple("SendValue").field(&self.0).finish()
749    }
750}
751
752impl Deref for SendValue {
753    type Target = Value;
754
755    fn deref(&self) -> &Value {
756        &self.0
757    }
758}
759
760impl<'a, T: ?Sized + SetValueOptional + Send> From<Option<&'a T>> for SendValue {
761    #[inline]
762    fn from(value: Option<&'a T>) -> Self {
763        SendValue(value.to_value())
764    }
765}
766
767impl<'a, T: ?Sized + SetValue + Send> From<&'a T> for SendValue {
768    #[inline]
769    fn from(value: &'a T) -> Self {
770        SendValue(value.to_value())
771    }
772}
773
774impl<T: Send> From<TypedValue<T>> for SendValue {
775    fn from(value: TypedValue<T>) -> Self {
776        SendValue(value.0)
777    }
778}
779
780from_glib!(SendValue, SendValue);
781
782#[doc(hidden)]
783impl<'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for SendValue {
784    type Storage = &'a mut SendValue;
785
786    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
787        StashMut(&mut (self.0).0, self)
788    }
789}
790
791/// Converts to `SendValue`.
792pub trait ToSendValue: Send + ToValue {
793    /// Returns a `SendValue` clone of `self`.
794    fn to_send_value(&self) -> SendValue;
795}
796
797impl<T: SetValueOptional + Send + ToValue> ToSendValue for Option<T> {
798    fn to_send_value(&self) -> SendValue {
799        SendValue(self.to_value())
800    }
801}
802
803impl<T: ?Sized + SetValue + Send + ToValue> ToSendValue for T {
804    fn to_send_value(&self) -> SendValue {
805        SendValue(self.to_value())
806    }
807}
808
809impl ToSendValue for SendValue {
810    fn to_send_value(&self) -> SendValue {
811        self.clone()
812    }
813}
814
815impl ToValue for SendValue {
816    fn to_value(&self) -> Value {
817        self.0.clone()
818    }
819
820    fn to_value_type(&self) -> Type {
821        self.type_()
822    }
823}
824
825/// Extracts a value.
826///
827/// Types that don't support a `None` value always return `Some`.
828pub trait FromValueOptional<'a>: StaticType + Sized {
829    unsafe fn from_value_optional(&'a Value) -> Option<Self>;
830}
831
832/// Extracts a value.
833///
834/// Only implemented for types that don't support a `None` value.
835pub trait FromValue<'a>: FromValueOptional<'a> {
836    unsafe fn from_value(&'a Value) -> Self;
837}
838
839/// Sets a value.
840///
841/// Only implemented for types that support a `None` value.
842pub trait SetValueOptional: SetValue {
843    unsafe fn set_value_optional(&mut Value, Option<&Self>);
844}
845
846/// Sets a value.
847pub trait SetValue: StaticType {
848    unsafe fn set_value(&mut Value, &Self);
849}
850
851impl<'a> FromValueOptional<'a> for String {
852    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
853        from_glib_none(gobject_sys::g_value_get_string(value.to_glib_none().0))
854    }
855}
856
857impl<'a> FromValueOptional<'a> for &'a str {
858    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
859        let cstr = gobject_sys::g_value_get_string(value.to_glib_none().0);
860        if cstr.is_null() {
861            None
862        } else {
863            CStr::from_ptr(cstr).to_str().ok()
864        }
865    }
866}
867
868impl SetValue for str {
869    unsafe fn set_value(value: &mut Value, this: &Self) {
870        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
871    }
872}
873
874impl SetValueOptional for str {
875    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
876        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
877    }
878}
879
880impl<'a> FromValueOptional<'a> for Vec<String> {
881    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
882        Some(<Vec<String> as FromValue>::from_value(value))
883    }
884}
885
886impl<'a> FromValue<'a> for Vec<String> {
887    unsafe fn from_value(value: &'a Value) -> Self {
888        let ptr = gobject_sys::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
889        FromGlibPtrContainer::from_glib_none(ptr)
890    }
891}
892
893impl<'a> FromValueOptional<'a> for Vec<GString> {
894    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
895        Some(<Vec<GString> as FromValue>::from_value(value))
896    }
897}
898
899impl<'a> FromValue<'a> for Vec<GString> {
900    unsafe fn from_value(value: &'a Value) -> Self {
901        let ptr = gobject_sys::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
902        FromGlibPtrContainer::from_glib_none(ptr)
903    }
904}
905
906impl<'a> SetValue for [&'a str] {
907    unsafe fn set_value(value: &mut Value, this: &Self) {
908        let ptr: *mut *mut c_char = this.to_glib_full();
909        gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
910    }
911}
912
913impl<'a> SetValueOptional for [&'a str] {
914    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
915        let ptr: *mut *mut c_char = this.to_glib_full();
916        gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
917    }
918}
919
920impl SetValue for Vec<String> {
921    unsafe fn set_value(value: &mut Value, this: &Self) {
922        let ptr: *mut *mut c_char = this.to_glib_full();
923        gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
924    }
925}
926
927impl SetValueOptional for Vec<String> {
928    #[allow(clippy::redundant_closure)]
929    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
930        let ptr: *mut *mut c_char = this.map(|v| v.to_glib_full()).unwrap_or(ptr::null_mut());
931        gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
932    }
933}
934
935impl<'a, T: ?Sized + SetValue> SetValue for &'a T {
936    unsafe fn set_value(value: &mut Value, this: &Self) {
937        SetValue::set_value(value, *this)
938    }
939}
940
941impl<'a, T: ?Sized + SetValueOptional> SetValueOptional for &'a T {
942    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
943        SetValueOptional::set_value_optional(value, this.cloned())
944    }
945}
946
947impl SetValue for String {
948    unsafe fn set_value(value: &mut Value, this: &Self) {
949        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
950    }
951}
952
953impl SetValueOptional for String {
954    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
955        gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
956    }
957}
958
959impl<'a> FromValueOptional<'a> for bool {
960    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
961        Some(from_glib(gobject_sys::g_value_get_boolean(
962            value.to_glib_none().0,
963        )))
964    }
965}
966
967impl<'a> FromValue<'a> for bool {
968    unsafe fn from_value(value: &'a Value) -> Self {
969        from_glib(gobject_sys::g_value_get_boolean(value.to_glib_none().0))
970    }
971}
972
973impl SetValue for bool {
974    unsafe fn set_value(value: &mut Value, this: &Self) {
975        gobject_sys::g_value_set_boolean(value.to_glib_none_mut().0, this.to_glib())
976    }
977}
978
979macro_rules! numeric {
980    ($name:ident, $get:ident, $set:ident) => {
981        impl<'a> FromValueOptional<'a> for $name {
982            unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
983                Some(gobject_sys::$get(value.to_glib_none().0))
984            }
985        }
986
987        impl<'a> FromValue<'a> for $name {
988            unsafe fn from_value(value: &'a Value) -> Self {
989                gobject_sys::$get(value.to_glib_none().0)
990            }
991        }
992
993        impl SetValue for $name {
994            unsafe fn set_value(value: &mut Value, this: &Self) {
995                gobject_sys::$set(value.to_glib_none_mut().0, *this)
996            }
997        }
998    };
999}
1000
1001numeric!(i8, g_value_get_schar, g_value_set_schar);
1002numeric!(u8, g_value_get_uchar, g_value_set_uchar);
1003numeric!(i32, g_value_get_int, g_value_set_int);
1004numeric!(u32, g_value_get_uint, g_value_set_uint);
1005numeric!(i64, g_value_get_int64, g_value_set_int64);
1006numeric!(u64, g_value_get_uint64, g_value_set_uint64);
1007numeric!(f32, g_value_get_float, g_value_set_float);
1008numeric!(f64, g_value_get_double, g_value_set_double);
1009
1010#[cfg(test)]
1011mod tests {
1012    use super::*;
1013
1014    #[test]
1015    fn test_send_value() {
1016        use std::thread;
1017
1018        let v = SendValue::from(&1i32);
1019
1020        // Must compile, while it must fail with Value
1021        thread::spawn(move || drop(v)).join().unwrap();
1022    }
1023
1024    #[test]
1025    fn test_strv() {
1026        let v = vec!["123", "456"].to_value();
1027        assert_eq!(
1028            v.get::<Vec<GString>>(),
1029            Some(vec![GString::from("123"), GString::from("456")])
1030        );
1031
1032        let v = vec![String::from("123"), String::from("456")].to_value();
1033        assert_eq!(
1034            v.get::<Vec<GString>>(),
1035            Some(vec![GString::from("123"), GString::from("456")])
1036        );
1037    }
1038}