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")]
25use crate::{Maybe, maybe_display_fmt};
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                debug_assert!(value >= 0);
834                // SAFETY: The `'de` lifetimes will ensure the borrow won't outlive the raw FD.
835                let fd = unsafe { std::os::fd::BorrowedFd::borrow_raw(value) };
836                Fd::Borrowed(fd).into()
837            }
838            _ => value.into(),
839        };
840
841        Ok(v)
842    }
843
844    #[inline]
845    fn visit_str<E>(self, value: &str) -> Result<Value<'de>, E>
846    where
847        E: serde::de::Error,
848    {
849        self.visit_string(String::from(value))
850    }
851
852    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
853    where
854        E: Error,
855    {
856        match &self.signature {
857            Signature::Str => Ok(Value::Str(Str::from(v))),
858            Signature::Signature => Signature::try_from(v)
859                .map(Value::Signature)
860                .map_err(Error::custom),
861            Signature::ObjectPath => Ok(Value::ObjectPath(ObjectPath::from_str_unchecked(v))),
862            _ => {
863                let expected = format!(
864                    "`{}`, `{}` or `{}`",
865                    <&str>::SIGNATURE_STR,
866                    Signature::SIGNATURE_STR,
867                    ObjectPath::SIGNATURE_STR,
868                );
869                Err(Error::invalid_type(
870                    Unexpected::Str(&self.signature.to_string()),
871                    &expected.as_str(),
872                ))
873            }
874        }
875    }
876
877    fn visit_seq<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
878    where
879        V: SeqAccess<'de>,
880    {
881        match &self.signature {
882            // For some reason rustc doesn't like us using ARRAY_SIGNATURE_CHAR const
883            Signature::Array(_) => self.visit_array(visitor),
884            Signature::Structure(_) => self.visit_struct(visitor),
885            Signature::Variant => self.visit_variant_as_seq(visitor),
886            s => Err(Error::invalid_value(
887                Unexpected::Str(&s.to_string()),
888                &"a Value signature",
889            )),
890        }
891    }
892
893    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
894    where
895        V: MapAccess<'de>,
896    {
897        let (key_signature, value_signature) = match &self.signature {
898            Signature::Dict { key, value } => (key.signature().clone(), value.signature().clone()),
899            Signature::Variant => return self.visit_variant_as_map(visitor),
900            _ => {
901                return Err(Error::invalid_type(
902                    Unexpected::Str(&self.signature.to_string()),
903                    &"a dict signature",
904                ));
905            }
906        };
907
908        let mut dict = Dict::new_full_signature(self.signature);
909
910        while let Some((key, value)) = visitor.next_entry_seed(
911            ValueSeed::<Value<'_>> {
912                signature: &key_signature,
913                phantom: PhantomData,
914            },
915            ValueSeed::<Value<'_>> {
916                signature: &value_signature,
917                phantom: PhantomData,
918            },
919        )? {
920            dict.append(key, value).map_err(Error::custom)?;
921        }
922
923        Ok(Value::Dict(dict))
924    }
925
926    #[cfg(feature = "gvariant")]
927    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
928    where
929        D: Deserializer<'de>,
930    {
931        let child_signature = match &self.signature {
932            Signature::Maybe(child) => child.signature().clone(),
933            _ => {
934                return Err(Error::invalid_type(
935                    Unexpected::Str(&self.signature.to_string()),
936                    &"a maybe signature",
937                ));
938            }
939        };
940        let visitor = ValueSeed::<T> {
941            signature: &child_signature,
942            phantom: PhantomData,
943        };
944
945        deserializer
946            .deserialize_any(visitor)
947            .map(|v| Value::Maybe(Maybe::just_full_signature(v, self.signature)))
948    }
949
950    #[cfg(not(feature = "gvariant"))]
951    fn visit_some<D>(self, _deserializer: D) -> Result<Self::Value, D::Error>
952    where
953        D: Deserializer<'de>,
954    {
955        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
956    }
957
958    #[cfg(feature = "gvariant")]
959    fn visit_none<E>(self) -> Result<Self::Value, E>
960    where
961        E: Error,
962    {
963        let value = Maybe::nothing_full_signature(self.signature);
964
965        Ok(Value::Maybe(value))
966    }
967
968    #[cfg(not(feature = "gvariant"))]
969    fn visit_none<E>(self) -> Result<Self::Value, E>
970    where
971        E: Error,
972    {
973        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
974    }
975}
976
977impl<'de, T> DeserializeSeed<'de> for ValueSeed<'_, T>
978where
979    T: Deserialize<'de>,
980{
981    type Value = Value<'de>;
982
983    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
984    where
985        D: Deserializer<'de>,
986    {
987        deserializer.deserialize_any(self)
988    }
989}
990
991impl Type for Value<'_> {
992    const SIGNATURE: &'static Signature = &Signature::Variant;
993}
994
995impl<'a> TryFrom<&Value<'a>> for Value<'a> {
996    type Error = crate::Error;
997
998    fn try_from(value: &Value<'a>) -> crate::Result<Value<'a>> {
999        value.try_clone()
1000    }
1001}
1002
1003impl Clone for Value<'_> {
1004    /// Clone the value.
1005    ///
1006    /// # Panics
1007    ///
1008    /// This method can only fail on Unix platforms for [`Value::Fd`] variant containing an
1009    /// [`Fd::Owned`] variant. This happens when the current process exceeds the limit on maximum
1010    /// number of open file descriptors.
1011    fn clone(&self) -> Self {
1012        self.try_clone()
1013            .expect("Process exceeded limit on maximum number of open file descriptors")
1014    }
1015}
1016
1017#[cfg(test)]
1018mod tests {
1019    use std::collections::HashMap;
1020
1021    use super::*;
1022
1023    #[test]
1024    fn value_display() {
1025        assert_eq!(
1026            Value::new((
1027                255_u8,
1028                true,
1029                -1_i16,
1030                65535_u16,
1031                -1,
1032                1_u32,
1033                -9223372036854775808_i64,
1034                18446744073709551615_u64,
1035                (-1., 1.0, 11000000000., 1.1e-10)
1036            ))
1037            .to_string(),
1038            "(byte 0xff, true, int16 -1, uint16 65535, -1, uint32 1, \
1039                int64 -9223372036854775808, uint64 18446744073709551615, \
1040                (-1., 1., 11000000000., 0.00000000011))"
1041        );
1042
1043        assert_eq!(
1044            Value::new(vec![
1045                "", " ", "a", r#"""#, "'", "a'b", "a'\"b", "\\", "\n'\"",
1046            ])
1047            .to_string(),
1048            r#"["", " ", "a", "\"", "'", "a'b", "a'\"b", "\\", "\n'\""]"#
1049        );
1050        assert_eq!(
1051            Value::new(vec![
1052                "\x07\x08\x09\x0A\x0B\x0C\x0D",
1053                "\x7F",
1054                char::from_u32(0xD8000).unwrap().to_string().as_str()
1055            ])
1056            .to_string(),
1057            r#"["\u{7}\u{8}\t\n\u{b}\u{c}\r", "\u{7f}", "\u{d8000}"]"#
1058        );
1059
1060        assert_eq!(
1061            Value::new((
1062                vec![crate::signature!(""), crate::signature!("(ysa{sd})"),],
1063                vec![
1064                    ObjectPath::from_static_str("/").unwrap(),
1065                    ObjectPath::from_static_str("/a/very/looooooooooooooooooooooooo0000o0ng/path")
1066                        .unwrap(),
1067                ],
1068                vec![
1069                    Value::new(0_u8),
1070                    Value::new((Value::new(51), Value::new(Value::new(1_u32)))),
1071                ]
1072            ))
1073            .to_string(),
1074            "([signature \"\", \"(ysa{sd})\"], \
1075                [objectpath \"/\", \"/a/very/looooooooooooooooooooooooo0000o0ng/path\"], \
1076                [<byte 0x00>, <(<51>, <<uint32 1>>)>])"
1077        );
1078
1079        assert_eq!(Value::new(vec![] as Vec<Vec<i64>>).to_string(), "@aax []");
1080        assert_eq!(
1081            Value::new(vec![
1082                vec![0_i16, 1_i16],
1083                vec![2_i16, 3_i16],
1084                vec![4_i16, 5_i16]
1085            ])
1086            .to_string(),
1087            "[[int16 0, 1], [2, 3], [4, 5]]"
1088        );
1089        assert_eq!(
1090            Value::new(vec![
1091                b"Hello".to_vec(),
1092                b"Hell\0o".to_vec(),
1093                b"H\0ello\0".to_vec(),
1094                b"Hello\0".to_vec(),
1095                b"\0".to_vec(),
1096                b" \0".to_vec(),
1097                b"'\0".to_vec(),
1098                b"\n'\"\0".to_vec(),
1099                b"\\\0".to_vec(),
1100            ])
1101            .to_string(),
1102            "[[byte 0x48, 0x65, 0x6c, 0x6c, 0x6f], \
1103                [0x48, 0x65, 0x6c, 0x6c, 0x00, 0x6f], \
1104                [0x48, 0x00, 0x65, 0x6c, 0x6c, 0x6f, 0x00], \
1105                b\"Hello\", b\"\", b\" \", b\"'\", b\"\\n'\\\"\", b\"\\\\\"]"
1106        );
1107
1108        assert_eq!(
1109            Value::new(HashMap::<bool, bool>::new()).to_string(),
1110            "@a{bb} {}"
1111        );
1112        assert_eq!(
1113            Value::new(vec![(true, 0_i64)].into_iter().collect::<HashMap<_, _>>()).to_string(),
1114            "{true: int64 0}",
1115        );
1116        // The order of the entries may vary
1117        let val = Value::new(
1118            vec![(32_u16, 64_i64), (100_u16, 200_i64)]
1119                .into_iter()
1120                .collect::<HashMap<_, _>>(),
1121        )
1122        .to_string();
1123        assert!(val.starts_with('{'));
1124        assert!(val.ends_with('}'));
1125        assert_eq!(val.matches("uint16").count(), 1);
1126        assert_eq!(val.matches("int64").count(), 1);
1127
1128        let items_str = val.split(", ").collect::<Vec<_>>();
1129        assert_eq!(items_str.len(), 2);
1130        assert!(
1131            items_str
1132                .iter()
1133                .any(|str| str.contains("32") && str.contains(": ") && str.contains("64"))
1134        );
1135        assert!(
1136            items_str
1137                .iter()
1138                .any(|str| str.contains("100") && str.contains(": ") && str.contains("200"))
1139        );
1140
1141        assert_eq!(
1142            Value::new(((true,), (true, false), (true, true, false))).to_string(),
1143            "((true,), (true, false), (true, true, false))"
1144        );
1145
1146        #[cfg(any(feature = "gvariant", feature = "option-as-array"))]
1147        {
1148            #[cfg(unix)]
1149            use std::os::fd::BorrowedFd;
1150
1151            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1152            let s = "((@mn 0, @mmn 0, @mmmn 0), \
1153                (@mn nothing, @mmn just nothing, @mmmn just just nothing), \
1154                (@mmn nothing, @mmmn just nothing))";
1155            #[cfg(feature = "option-as-array")]
1156            let s = "(([int16 0], [[int16 0]], [[[int16 0]]]), \
1157                (@an [], [@an []], [[@an []]]), \
1158                (@aan [], [@aan []]))";
1159            assert_eq!(
1160                Value::new((
1161                    (Some(0_i16), Some(Some(0_i16)), Some(Some(Some(0_i16))),),
1162                    (None::<i16>, Some(None::<i16>), Some(Some(None::<i16>)),),
1163                    (None::<Option<i16>>, Some(None::<Option<i16>>)),
1164                ))
1165                .to_string(),
1166                s,
1167            );
1168
1169            #[cfg(unix)]
1170            assert_eq!(
1171                Value::new(vec![
1172                    Fd::from(unsafe { BorrowedFd::borrow_raw(0) }),
1173                    Fd::from(unsafe { BorrowedFd::borrow_raw(-100) })
1174                ])
1175                .to_string(),
1176                "[handle 0, -100]"
1177            );
1178
1179            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1180            let s = "(@mb nothing, @mb nothing, \
1181                @ma{sv} {\"size\": <(800, 600)>}, \
1182                [<1>, <{\"dimension\": <([2.4, 1.], \
1183                @mmn 200, <(byte 0x03, \"Hello!\")>)>}>], \
1184                7777, objectpath \"/\", 8888)";
1185            #[cfg(feature = "option-as-array")]
1186            let s = "(@ab [], @ab [], [{\"size\": <(800, 600)>}], \
1187                [<1>, <{\"dimension\": <([2.4, 1.], [[int16 200]], \
1188                <(byte 0x03, \"Hello!\")>)>}>], 7777, objectpath \"/\", 8888)";
1189            assert_eq!(
1190                Value::new((
1191                    None::<bool>,
1192                    None::<bool>,
1193                    Some(
1194                        vec![("size", Value::new((800, 600)))]
1195                            .into_iter()
1196                            .collect::<HashMap<_, _>>()
1197                    ),
1198                    vec![
1199                        Value::new(1),
1200                        Value::new(
1201                            vec![(
1202                                "dimension",
1203                                Value::new((
1204                                    vec![2.4, 1.],
1205                                    Some(Some(200_i16)),
1206                                    Value::new((3_u8, "Hello!"))
1207                                ))
1208                            )]
1209                            .into_iter()
1210                            .collect::<HashMap<_, _>>()
1211                        )
1212                    ],
1213                    7777,
1214                    ObjectPath::from_static_str("/").unwrap(),
1215                    8888
1216                ))
1217                .to_string(),
1218                s,
1219            );
1220        }
1221    }
1222}