Skip to main content

zvariant/
value.rs

1use core::{
2    cmp::Ordering,
3    fmt::{Display, Write},
4    hash::{Hash, Hasher},
5    marker::PhantomData,
6    mem::discriminant,
7    str,
8};
9
10use serde::{
11    de::{
12        Deserialize, DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Unexpected,
13        Visitor,
14    },
15    ser::{
16        Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer,
17    },
18};
19
20use crate::{
21    Array, Basic, Dict, DynamicType, ObjectPath, OwnedValue, Signature, Str, Structure,
22    StructureBuilder, Type, array_display_fmt, dict_display_fmt, structure_display_fmt, utils::*,
23};
24#[cfg(feature = "gvariant")]
25#[allow(deprecated)]
26use crate::{Maybe, maybe_display_fmt};
27
28#[cfg(unix)]
29use crate::Fd;
30
31/// A generic container, in the form of an enum that holds exactly one value of any of the other
32/// types.
33///
34/// Note that this type corresponds to the `VARIANT` data type defined by the [D-Bus specification]
35/// and as such, its encoding is not the same as that of the enclosed value.
36///
37/// # Examples
38///
39/// ```
40/// use zvariant::{to_bytes, serialized::Context, Value, LE};
41///
42/// // Create a Value from an i16
43/// let v = Value::new(i16::max_value());
44///
45/// // Encode it
46/// let ctxt = Context::new_dbus(LE, 0);
47/// let encoding = to_bytes(ctxt, &v).unwrap();
48///
49/// // Decode it back
50/// let v: Value = encoding.deserialize().unwrap().0;
51///
52/// // Check everything is as expected
53/// assert_eq!(i16::try_from(&v).unwrap(), i16::max_value());
54/// ```
55///
56/// Now let's try a more complicated example:
57///
58/// ```
59/// use zvariant::{to_bytes, serialized::Context, LE};
60/// use zvariant::{Structure, Value, Str};
61///
62/// // Create a Value from a tuple this time
63/// let v = Value::new((i16::max_value(), "hello", true));
64///
65/// // Same drill as previous example
66/// let ctxt = Context::new_dbus(LE, 0);
67/// let encoding = to_bytes(ctxt, &v).unwrap();
68/// let v: Value = encoding.deserialize().unwrap().0;
69///
70/// // Check everything is as expected
71/// let s = Structure::try_from(v).unwrap();
72/// assert_eq!(
73///     <(i16, Str, bool)>::try_from(s).unwrap(),
74///     (i16::max_value(), Str::from("hello"), true),
75/// );
76/// ```
77///
78/// [D-Bus specification]: https://dbus.freedesktop.org/doc/dbus-specification.html#container-types
79#[derive(Debug, PartialEq, PartialOrd)]
80pub enum Value<'a> {
81    // Simple types
82    U8(u8),
83    Bool(bool),
84    I16(i16),
85    U16(u16),
86    I32(i32),
87    U32(u32),
88    I64(i64),
89    U64(u64),
90    F64(f64),
91    Str(Str<'a>),
92    Signature(Signature),
93    ObjectPath(ObjectPath<'a>),
94    Value(Box<Value<'a>>),
95
96    // Container types
97    Array(Array<'a>),
98    Dict(Dict<'a, 'a>),
99    Structure(Structure<'a>),
100    #[cfg(feature = "gvariant")]
101    #[deprecated(
102        since = "5.15.0",
103        note = "GVariant support is deprecated and will be removed in zvariant 6.0. Use the \
104                `zgvariant` crate instead."
105    )]
106    #[allow(deprecated)]
107    Maybe(Maybe<'a>),
108
109    #[cfg(unix)]
110    Fd(Fd<'a>),
111}
112
113impl Hash for Value<'_> {
114    fn hash<H: Hasher>(&self, state: &mut H) {
115        discriminant(self).hash(state);
116        match self {
117            Self::U8(inner) => inner.hash(state),
118            Self::Bool(inner) => inner.hash(state),
119            Self::I16(inner) => inner.hash(state),
120            Self::U16(inner) => inner.hash(state),
121            Self::I32(inner) => inner.hash(state),
122            Self::U32(inner) => inner.hash(state),
123            Self::I64(inner) => inner.hash(state),
124            Self::U64(inner) => inner.hash(state),
125            // To hold the +0.0 == -0.0 => hash(+0.0) == hash(-0.0) property.
126            // See https://doc.rust-lang.org/beta/std/hash/trait.Hash.html#hash-and-eq
127            Self::F64(inner) if *inner == 0. => 0f64.to_le_bytes().hash(state),
128            Self::F64(inner) => inner.to_le_bytes().hash(state),
129            Self::Str(inner) => inner.hash(state),
130            Self::Signature(inner) => inner.hash(state),
131            Self::ObjectPath(inner) => inner.hash(state),
132            Self::Value(inner) => inner.hash(state),
133            Self::Array(inner) => inner.hash(state),
134            Self::Dict(inner) => inner.hash(state),
135            Self::Structure(inner) => inner.hash(state),
136            #[cfg(feature = "gvariant")]
137            #[allow(deprecated)]
138            Self::Maybe(inner) => inner.hash(state),
139            #[cfg(unix)]
140            Self::Fd(inner) => inner.hash(state),
141        }
142    }
143}
144
145impl Eq for Value<'_> {}
146
147impl Ord for Value<'_> {
148    fn cmp(&self, other: &Self) -> Ordering {
149        self.partial_cmp(other)
150            .unwrap_or_else(|| match (self, other) {
151                (Self::F64(lhs), Self::F64(rhs)) => lhs.total_cmp(rhs),
152                // `partial_cmp` returns `Some(_)` if either the discriminants are different
153                // or if both the left hand side and right hand side is `Self::F64(_)`. We can only
154                // reach this arm, if only one of the sides is `Self::F64(_)`. So we can just
155                // pretend the ordering is equal.
156                _ => Ordering::Equal,
157            })
158    }
159}
160
161macro_rules! serialize_value {
162    ($self:ident $serializer:ident.$method:ident $($first_arg:expr)*) => {
163        match $self {
164            Value::U8(value) => $serializer.$method($($first_arg,)* value),
165            Value::Bool(value) => $serializer.$method($($first_arg,)* value),
166            Value::I16(value) => $serializer.$method($($first_arg,)* value),
167            Value::U16(value) => $serializer.$method($($first_arg,)* value),
168            Value::I32(value) => $serializer.$method($($first_arg,)* value),
169            Value::U32(value) => $serializer.$method($($first_arg,)* value),
170            Value::I64(value) => $serializer.$method($($first_arg,)* value),
171            Value::U64(value) => $serializer.$method($($first_arg,)* value),
172            Value::F64(value) => $serializer.$method($($first_arg,)* value),
173            Value::Str(value) => $serializer.$method($($first_arg,)* value),
174            Value::Signature(value) => $serializer.$method($($first_arg,)* value),
175            Value::ObjectPath(value) => $serializer.$method($($first_arg,)* value),
176            Value::Value(value) => $serializer.$method($($first_arg,)* value),
177
178            // Container types
179            Value::Array(value) => $serializer.$method($($first_arg,)* value),
180            Value::Dict(value) => $serializer.$method($($first_arg,)* value),
181            Value::Structure(value) => $serializer.$method($($first_arg,)* value),
182            #[cfg(feature = "gvariant")]
183            #[allow(deprecated)]
184            Value::Maybe(value) => $serializer.$method($($first_arg,)* value),
185
186            #[cfg(unix)]
187            Value::Fd(value) => $serializer.$method($($first_arg,)* value),
188        }
189    }
190}
191
192impl<'a> Value<'a> {
193    /// Make a [`Value`] for a given value.
194    ///
195    /// In general, you can use [`Into`] trait on basic types, except
196    /// when you explicitly need to wrap [`Value`] itself, in which
197    /// case this constructor comes handy.
198    ///
199    /// # Examples
200    ///
201    /// ```
202    /// use zvariant::Value;
203    ///
204    /// let s = Value::new("hello");
205    /// let u: Value = 51.into();
206    /// assert_ne!(s, u);
207    /// ```
208    ///
209    /// [`Value`]: enum.Value.html
210    /// [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html
211    pub fn new<T>(value: T) -> Self
212    where
213        T: Into<Self> + DynamicType,
214    {
215        // With specialization, we wouldn't have this
216        if value.signature() == VARIANT_SIGNATURE_STR {
217            Self::Value(Box::new(value.into()))
218        } else {
219            value.into()
220        }
221    }
222
223    /// Try to create an owned version of `self`.
224    ///
225    /// # Errors
226    ///
227    /// This method can currently only fail on Unix platforms for [`Value::Fd`] variant. This
228    /// happens when the current process exceeds the maximum number of open file descriptors.
229    pub fn try_to_owned(&self) -> crate::Result<OwnedValue> {
230        Ok(OwnedValue(match self {
231            Value::U8(v) => Value::U8(*v),
232            Value::Bool(v) => Value::Bool(*v),
233            Value::I16(v) => Value::I16(*v),
234            Value::U16(v) => Value::U16(*v),
235            Value::I32(v) => Value::I32(*v),
236            Value::U32(v) => Value::U32(*v),
237            Value::I64(v) => Value::I64(*v),
238            Value::U64(v) => Value::U64(*v),
239            Value::F64(v) => Value::F64(*v),
240            Value::Str(v) => Value::Str(v.to_owned()),
241            Value::Signature(v) => Value::Signature(v.to_owned()),
242            Value::ObjectPath(v) => Value::ObjectPath(v.to_owned()),
243            Value::Value(v) => {
244                let o = OwnedValue::try_from(&**v)?;
245                Value::Value(Box::new(o.into_inner()))
246            }
247
248            Value::Array(v) => Value::Array(v.try_to_owned()?),
249            Value::Dict(v) => Value::Dict(v.try_to_owned()?),
250            Value::Structure(v) => Value::Structure(v.try_to_owned()?),
251            #[cfg(feature = "gvariant")]
252            #[allow(deprecated)]
253            Value::Maybe(v) => Value::Maybe(v.try_to_owned()?),
254            #[cfg(unix)]
255            Value::Fd(v) => Value::Fd(v.try_to_owned()?),
256        }))
257    }
258
259    /// Creates an owned value from `self`.
260    ///
261    /// This method can currently only fail on Unix platforms for [`Value::Fd`] variant containing
262    /// an [`Fd::Owned`] variant. This happens when the current process exceeds the maximum number
263    /// of open file descriptors.
264    ///
265    /// Results in an extra allocation if the value contains borrowed data.
266    pub fn try_into_owned(self) -> crate::Result<OwnedValue> {
267        Ok(OwnedValue(match self {
268            Value::U8(v) => Value::U8(v),
269            Value::Bool(v) => Value::Bool(v),
270            Value::I16(v) => Value::I16(v),
271            Value::U16(v) => Value::U16(v),
272            Value::I32(v) => Value::I32(v),
273            Value::U32(v) => Value::U32(v),
274            Value::I64(v) => Value::I64(v),
275            Value::U64(v) => Value::U64(v),
276            Value::F64(v) => Value::F64(v),
277            Value::Str(v) => Value::Str(v.into_owned()),
278            Value::Signature(v) => Value::Signature(v),
279            Value::ObjectPath(v) => Value::ObjectPath(v.into_owned()),
280            Value::Value(v) => Value::Value(Box::new(v.try_into_owned()?.into())),
281            Value::Array(v) => Value::Array(v.try_into_owned()?),
282            Value::Dict(v) => Value::Dict(v.try_into_owned()?),
283            Value::Structure(v) => Value::Structure(v.try_into_owned()?),
284            #[cfg(feature = "gvariant")]
285            #[allow(deprecated)]
286            Value::Maybe(v) => Value::Maybe(v.try_into_owned()?),
287            #[cfg(unix)]
288            Value::Fd(v) => Value::Fd(v.try_to_owned()?),
289        }))
290    }
291
292    /// Get the signature of the enclosed value.
293    pub fn value_signature(&self) -> &Signature {
294        match self {
295            Value::U8(_) => u8::SIGNATURE,
296            Value::Bool(_) => bool::SIGNATURE,
297            Value::I16(_) => i16::SIGNATURE,
298            Value::U16(_) => u16::SIGNATURE,
299            Value::I32(_) => i32::SIGNATURE,
300            Value::U32(_) => u32::SIGNATURE,
301            Value::I64(_) => i64::SIGNATURE,
302            Value::U64(_) => u64::SIGNATURE,
303            Value::F64(_) => f64::SIGNATURE,
304            Value::Str(_) => <&str>::SIGNATURE,
305            Value::Signature(_) => Signature::SIGNATURE,
306            Value::ObjectPath(_) => ObjectPath::SIGNATURE,
307            Value::Value(_) => &Signature::Variant,
308
309            // Container types
310            Value::Array(value) => value.signature(),
311            Value::Dict(value) => value.signature(),
312            Value::Structure(value) => value.signature(),
313            #[cfg(feature = "gvariant")]
314            #[allow(deprecated)]
315            Value::Maybe(value) => value.signature(),
316
317            #[cfg(unix)]
318            Value::Fd(_) => Fd::SIGNATURE,
319        }
320    }
321
322    /// Try to clone the value.
323    ///
324    /// # Errors
325    ///
326    /// This method can currently only fail on Unix platforms for [`Value::Fd`] variant containing
327    /// an [`Fd::Owned`] variant. This happens when the current process exceeds the maximum number
328    /// of open file descriptors.
329    pub fn try_clone(&self) -> crate::Result<Self> {
330        Ok(match self {
331            Value::U8(v) => Value::U8(*v),
332            Value::Bool(v) => Value::Bool(*v),
333            Value::I16(v) => Value::I16(*v),
334            Value::U16(v) => Value::U16(*v),
335            Value::I32(v) => Value::I32(*v),
336            Value::U32(v) => Value::U32(*v),
337            Value::I64(v) => Value::I64(*v),
338            Value::U64(v) => Value::U64(*v),
339            Value::F64(v) => Value::F64(*v),
340            Value::Str(v) => Value::Str(v.clone()),
341            Value::Signature(v) => Value::Signature(v.clone()),
342            Value::ObjectPath(v) => Value::ObjectPath(v.clone()),
343            Value::Value(v) => Value::Value(Box::new(v.try_clone()?)),
344            Value::Array(v) => Value::Array(v.try_clone()?),
345            Value::Dict(v) => Value::Dict(v.try_clone()?),
346            Value::Structure(v) => Value::Structure(v.try_clone()?),
347            #[cfg(feature = "gvariant")]
348            #[allow(deprecated)]
349            Value::Maybe(v) => Value::Maybe(v.try_clone()?),
350            #[cfg(unix)]
351            Value::Fd(v) => Value::Fd(v.try_clone()?),
352        })
353    }
354
355    pub(crate) fn serialize_value_as_struct_field<S>(
356        &self,
357        name: &'static str,
358        serializer: &mut S,
359    ) -> Result<(), S::Error>
360    where
361        S: SerializeStruct,
362    {
363        serialize_value!(self serializer.serialize_field name)
364    }
365
366    pub(crate) fn serialize_value_as_tuple_struct_field<S>(
367        &self,
368        serializer: &mut S,
369    ) -> Result<(), S::Error>
370    where
371        S: SerializeTupleStruct,
372    {
373        serialize_value!(self serializer.serialize_field)
374    }
375
376    // Really crappy that we need to do this separately for struct and seq cases. :(
377    pub(crate) fn serialize_value_as_seq_element<S>(
378        &self,
379        serializer: &mut S,
380    ) -> Result<(), S::Error>
381    where
382        S: SerializeSeq,
383    {
384        serialize_value!(self serializer.serialize_element)
385    }
386
387    pub(crate) fn serialize_value_as_dict_key<S>(&self, serializer: &mut S) -> Result<(), S::Error>
388    where
389        S: SerializeMap,
390    {
391        serialize_value!(self serializer.serialize_key)
392    }
393
394    pub(crate) fn serialize_value_as_dict_value<S>(
395        &self,
396        serializer: &mut S,
397    ) -> Result<(), S::Error>
398    where
399        S: SerializeMap,
400    {
401        serialize_value!(self serializer.serialize_value)
402    }
403
404    #[cfg(feature = "gvariant")]
405    pub(crate) fn serialize_value_as_some<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
406    where
407        S: Serializer,
408    {
409        serialize_value!(self serializer.serialize_some)
410    }
411
412    /// Try to get the underlying type `T`.
413    ///
414    /// Note that [`TryFrom<Value>`] is implemented for various types, and it's usually best to use
415    /// that instead. However, in generic code where you also want to unwrap [`Value::Value`],
416    /// you should use this function (because [`TryFrom<Value>`] can not be implemented for `Value`
417    /// itself as [`From<Value>`] is implicitly implemented for `Value`).
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use zvariant::{Error, Result, Value};
423    ///
424    /// fn value_vec_to_type_vec<'a, T>(values: Vec<Value<'a>>) -> Result<Vec<T>>
425    /// where
426    ///     T: TryFrom<Value<'a>>,
427    ///     <T as TryFrom<Value<'a>>>::Error: Into<Error>,
428    /// {
429    ///     let mut res = vec![];
430    ///     for value in values.into_iter() {
431    ///         res.push(value.downcast()?);
432    ///     }
433    ///
434    ///     Ok(res)
435    /// }
436    ///
437    /// // Let's try u32 values first
438    /// let v = vec![Value::U32(42), Value::U32(43)];
439    /// let v = value_vec_to_type_vec::<u32>(v).unwrap();
440    /// assert_eq!(v[0], 42);
441    /// assert_eq!(v[1], 43);
442    ///
443    /// // Now try Value values
444    /// let v = vec![Value::new(Value::U32(42)), Value::new(Value::U32(43))];
445    /// let v = value_vec_to_type_vec::<Value>(v).unwrap();
446    /// assert_eq!(v[0], Value::U32(42));
447    /// assert_eq!(v[1], Value::U32(43));
448    /// ```
449    ///
450    /// [`Value::Value`]: enum.Value.html#variant.Value
451    /// [`TryFrom<Value>`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html
452    /// [`From<Value>`]: https://doc.rust-lang.org/std/convert/trait.From.html
453    pub fn downcast<T>(self) -> Result<T, crate::Error>
454    where
455        T: TryFrom<Value<'a>>,
456        <T as TryFrom<Value<'a>>>::Error: Into<crate::Error>,
457    {
458        if let Value::Value(v) = self {
459            T::try_from(*v)
460        } else {
461            T::try_from(self)
462        }
463        .map_err(Into::into)
464    }
465
466    /// Try to get the underlying type `T`.
467    ///
468    /// Same as [`downcast`] except it doesn't consume `self` and hence requires
469    /// `T: TryFrom<&Value<_>>`.
470    ///
471    /// # Examples
472    ///
473    /// ```
474    /// use zvariant::{Error, Result, Value};
475    ///
476    /// fn value_vec_to_type_vec<'a, T>(values: &'a Vec<Value<'a>>) -> Result<Vec<&'a T>>
477    /// where
478    ///     &'a T: TryFrom<&'a Value<'a>>,
479    ///     <&'a T as TryFrom<&'a Value<'a>>>::Error: Into<Error>,
480    /// {
481    ///     let mut res = vec![];
482    ///     for value in values.into_iter() {
483    ///         res.push(value.downcast_ref()?);
484    ///     }
485    ///
486    ///     Ok(res)
487    /// }
488    ///
489    /// // Let's try u32 values first
490    /// let v = vec![Value::U32(42), Value::U32(43)];
491    /// let v = value_vec_to_type_vec::<u32>(&v).unwrap();
492    /// assert_eq!(*v[0], 42);
493    /// assert_eq!(*v[1], 43);
494    ///
495    /// // Now try Value values
496    /// let v = vec![Value::new(Value::U32(42)), Value::new(Value::U32(43))];
497    /// let v = value_vec_to_type_vec::<Value>(&v).unwrap();
498    /// assert_eq!(*v[0], Value::U32(42));
499    /// assert_eq!(*v[1], Value::U32(43));
500    /// ```
501    ///
502    /// [`downcast`]: enum.Value.html#method.downcast
503    pub fn downcast_ref<T>(&'a self) -> Result<T, crate::Error>
504    where
505        T: TryFrom<&'a Value<'a>>,
506        <T as TryFrom<&'a Value<'a>>>::Error: Into<crate::Error>,
507    {
508        if let Value::Value(v) = self {
509            <T>::try_from(v)
510        } else {
511            <T>::try_from(self)
512        }
513        .map_err(Into::into)
514    }
515}
516
517impl Display for Value<'_> {
518    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
519        value_display_fmt(self, f, true)
520    }
521}
522
523/// Implemented based on https://gitlab.gnome.org/GNOME/glib/-/blob/e1d47f0b0d0893ac9171e24cc7bf635495376546/glib/gvariant.c#L2213
524pub(crate) fn value_display_fmt(
525    value: &Value<'_>,
526    f: &mut std::fmt::Formatter<'_>,
527    type_annotate: bool,
528) -> std::fmt::Result {
529    match value {
530        Value::U8(num) => {
531            if type_annotate {
532                f.write_str("byte ")?;
533            }
534            write!(f, "0x{num:02x}")
535        }
536        Value::Bool(boolean) => {
537            write!(f, "{boolean}")
538        }
539        Value::I16(num) => {
540            if type_annotate {
541                f.write_str("int16 ")?;
542            }
543            write!(f, "{num}")
544        }
545        Value::U16(num) => {
546            if type_annotate {
547                f.write_str("uint16 ")?;
548            }
549            write!(f, "{num}")
550        }
551        Value::I32(num) => {
552            // Never annotate this type because it is the default for numbers
553            write!(f, "{num}")
554        }
555        Value::U32(num) => {
556            if type_annotate {
557                f.write_str("uint32 ")?;
558            }
559            write!(f, "{num}")
560        }
561        Value::I64(num) => {
562            if type_annotate {
563                f.write_str("int64 ")?;
564            }
565            write!(f, "{num}")
566        }
567        Value::U64(num) => {
568            if type_annotate {
569                f.write_str("uint64 ")?;
570            }
571            write!(f, "{num}")
572        }
573        Value::F64(num) => {
574            if num.fract() == 0. {
575                // Add a dot to make it clear that this is a float
576                write!(f, "{num}.")
577            } else {
578                write!(f, "{num}")
579            }
580        }
581        Value::Str(string) => {
582            write!(f, "{:?}", string.as_str())
583        }
584        Value::Signature(val) => {
585            if type_annotate {
586                f.write_str("signature ")?;
587            }
588            write!(f, "{:?}", val.to_string())
589        }
590        Value::ObjectPath(val) => {
591            if type_annotate {
592                f.write_str("objectpath ")?;
593            }
594            write!(f, "{:?}", val.as_str())
595        }
596        Value::Value(child) => {
597            f.write_char('<')?;
598
599            // Always annotate types in nested variants, because they are (by nature) of
600            // variable type.
601            value_display_fmt(child, f, true)?;
602
603            f.write_char('>')?;
604            Ok(())
605        }
606        Value::Array(array) => array_display_fmt(array, f, type_annotate),
607        Value::Dict(dict) => dict_display_fmt(dict, f, type_annotate),
608        Value::Structure(structure) => structure_display_fmt(structure, f, type_annotate),
609        #[cfg(feature = "gvariant")]
610        #[allow(deprecated)]
611        Value::Maybe(maybe) => maybe_display_fmt(maybe, f, type_annotate),
612        #[cfg(unix)]
613        Value::Fd(handle) => {
614            if type_annotate {
615                f.write_str("handle ")?;
616            }
617            write!(f, "{handle}")
618        }
619    }
620}
621
622impl Serialize for Value<'_> {
623    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
624    where
625        S: Serializer,
626    {
627        // Serializer implementation needs to ensure padding isn't added for Value.
628        let mut structure = serializer.serialize_struct("Variant", 2)?;
629
630        let signature = self.value_signature();
631        structure.serialize_field("signature", &signature)?;
632
633        self.serialize_value_as_struct_field("value", &mut structure)?;
634
635        structure.end()
636    }
637}
638
639impl<'de: 'a, 'a> Deserialize<'de> for Value<'a> {
640    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
641    where
642        D: Deserializer<'de>,
643    {
644        let visitor = ValueVisitor;
645
646        deserializer.deserialize_any(visitor)
647    }
648}
649
650struct ValueVisitor;
651
652impl<'de> Visitor<'de> for ValueVisitor {
653    type Value = Value<'de>;
654
655    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
656        formatter.write_str("a Value")
657    }
658
659    fn visit_seq<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
660    where
661        V: SeqAccess<'de>,
662    {
663        let signature = visitor.next_element::<Signature>()?.ok_or_else(|| {
664            Error::invalid_value(Unexpected::Other("nothing"), &"a Value signature")
665        })?;
666        let seed = ValueSeed::<Value<'_>> {
667            signature: &signature,
668            phantom: PhantomData,
669        };
670
671        visitor
672            .next_element_seed(seed)?
673            .ok_or_else(|| Error::invalid_value(Unexpected::Other("nothing"), &"a Value value"))
674    }
675
676    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
677    where
678        V: MapAccess<'de>,
679    {
680        let (_, signature) = visitor.next_entry::<&str, Signature>()?.ok_or_else(|| {
681            Error::invalid_value(Unexpected::Other("nothing"), &"a Value signature")
682        })?;
683        let _ = visitor.next_key::<&str>()?;
684
685        let seed = ValueSeed::<Value<'_>> {
686            signature: &signature,
687            phantom: PhantomData,
688        };
689        visitor.next_value_seed(seed)
690    }
691}
692
693pub(crate) struct SignatureSeed<'sig> {
694    pub signature: &'sig Signature,
695}
696
697impl SignatureSeed<'_> {
698    pub(crate) fn visit_array<'de, V>(self, mut visitor: V) -> Result<Array<'de>, V::Error>
699    where
700        V: SeqAccess<'de>,
701    {
702        let element_signature = match self.signature {
703            Signature::Array(child) => child.signature(),
704            _ => {
705                return Err(Error::invalid_type(
706                    Unexpected::Str(&self.signature.to_string()),
707                    &"an array signature",
708                ));
709            }
710        };
711        let mut array = Array::new_full_signature(self.signature);
712
713        while let Some(elem) = visitor.next_element_seed(ValueSeed::<Value<'_>> {
714            signature: element_signature,
715            phantom: PhantomData,
716        })? {
717            elem.value_signature();
718            array.append(elem).map_err(Error::custom)?;
719        }
720
721        Ok(array)
722    }
723
724    pub(crate) fn visit_struct<'de, V>(self, mut visitor: V) -> Result<Structure<'de>, V::Error>
725    where
726        V: SeqAccess<'de>,
727    {
728        let fields_signatures = match self.signature {
729            Signature::Structure(fields) => fields.iter(),
730            _ => {
731                return Err(Error::invalid_type(
732                    Unexpected::Str(&self.signature.to_string()),
733                    &"a structure signature",
734                ));
735            }
736        };
737
738        let mut builder = StructureBuilder::new();
739        for field_signature in fields_signatures {
740            if let Some(field) = visitor.next_element_seed(ValueSeed::<Value<'_>> {
741                signature: field_signature,
742                phantom: PhantomData,
743            })? {
744                builder = builder.append_field(field);
745            }
746        }
747        Ok(builder.build_with_signature(self.signature))
748    }
749}
750
751impl<'sig, T> From<ValueSeed<'sig, T>> for SignatureSeed<'sig> {
752    fn from(seed: ValueSeed<'sig, T>) -> Self {
753        SignatureSeed {
754            signature: seed.signature,
755        }
756    }
757}
758
759struct ValueSeed<'sig, T> {
760    signature: &'sig Signature,
761    phantom: PhantomData<T>,
762}
763
764impl<'de, T> ValueSeed<'_, T>
765where
766    T: Deserialize<'de>,
767{
768    #[inline]
769    fn visit_array<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
770    where
771        V: SeqAccess<'de>,
772    {
773        SignatureSeed::from(self)
774            .visit_array(visitor)
775            .map(Value::Array)
776    }
777
778    #[inline]
779    fn visit_struct<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
780    where
781        V: SeqAccess<'de>,
782    {
783        SignatureSeed::from(self)
784            .visit_struct(visitor)
785            .map(Value::Structure)
786    }
787
788    #[inline]
789    fn visit_variant_as_seq<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
790    where
791        V: SeqAccess<'de>,
792    {
793        ValueVisitor
794            .visit_seq(visitor)
795            .map(|v| Value::Value(Box::new(v)))
796    }
797
798    #[inline]
799    fn visit_variant_as_map<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
800    where
801        V: MapAccess<'de>,
802    {
803        ValueVisitor
804            .visit_map(visitor)
805            .map(|v| Value::Value(Box::new(v)))
806    }
807}
808
809macro_rules! value_seed_basic_method {
810    ($name:ident, $type:ty) => {
811        #[inline]
812        fn $name<E>(self, value: $type) -> Result<Value<'static>, E>
813        where
814            E: serde::de::Error,
815        {
816            Ok(value.into())
817        }
818    };
819}
820
821impl<'de, T> Visitor<'de> for ValueSeed<'_, T>
822where
823    T: Deserialize<'de>,
824{
825    type Value = Value<'de>;
826
827    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
828        formatter.write_str("a Value value")
829    }
830
831    value_seed_basic_method!(visit_bool, bool);
832    value_seed_basic_method!(visit_i16, i16);
833    value_seed_basic_method!(visit_i64, i64);
834    value_seed_basic_method!(visit_u8, u8);
835    value_seed_basic_method!(visit_u16, u16);
836    value_seed_basic_method!(visit_u32, u32);
837    value_seed_basic_method!(visit_u64, u64);
838    value_seed_basic_method!(visit_f64, f64);
839
840    fn visit_i32<E>(self, value: i32) -> Result<Value<'de>, E>
841    where
842        E: serde::de::Error,
843    {
844        let v = match &self.signature {
845            #[cfg(unix)]
846            Signature::Fd => {
847                debug_assert!(value >= 0);
848                // SAFETY: The `'de` lifetimes will ensure the borrow won't outlive the raw FD.
849                let fd = unsafe { std::os::fd::BorrowedFd::borrow_raw(value) };
850                Fd::Borrowed(fd).into()
851            }
852            _ => value.into(),
853        };
854
855        Ok(v)
856    }
857
858    #[inline]
859    fn visit_str<E>(self, value: &str) -> Result<Value<'de>, E>
860    where
861        E: serde::de::Error,
862    {
863        self.visit_string(String::from(value))
864    }
865
866    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
867    where
868        E: Error,
869    {
870        match &self.signature {
871            Signature::Str => Ok(Value::Str(Str::from(v))),
872            Signature::Signature => Signature::try_from(v)
873                .map(Value::Signature)
874                .map_err(Error::custom),
875            Signature::ObjectPath => Ok(Value::ObjectPath(ObjectPath::from_str_unchecked(v))),
876            _ => {
877                let expected = format!(
878                    "`{}`, `{}` or `{}`",
879                    <&str>::SIGNATURE_STR,
880                    Signature::SIGNATURE_STR,
881                    ObjectPath::SIGNATURE_STR,
882                );
883                Err(Error::invalid_type(
884                    Unexpected::Str(&self.signature.to_string()),
885                    &expected.as_str(),
886                ))
887            }
888        }
889    }
890
891    fn visit_seq<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
892    where
893        V: SeqAccess<'de>,
894    {
895        match &self.signature {
896            // For some reason rustc doesn't like us using ARRAY_SIGNATURE_CHAR const
897            Signature::Array(_) => self.visit_array(visitor),
898            Signature::Structure(_) => self.visit_struct(visitor),
899            Signature::Variant => self.visit_variant_as_seq(visitor),
900            s => Err(Error::invalid_value(
901                Unexpected::Str(&s.to_string()),
902                &"a Value signature",
903            )),
904        }
905    }
906
907    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
908    where
909        V: MapAccess<'de>,
910    {
911        let (key_signature, value_signature) = match &self.signature {
912            Signature::Dict { key, value } => (key.signature().clone(), value.signature().clone()),
913            Signature::Variant => return self.visit_variant_as_map(visitor),
914            _ => {
915                return Err(Error::invalid_type(
916                    Unexpected::Str(&self.signature.to_string()),
917                    &"a dict signature",
918                ));
919            }
920        };
921
922        let mut dict = Dict::new_full_signature(self.signature);
923
924        while let Some((key, value)) = visitor.next_entry_seed(
925            ValueSeed::<Value<'_>> {
926                signature: &key_signature,
927                phantom: PhantomData,
928            },
929            ValueSeed::<Value<'_>> {
930                signature: &value_signature,
931                phantom: PhantomData,
932            },
933        )? {
934            dict.append(key, value).map_err(Error::custom)?;
935        }
936
937        Ok(Value::Dict(dict))
938    }
939
940    #[cfg(feature = "gvariant")]
941    #[allow(deprecated)]
942    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
943    where
944        D: Deserializer<'de>,
945    {
946        let child_signature = match &self.signature {
947            Signature::Maybe(child) => child.signature().clone(),
948            _ => {
949                return Err(Error::invalid_type(
950                    Unexpected::Str(&self.signature.to_string()),
951                    &"a maybe signature",
952                ));
953            }
954        };
955        let visitor = ValueSeed::<T> {
956            signature: &child_signature,
957            phantom: PhantomData,
958        };
959
960        deserializer
961            .deserialize_any(visitor)
962            .map(|v| Value::Maybe(Maybe::just_full_signature(v, self.signature)))
963    }
964
965    #[cfg(not(feature = "gvariant"))]
966    fn visit_some<D>(self, _deserializer: D) -> Result<Self::Value, D::Error>
967    where
968        D: Deserializer<'de>,
969    {
970        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
971    }
972
973    #[cfg(feature = "gvariant")]
974    #[allow(deprecated)]
975    fn visit_none<E>(self) -> Result<Self::Value, E>
976    where
977        E: Error,
978    {
979        let value = Maybe::nothing_full_signature(self.signature);
980
981        Ok(Value::Maybe(value))
982    }
983
984    #[cfg(not(feature = "gvariant"))]
985    fn visit_none<E>(self) -> Result<Self::Value, E>
986    where
987        E: Error,
988    {
989        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
990    }
991}
992
993impl<'de, T> DeserializeSeed<'de> for ValueSeed<'_, T>
994where
995    T: Deserialize<'de>,
996{
997    type Value = Value<'de>;
998
999    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1000    where
1001        D: Deserializer<'de>,
1002    {
1003        deserializer.deserialize_any(self)
1004    }
1005}
1006
1007impl Type for Value<'_> {
1008    const SIGNATURE: &'static Signature = &Signature::Variant;
1009}
1010
1011impl<'a> TryFrom<&Value<'a>> for Value<'a> {
1012    type Error = crate::Error;
1013
1014    fn try_from(value: &Value<'a>) -> crate::Result<Value<'a>> {
1015        value.try_clone()
1016    }
1017}
1018
1019impl Clone for Value<'_> {
1020    /// Clone the value.
1021    ///
1022    /// # Panics
1023    ///
1024    /// This method can only fail on Unix platforms for [`Value::Fd`] variant containing an
1025    /// [`Fd::Owned`] variant. This happens when the current process exceeds the limit on maximum
1026    /// number of open file descriptors.
1027    fn clone(&self) -> Self {
1028        self.try_clone()
1029            .expect("Process exceeded limit on maximum number of open file descriptors")
1030    }
1031}
1032
1033#[cfg(test)]
1034mod tests {
1035    use std::collections::HashMap;
1036
1037    use super::*;
1038
1039    #[test]
1040    fn value_display() {
1041        assert_eq!(
1042            Value::new((
1043                255_u8,
1044                true,
1045                -1_i16,
1046                65535_u16,
1047                -1,
1048                1_u32,
1049                -9223372036854775808_i64,
1050                18446744073709551615_u64,
1051                (-1., 1.0, 11000000000., 1.1e-10)
1052            ))
1053            .to_string(),
1054            "(byte 0xff, true, int16 -1, uint16 65535, -1, uint32 1, \
1055                int64 -9223372036854775808, uint64 18446744073709551615, \
1056                (-1., 1., 11000000000., 0.00000000011))"
1057        );
1058
1059        assert_eq!(
1060            Value::new(vec![
1061                "", " ", "a", r#"""#, "'", "a'b", "a'\"b", "\\", "\n'\"",
1062            ])
1063            .to_string(),
1064            r#"["", " ", "a", "\"", "'", "a'b", "a'\"b", "\\", "\n'\""]"#
1065        );
1066        assert_eq!(
1067            Value::new(vec![
1068                "\x07\x08\x09\x0A\x0B\x0C\x0D",
1069                "\x7F",
1070                char::from_u32(0xD8000).unwrap().to_string().as_str()
1071            ])
1072            .to_string(),
1073            r#"["\u{7}\u{8}\t\n\u{b}\u{c}\r", "\u{7f}", "\u{d8000}"]"#
1074        );
1075
1076        assert_eq!(
1077            Value::new((
1078                vec![crate::signature!(""), crate::signature!("(ysa{sd})"),],
1079                vec![
1080                    ObjectPath::from_static_str("/").unwrap(),
1081                    ObjectPath::from_static_str("/a/very/looooooooooooooooooooooooo0000o0ng/path")
1082                        .unwrap(),
1083                ],
1084                vec![
1085                    Value::new(0_u8),
1086                    Value::new((Value::new(51), Value::new(Value::new(1_u32)))),
1087                ]
1088            ))
1089            .to_string(),
1090            "([signature \"\", \"(ysa{sd})\"], \
1091                [objectpath \"/\", \"/a/very/looooooooooooooooooooooooo0000o0ng/path\"], \
1092                [<byte 0x00>, <(<51>, <<uint32 1>>)>])"
1093        );
1094
1095        assert_eq!(Value::new(vec![] as Vec<Vec<i64>>).to_string(), "@aax []");
1096        assert_eq!(
1097            Value::new(vec![
1098                vec![0_i16, 1_i16],
1099                vec![2_i16, 3_i16],
1100                vec![4_i16, 5_i16]
1101            ])
1102            .to_string(),
1103            "[[int16 0, 1], [2, 3], [4, 5]]"
1104        );
1105        assert_eq!(
1106            Value::new(vec![
1107                b"Hello".to_vec(),
1108                b"Hell\0o".to_vec(),
1109                b"H\0ello\0".to_vec(),
1110                b"Hello\0".to_vec(),
1111                b"\0".to_vec(),
1112                b" \0".to_vec(),
1113                b"'\0".to_vec(),
1114                b"\n'\"\0".to_vec(),
1115                b"\\\0".to_vec(),
1116            ])
1117            .to_string(),
1118            "[[byte 0x48, 0x65, 0x6c, 0x6c, 0x6f], \
1119                [0x48, 0x65, 0x6c, 0x6c, 0x00, 0x6f], \
1120                [0x48, 0x00, 0x65, 0x6c, 0x6c, 0x6f, 0x00], \
1121                b\"Hello\", b\"\", b\" \", b\"'\", b\"\\n'\\\"\", b\"\\\\\"]"
1122        );
1123
1124        assert_eq!(
1125            Value::new(HashMap::<bool, bool>::new()).to_string(),
1126            "@a{bb} {}"
1127        );
1128        assert_eq!(
1129            Value::new(vec![(true, 0_i64)].into_iter().collect::<HashMap<_, _>>()).to_string(),
1130            "{true: int64 0}",
1131        );
1132        // The order of the entries may vary
1133        let val = Value::new(
1134            vec![(32_u16, 64_i64), (100_u16, 200_i64)]
1135                .into_iter()
1136                .collect::<HashMap<_, _>>(),
1137        )
1138        .to_string();
1139        assert!(val.starts_with('{'));
1140        assert!(val.ends_with('}'));
1141        assert_eq!(val.matches("uint16").count(), 1);
1142        assert_eq!(val.matches("int64").count(), 1);
1143
1144        let items_str = val.split(", ").collect::<Vec<_>>();
1145        assert_eq!(items_str.len(), 2);
1146        assert!(
1147            items_str
1148                .iter()
1149                .any(|str| str.contains("32") && str.contains(": ") && str.contains("64"))
1150        );
1151        assert!(
1152            items_str
1153                .iter()
1154                .any(|str| str.contains("100") && str.contains(": ") && str.contains("200"))
1155        );
1156
1157        assert_eq!(
1158            Value::new(((true,), (true, false), (true, true, false))).to_string(),
1159            "((true,), (true, false), (true, true, false))"
1160        );
1161
1162        #[cfg(any(feature = "gvariant", feature = "option-as-array"))]
1163        {
1164            #[cfg(unix)]
1165            use std::os::fd::BorrowedFd;
1166
1167            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1168            let s = "((@mn 0, @mmn 0, @mmmn 0), \
1169                (@mn nothing, @mmn just nothing, @mmmn just just nothing), \
1170                (@mmn nothing, @mmmn just nothing))";
1171            #[cfg(feature = "option-as-array")]
1172            let s = "(([int16 0], [[int16 0]], [[[int16 0]]]), \
1173                (@an [], [@an []], [[@an []]]), \
1174                (@aan [], [@aan []]))";
1175            assert_eq!(
1176                Value::new((
1177                    (Some(0_i16), Some(Some(0_i16)), Some(Some(Some(0_i16))),),
1178                    (None::<i16>, Some(None::<i16>), Some(Some(None::<i16>)),),
1179                    (None::<Option<i16>>, Some(None::<Option<i16>>)),
1180                ))
1181                .to_string(),
1182                s,
1183            );
1184
1185            #[cfg(unix)]
1186            assert_eq!(
1187                Value::new(vec![
1188                    Fd::from(unsafe { BorrowedFd::borrow_raw(0) }),
1189                    Fd::from(unsafe { BorrowedFd::borrow_raw(-100) })
1190                ])
1191                .to_string(),
1192                "[handle 0, -100]"
1193            );
1194
1195            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1196            let s = "(@mb nothing, @mb nothing, \
1197                @ma{sv} {\"size\": <(800, 600)>}, \
1198                [<1>, <{\"dimension\": <([2.4, 1.], \
1199                @mmn 200, <(byte 0x03, \"Hello!\")>)>}>], \
1200                7777, objectpath \"/\", 8888)";
1201            #[cfg(feature = "option-as-array")]
1202            let s = "(@ab [], @ab [], [{\"size\": <(800, 600)>}], \
1203                [<1>, <{\"dimension\": <([2.4, 1.], [[int16 200]], \
1204                <(byte 0x03, \"Hello!\")>)>}>], 7777, objectpath \"/\", 8888)";
1205            assert_eq!(
1206                Value::new((
1207                    None::<bool>,
1208                    None::<bool>,
1209                    Some(
1210                        vec![("size", Value::new((800, 600)))]
1211                            .into_iter()
1212                            .collect::<HashMap<_, _>>()
1213                    ),
1214                    vec![
1215                        Value::new(1),
1216                        Value::new(
1217                            vec![(
1218                                "dimension",
1219                                Value::new((
1220                                    vec![2.4, 1.],
1221                                    Some(Some(200_i16)),
1222                                    Value::new((3_u8, "Hello!"))
1223                                ))
1224                            )]
1225                            .into_iter()
1226                            .collect::<HashMap<_, _>>()
1227                        )
1228                    ],
1229                    7777,
1230                    ObjectPath::from_static_str("/").unwrap(),
1231                    8888
1232                ))
1233                .to_string(),
1234                s,
1235            );
1236        }
1237    }
1238}