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