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    /// Get the signature of the enclosed value.
250    pub fn value_signature(&self) -> &Signature {
251        match self {
252            Value::U8(_) => u8::SIGNATURE,
253            Value::Bool(_) => bool::SIGNATURE,
254            Value::I16(_) => i16::SIGNATURE,
255            Value::U16(_) => u16::SIGNATURE,
256            Value::I32(_) => i32::SIGNATURE,
257            Value::U32(_) => u32::SIGNATURE,
258            Value::I64(_) => i64::SIGNATURE,
259            Value::U64(_) => u64::SIGNATURE,
260            Value::F64(_) => f64::SIGNATURE,
261            Value::Str(_) => <&str>::SIGNATURE,
262            Value::Signature(_) => Signature::SIGNATURE,
263            Value::ObjectPath(_) => ObjectPath::SIGNATURE,
264            Value::Value(_) => &Signature::Variant,
265
266            // Container types
267            Value::Array(value) => value.signature(),
268            Value::Dict(value) => value.signature(),
269            Value::Structure(value) => value.signature(),
270            #[cfg(feature = "gvariant")]
271            Value::Maybe(value) => value.signature(),
272
273            #[cfg(unix)]
274            Value::Fd(_) => Fd::SIGNATURE,
275        }
276    }
277
278    /// Try to clone the value.
279    ///
280    /// # Errors
281    ///
282    /// This method can currently only fail on Unix platforms for [`Value::Fd`] variant containing
283    /// an [`Fd::Owned`] variant. This happens when the current process exceeds the maximum number
284    /// of open file descriptors.
285    pub fn try_clone(&self) -> crate::Result<Self> {
286        Ok(match self {
287            Value::U8(v) => Value::U8(*v),
288            Value::Bool(v) => Value::Bool(*v),
289            Value::I16(v) => Value::I16(*v),
290            Value::U16(v) => Value::U16(*v),
291            Value::I32(v) => Value::I32(*v),
292            Value::U32(v) => Value::U32(*v),
293            Value::I64(v) => Value::I64(*v),
294            Value::U64(v) => Value::U64(*v),
295            Value::F64(v) => Value::F64(*v),
296            Value::Str(v) => Value::Str(v.clone()),
297            Value::Signature(v) => Value::Signature(v.clone()),
298            Value::ObjectPath(v) => Value::ObjectPath(v.clone()),
299            Value::Value(v) => Value::Value(Box::new(v.try_clone()?)),
300            Value::Array(v) => Value::Array(v.try_clone()?),
301            Value::Dict(v) => Value::Dict(v.try_clone()?),
302            Value::Structure(v) => Value::Structure(v.try_clone()?),
303            #[cfg(feature = "gvariant")]
304            Value::Maybe(v) => Value::Maybe(v.try_clone()?),
305            #[cfg(unix)]
306            Value::Fd(v) => Value::Fd(v.try_clone()?),
307        })
308    }
309
310    pub(crate) fn serialize_value_as_struct_field<S>(
311        &self,
312        name: &'static str,
313        serializer: &mut S,
314    ) -> Result<(), S::Error>
315    where
316        S: SerializeStruct,
317    {
318        serialize_value!(self serializer.serialize_field name)
319    }
320
321    pub(crate) fn serialize_value_as_tuple_struct_field<S>(
322        &self,
323        serializer: &mut S,
324    ) -> Result<(), S::Error>
325    where
326        S: SerializeTupleStruct,
327    {
328        serialize_value!(self serializer.serialize_field)
329    }
330
331    // Really crappy that we need to do this separately for struct and seq cases. :(
332    pub(crate) fn serialize_value_as_seq_element<S>(
333        &self,
334        serializer: &mut S,
335    ) -> Result<(), S::Error>
336    where
337        S: SerializeSeq,
338    {
339        serialize_value!(self serializer.serialize_element)
340    }
341
342    pub(crate) fn serialize_value_as_dict_key<S>(&self, serializer: &mut S) -> Result<(), S::Error>
343    where
344        S: SerializeMap,
345    {
346        serialize_value!(self serializer.serialize_key)
347    }
348
349    pub(crate) fn serialize_value_as_dict_value<S>(
350        &self,
351        serializer: &mut S,
352    ) -> Result<(), S::Error>
353    where
354        S: SerializeMap,
355    {
356        serialize_value!(self serializer.serialize_value)
357    }
358
359    #[cfg(feature = "gvariant")]
360    pub(crate) fn serialize_value_as_some<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
361    where
362        S: Serializer,
363    {
364        serialize_value!(self serializer.serialize_some)
365    }
366
367    /// Try to get the underlying type `T`.
368    ///
369    /// Note that [`TryFrom<Value>`] is implemented for various types, and it's usually best to use
370    /// that instead. However, in generic code where you also want to unwrap [`Value::Value`],
371    /// you should use this function (because [`TryFrom<Value>`] can not be implemented for `Value`
372    /// itself as [`From<Value>`] is implicitly implemented for `Value`).
373    ///
374    /// # Examples
375    ///
376    /// ```
377    /// use zvariant::{Error, Result, Value};
378    ///
379    /// fn value_vec_to_type_vec<'a, T>(values: Vec<Value<'a>>) -> Result<Vec<T>>
380    /// where
381    ///     T: TryFrom<Value<'a>>,
382    ///     <T as TryFrom<Value<'a>>>::Error: Into<Error>,
383    /// {
384    ///     let mut res = vec![];
385    ///     for value in values.into_iter() {
386    ///         res.push(value.downcast()?);
387    ///     }
388    ///
389    ///     Ok(res)
390    /// }
391    ///
392    /// // Let's try u32 values first
393    /// let v = vec![Value::U32(42), Value::U32(43)];
394    /// let v = value_vec_to_type_vec::<u32>(v).unwrap();
395    /// assert_eq!(v[0], 42);
396    /// assert_eq!(v[1], 43);
397    ///
398    /// // Now try Value values
399    /// let v = vec![Value::new(Value::U32(42)), Value::new(Value::U32(43))];
400    /// let v = value_vec_to_type_vec::<Value>(v).unwrap();
401    /// assert_eq!(v[0], Value::U32(42));
402    /// assert_eq!(v[1], Value::U32(43));
403    /// ```
404    ///
405    /// [`Value::Value`]: enum.Value.html#variant.Value
406    /// [`TryFrom<Value>`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html
407    /// [`From<Value>`]: https://doc.rust-lang.org/std/convert/trait.From.html
408    pub fn downcast<T>(self) -> Result<T, crate::Error>
409    where
410        T: TryFrom<Value<'a>>,
411        <T as TryFrom<Value<'a>>>::Error: Into<crate::Error>,
412    {
413        if let Value::Value(v) = self {
414            T::try_from(*v)
415        } else {
416            T::try_from(self)
417        }
418        .map_err(Into::into)
419    }
420
421    /// Try to get the underlying type `T`.
422    ///
423    /// Same as [`downcast`] except it doesn't consume `self` and hence requires
424    /// `T: TryFrom<&Value<_>>`.
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use zvariant::{Error, Result, Value};
430    ///
431    /// fn value_vec_to_type_vec<'a, T>(values: &'a Vec<Value<'a>>) -> Result<Vec<&'a T>>
432    /// where
433    ///     &'a T: TryFrom<&'a Value<'a>>,
434    ///     <&'a T as TryFrom<&'a Value<'a>>>::Error: Into<Error>,
435    /// {
436    ///     let mut res = vec![];
437    ///     for value in values.into_iter() {
438    ///         res.push(value.downcast_ref()?);
439    ///     }
440    ///
441    ///     Ok(res)
442    /// }
443    ///
444    /// // Let's try u32 values first
445    /// let v = vec![Value::U32(42), Value::U32(43)];
446    /// let v = value_vec_to_type_vec::<u32>(&v).unwrap();
447    /// assert_eq!(*v[0], 42);
448    /// assert_eq!(*v[1], 43);
449    ///
450    /// // Now try Value values
451    /// let v = vec![Value::new(Value::U32(42)), Value::new(Value::U32(43))];
452    /// let v = value_vec_to_type_vec::<Value>(&v).unwrap();
453    /// assert_eq!(*v[0], Value::U32(42));
454    /// assert_eq!(*v[1], Value::U32(43));
455    /// ```
456    ///
457    /// [`downcast`]: enum.Value.html#method.downcast
458    pub fn downcast_ref<T>(&'a self) -> Result<T, crate::Error>
459    where
460        T: TryFrom<&'a Value<'a>>,
461        <T as TryFrom<&'a Value<'a>>>::Error: Into<crate::Error>,
462    {
463        if let Value::Value(v) = self {
464            <T>::try_from(v)
465        } else {
466            <T>::try_from(self)
467        }
468        .map_err(Into::into)
469    }
470}
471
472impl Display for Value<'_> {
473    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
474        value_display_fmt(self, f, true)
475    }
476}
477
478/// Implemented based on https://gitlab.gnome.org/GNOME/glib/-/blob/e1d47f0b0d0893ac9171e24cc7bf635495376546/glib/gvariant.c#L2213
479pub(crate) fn value_display_fmt(
480    value: &Value<'_>,
481    f: &mut std::fmt::Formatter<'_>,
482    type_annotate: bool,
483) -> std::fmt::Result {
484    match value {
485        Value::U8(num) => {
486            if type_annotate {
487                f.write_str("byte ")?;
488            }
489            write!(f, "0x{num:02x}")
490        }
491        Value::Bool(boolean) => {
492            write!(f, "{boolean}")
493        }
494        Value::I16(num) => {
495            if type_annotate {
496                f.write_str("int16 ")?;
497            }
498            write!(f, "{num}")
499        }
500        Value::U16(num) => {
501            if type_annotate {
502                f.write_str("uint16 ")?;
503            }
504            write!(f, "{num}")
505        }
506        Value::I32(num) => {
507            // Never annotate this type because it is the default for numbers
508            write!(f, "{num}")
509        }
510        Value::U32(num) => {
511            if type_annotate {
512                f.write_str("uint32 ")?;
513            }
514            write!(f, "{num}")
515        }
516        Value::I64(num) => {
517            if type_annotate {
518                f.write_str("int64 ")?;
519            }
520            write!(f, "{num}")
521        }
522        Value::U64(num) => {
523            if type_annotate {
524                f.write_str("uint64 ")?;
525            }
526            write!(f, "{num}")
527        }
528        Value::F64(num) => {
529            if num.fract() == 0. {
530                // Add a dot to make it clear that this is a float
531                write!(f, "{num}.")
532            } else {
533                write!(f, "{num}")
534            }
535        }
536        Value::Str(string) => {
537            write!(f, "{:?}", string.as_str())
538        }
539        Value::Signature(val) => {
540            if type_annotate {
541                f.write_str("signature ")?;
542            }
543            write!(f, "{:?}", val.to_string())
544        }
545        Value::ObjectPath(val) => {
546            if type_annotate {
547                f.write_str("objectpath ")?;
548            }
549            write!(f, "{:?}", val.as_str())
550        }
551        Value::Value(child) => {
552            f.write_char('<')?;
553
554            // Always annotate types in nested variants, because they are (by nature) of
555            // variable type.
556            value_display_fmt(child, f, true)?;
557
558            f.write_char('>')?;
559            Ok(())
560        }
561        Value::Array(array) => array_display_fmt(array, f, type_annotate),
562        Value::Dict(dict) => dict_display_fmt(dict, f, type_annotate),
563        Value::Structure(structure) => structure_display_fmt(structure, f, type_annotate),
564        #[cfg(feature = "gvariant")]
565        Value::Maybe(maybe) => maybe_display_fmt(maybe, f, type_annotate),
566        #[cfg(unix)]
567        Value::Fd(handle) => {
568            if type_annotate {
569                f.write_str("handle ")?;
570            }
571            write!(f, "{handle}")
572        }
573    }
574}
575
576impl Serialize for Value<'_> {
577    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
578    where
579        S: Serializer,
580    {
581        // Serializer implementation needs to ensure padding isn't added for Value.
582        let mut structure = serializer.serialize_struct("Variant", 2)?;
583
584        let signature = self.value_signature();
585        structure.serialize_field("signature", &signature)?;
586
587        self.serialize_value_as_struct_field("value", &mut structure)?;
588
589        structure.end()
590    }
591}
592
593impl<'de: 'a, 'a> Deserialize<'de> for Value<'a> {
594    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
595    where
596        D: Deserializer<'de>,
597    {
598        let visitor = ValueVisitor;
599
600        deserializer.deserialize_any(visitor)
601    }
602}
603
604struct ValueVisitor;
605
606impl<'de> Visitor<'de> for ValueVisitor {
607    type Value = Value<'de>;
608
609    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610        formatter.write_str("a Value")
611    }
612
613    fn visit_seq<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
614    where
615        V: SeqAccess<'de>,
616    {
617        let signature = visitor.next_element::<Signature>()?.ok_or_else(|| {
618            Error::invalid_value(Unexpected::Other("nothing"), &"a Value signature")
619        })?;
620        let seed = ValueSeed::<Value<'_>> {
621            signature: &signature,
622            phantom: PhantomData,
623        };
624
625        visitor
626            .next_element_seed(seed)?
627            .ok_or_else(|| Error::invalid_value(Unexpected::Other("nothing"), &"a Value value"))
628    }
629
630    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
631    where
632        V: MapAccess<'de>,
633    {
634        let (_, signature) = visitor.next_entry::<&str, Signature>()?.ok_or_else(|| {
635            Error::invalid_value(Unexpected::Other("nothing"), &"a Value signature")
636        })?;
637        let _ = visitor.next_key::<&str>()?;
638
639        let seed = ValueSeed::<Value<'_>> {
640            signature: &signature,
641            phantom: PhantomData,
642        };
643        visitor.next_value_seed(seed)
644    }
645}
646
647pub(crate) struct SignatureSeed<'sig> {
648    pub signature: &'sig Signature,
649}
650
651impl SignatureSeed<'_> {
652    pub(crate) fn visit_array<'de, V>(self, mut visitor: V) -> Result<Array<'de>, V::Error>
653    where
654        V: SeqAccess<'de>,
655    {
656        let element_signature = match self.signature {
657            Signature::Array(child) => child.signature(),
658            _ => {
659                return Err(Error::invalid_type(
660                    Unexpected::Str(&self.signature.to_string()),
661                    &"an array signature",
662                ))
663            }
664        };
665        let mut array = Array::new_full_signature(self.signature);
666
667        while let Some(elem) = visitor.next_element_seed(ValueSeed::<Value<'_>> {
668            signature: element_signature,
669            phantom: PhantomData,
670        })? {
671            elem.value_signature();
672            array.append(elem).map_err(Error::custom)?;
673        }
674
675        Ok(array)
676    }
677
678    pub(crate) fn visit_struct<'de, V>(self, mut visitor: V) -> Result<Structure<'de>, V::Error>
679    where
680        V: SeqAccess<'de>,
681    {
682        let fields_signatures = match self.signature {
683            Signature::Structure(fields) => fields.iter(),
684            _ => {
685                return Err(Error::invalid_type(
686                    Unexpected::Str(&self.signature.to_string()),
687                    &"a structure signature",
688                ))
689            }
690        };
691
692        let mut builder = StructureBuilder::new();
693        for field_signature in fields_signatures {
694            if let Some(field) = visitor.next_element_seed(ValueSeed::<Value<'_>> {
695                signature: field_signature,
696                phantom: PhantomData,
697            })? {
698                builder = builder.append_field(field);
699            }
700        }
701        Ok(builder.build_with_signature(self.signature))
702    }
703}
704
705impl<'sig, T> From<ValueSeed<'sig, T>> for SignatureSeed<'sig> {
706    fn from(seed: ValueSeed<'sig, T>) -> Self {
707        SignatureSeed {
708            signature: seed.signature,
709        }
710    }
711}
712
713struct ValueSeed<'sig, T> {
714    signature: &'sig Signature,
715    phantom: PhantomData<T>,
716}
717
718impl<'de, T> ValueSeed<'_, T>
719where
720    T: Deserialize<'de>,
721{
722    #[inline]
723    fn visit_array<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
724    where
725        V: SeqAccess<'de>,
726    {
727        SignatureSeed::from(self)
728            .visit_array(visitor)
729            .map(Value::Array)
730    }
731
732    #[inline]
733    fn visit_struct<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
734    where
735        V: SeqAccess<'de>,
736    {
737        SignatureSeed::from(self)
738            .visit_struct(visitor)
739            .map(Value::Structure)
740    }
741
742    #[inline]
743    fn visit_variant_as_seq<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
744    where
745        V: SeqAccess<'de>,
746    {
747        ValueVisitor
748            .visit_seq(visitor)
749            .map(|v| Value::Value(Box::new(v)))
750    }
751
752    #[inline]
753    fn visit_variant_as_map<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
754    where
755        V: MapAccess<'de>,
756    {
757        ValueVisitor
758            .visit_map(visitor)
759            .map(|v| Value::Value(Box::new(v)))
760    }
761}
762
763macro_rules! value_seed_basic_method {
764    ($name:ident, $type:ty) => {
765        #[inline]
766        fn $name<E>(self, value: $type) -> Result<Value<'static>, E>
767        where
768            E: serde::de::Error,
769        {
770            Ok(value.into())
771        }
772    };
773}
774
775impl<'de, T> Visitor<'de> for ValueSeed<'_, T>
776where
777    T: Deserialize<'de>,
778{
779    type Value = Value<'de>;
780
781    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
782        formatter.write_str("a Value value")
783    }
784
785    value_seed_basic_method!(visit_bool, bool);
786    value_seed_basic_method!(visit_i16, i16);
787    value_seed_basic_method!(visit_i64, i64);
788    value_seed_basic_method!(visit_u8, u8);
789    value_seed_basic_method!(visit_u16, u16);
790    value_seed_basic_method!(visit_u32, u32);
791    value_seed_basic_method!(visit_u64, u64);
792    value_seed_basic_method!(visit_f64, f64);
793
794    fn visit_i32<E>(self, value: i32) -> Result<Value<'de>, E>
795    where
796        E: serde::de::Error,
797    {
798        let v = match &self.signature {
799            #[cfg(unix)]
800            Signature::Fd => {
801                // SAFETY: The `'de` lifetimes will ensure the borrow won't outlive the raw FD.
802                let fd = unsafe { std::os::fd::BorrowedFd::borrow_raw(value) };
803                Fd::Borrowed(fd).into()
804            }
805            _ => value.into(),
806        };
807
808        Ok(v)
809    }
810
811    #[inline]
812    fn visit_str<E>(self, value: &str) -> Result<Value<'de>, E>
813    where
814        E: serde::de::Error,
815    {
816        self.visit_string(String::from(value))
817    }
818
819    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
820    where
821        E: Error,
822    {
823        match &self.signature {
824            Signature::Str => Ok(Value::Str(Str::from(v))),
825            Signature::Signature => Signature::try_from(v)
826                .map(Value::Signature)
827                .map_err(Error::custom),
828            Signature::ObjectPath => Ok(Value::ObjectPath(ObjectPath::from_str_unchecked(v))),
829            _ => {
830                let expected = format!(
831                    "`{}`, `{}` or `{}`",
832                    <&str>::SIGNATURE_STR,
833                    Signature::SIGNATURE_STR,
834                    ObjectPath::SIGNATURE_STR,
835                );
836                Err(Error::invalid_type(
837                    Unexpected::Str(&self.signature.to_string()),
838                    &expected.as_str(),
839                ))
840            }
841        }
842    }
843
844    fn visit_seq<V>(self, visitor: V) -> Result<Value<'de>, V::Error>
845    where
846        V: SeqAccess<'de>,
847    {
848        match &self.signature {
849            // For some reason rustc doesn't like us using ARRAY_SIGNATURE_CHAR const
850            Signature::Array(_) => self.visit_array(visitor),
851            Signature::Structure(_) => self.visit_struct(visitor),
852            Signature::Variant => self.visit_variant_as_seq(visitor),
853            s => Err(Error::invalid_value(
854                Unexpected::Str(&s.to_string()),
855                &"a Value signature",
856            )),
857        }
858    }
859
860    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de>, V::Error>
861    where
862        V: MapAccess<'de>,
863    {
864        let (key_signature, value_signature) = match &self.signature {
865            Signature::Dict { key, value } => (key.signature().clone(), value.signature().clone()),
866            Signature::Variant => return self.visit_variant_as_map(visitor),
867            _ => {
868                return Err(Error::invalid_type(
869                    Unexpected::Str(&self.signature.to_string()),
870                    &"a dict signature",
871                ))
872            }
873        };
874
875        let mut dict = Dict::new_full_signature(self.signature);
876
877        while let Some((key, value)) = visitor.next_entry_seed(
878            ValueSeed::<Value<'_>> {
879                signature: &key_signature,
880                phantom: PhantomData,
881            },
882            ValueSeed::<Value<'_>> {
883                signature: &value_signature,
884                phantom: PhantomData,
885            },
886        )? {
887            dict.append(key, value).map_err(Error::custom)?;
888        }
889
890        Ok(Value::Dict(dict))
891    }
892
893    #[cfg(feature = "gvariant")]
894    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
895    where
896        D: Deserializer<'de>,
897    {
898        let child_signature = match &self.signature {
899            Signature::Maybe(child) => child.signature().clone(),
900            _ => {
901                return Err(Error::invalid_type(
902                    Unexpected::Str(&self.signature.to_string()),
903                    &"a maybe signature",
904                ))
905            }
906        };
907        let visitor = ValueSeed::<T> {
908            signature: &child_signature,
909            phantom: PhantomData,
910        };
911
912        deserializer
913            .deserialize_any(visitor)
914            .map(|v| Value::Maybe(Maybe::just_full_signature(v, self.signature)))
915    }
916
917    #[cfg(not(feature = "gvariant"))]
918    fn visit_some<D>(self, _deserializer: D) -> Result<Self::Value, D::Error>
919    where
920        D: Deserializer<'de>,
921    {
922        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
923    }
924
925    #[cfg(feature = "gvariant")]
926    fn visit_none<E>(self) -> Result<Self::Value, E>
927    where
928        E: Error,
929    {
930        let value = Maybe::nothing_full_signature(self.signature);
931
932        Ok(Value::Maybe(value))
933    }
934
935    #[cfg(not(feature = "gvariant"))]
936    fn visit_none<E>(self) -> Result<Self::Value, E>
937    where
938        E: Error,
939    {
940        panic!("`Maybe` type is only supported for GVariant format but it's disabled");
941    }
942}
943
944impl<'de, T> DeserializeSeed<'de> for ValueSeed<'_, T>
945where
946    T: Deserialize<'de>,
947{
948    type Value = Value<'de>;
949
950    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
951    where
952        D: Deserializer<'de>,
953    {
954        deserializer.deserialize_any(self)
955    }
956}
957
958impl Type for Value<'_> {
959    const SIGNATURE: &'static Signature = &Signature::Variant;
960}
961
962impl<'a> TryFrom<&Value<'a>> for Value<'a> {
963    type Error = crate::Error;
964
965    fn try_from(value: &Value<'a>) -> crate::Result<Value<'a>> {
966        value.try_clone()
967    }
968}
969
970impl Clone for Value<'_> {
971    /// Clone the value.
972    ///
973    /// # Panics
974    ///
975    /// This method can only fail on Unix platforms for [`Value::Fd`] variant containing an
976    /// [`Fd::Owned`] variant. This happens when the current process exceeds the limit on maximum
977    /// number of open file descriptors.
978    fn clone(&self) -> Self {
979        self.try_clone()
980            .expect("Process exceeded limit on maximum number of open file descriptors")
981    }
982}
983
984#[cfg(test)]
985mod tests {
986    use std::collections::HashMap;
987
988    use super::*;
989
990    #[test]
991    fn value_display() {
992        assert_eq!(
993            Value::new((
994                255_u8,
995                true,
996                -1_i16,
997                65535_u16,
998                -1,
999                1_u32,
1000                -9223372036854775808_i64,
1001                18446744073709551615_u64,
1002                (-1., 1.0, 11000000000., 1.1e-10)
1003            ))
1004            .to_string(),
1005            "(byte 0xff, true, int16 -1, uint16 65535, -1, uint32 1, \
1006                int64 -9223372036854775808, uint64 18446744073709551615, \
1007                (-1., 1., 11000000000., 0.00000000011))"
1008        );
1009
1010        assert_eq!(
1011            Value::new(vec![
1012                "", " ", "a", r#"""#, "'", "a'b", "a'\"b", "\\", "\n'\"",
1013            ])
1014            .to_string(),
1015            r#"["", " ", "a", "\"", "'", "a'b", "a'\"b", "\\", "\n'\""]"#
1016        );
1017        assert_eq!(
1018            Value::new(vec![
1019                "\x07\x08\x09\x0A\x0B\x0C\x0D",
1020                "\x7F",
1021                char::from_u32(0xD8000).unwrap().to_string().as_str()
1022            ])
1023            .to_string(),
1024            r#"["\u{7}\u{8}\t\n\u{b}\u{c}\r", "\u{7f}", "\u{d8000}"]"#
1025        );
1026
1027        assert_eq!(
1028            Value::new((
1029                vec![
1030                    Signature::try_from("").unwrap(),
1031                    Signature::try_from("(ysa{sd})").unwrap(),
1032                ],
1033                vec![
1034                    ObjectPath::from_static_str("/").unwrap(),
1035                    ObjectPath::from_static_str("/a/very/looooooooooooooooooooooooo0000o0ng/path")
1036                        .unwrap(),
1037                ],
1038                vec![
1039                    Value::new(0_u8),
1040                    Value::new((Value::new(51), Value::new(Value::new(1_u32)))),
1041                ]
1042            ))
1043            .to_string(),
1044            "([signature \"\", \"(ysa{sd})\"], \
1045                [objectpath \"/\", \"/a/very/looooooooooooooooooooooooo0000o0ng/path\"], \
1046                [<byte 0x00>, <(<51>, <<uint32 1>>)>])"
1047        );
1048
1049        assert_eq!(Value::new(vec![] as Vec<Vec<i64>>).to_string(), "@aax []");
1050        assert_eq!(
1051            Value::new(vec![
1052                vec![0_i16, 1_i16],
1053                vec![2_i16, 3_i16],
1054                vec![4_i16, 5_i16]
1055            ])
1056            .to_string(),
1057            "[[int16 0, 1], [2, 3], [4, 5]]"
1058        );
1059        assert_eq!(
1060            Value::new(vec![
1061                b"Hello".to_vec(),
1062                b"Hell\0o".to_vec(),
1063                b"H\0ello\0".to_vec(),
1064                b"Hello\0".to_vec(),
1065                b"\0".to_vec(),
1066                b" \0".to_vec(),
1067                b"'\0".to_vec(),
1068                b"\n'\"\0".to_vec(),
1069                b"\\\0".to_vec(),
1070            ])
1071            .to_string(),
1072            "[[byte 0x48, 0x65, 0x6c, 0x6c, 0x6f], \
1073                [0x48, 0x65, 0x6c, 0x6c, 0x00, 0x6f], \
1074                [0x48, 0x00, 0x65, 0x6c, 0x6c, 0x6f, 0x00], \
1075                b\"Hello\", b\"\", b\" \", b\"'\", b\"\\n'\\\"\", b\"\\\\\"]"
1076        );
1077
1078        assert_eq!(
1079            Value::new(HashMap::<bool, bool>::new()).to_string(),
1080            "@a{bb} {}"
1081        );
1082        assert_eq!(
1083            Value::new(vec![(true, 0_i64)].into_iter().collect::<HashMap<_, _>>()).to_string(),
1084            "{true: int64 0}",
1085        );
1086        // The order of the entries may vary
1087        let val = Value::new(
1088            vec![(32_u16, 64_i64), (100_u16, 200_i64)]
1089                .into_iter()
1090                .collect::<HashMap<_, _>>(),
1091        )
1092        .to_string();
1093        assert!(val.starts_with('{'));
1094        assert!(val.ends_with('}'));
1095        assert_eq!(val.matches("uint16").count(), 1);
1096        assert_eq!(val.matches("int64").count(), 1);
1097
1098        let items_str = val.split(", ").collect::<Vec<_>>();
1099        assert_eq!(items_str.len(), 2);
1100        assert!(items_str
1101            .iter()
1102            .any(|str| str.contains("32") && str.contains(": ") && str.contains("64")));
1103        assert!(items_str
1104            .iter()
1105            .any(|str| str.contains("100") && str.contains(": ") && str.contains("200")));
1106
1107        assert_eq!(
1108            Value::new(((true,), (true, false), (true, true, false))).to_string(),
1109            "((true,), (true, false), (true, true, false))"
1110        );
1111
1112        #[cfg(any(feature = "gvariant", feature = "option-as-array"))]
1113        {
1114            #[cfg(unix)]
1115            use std::os::fd::BorrowedFd;
1116
1117            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1118            let s = "((@mn 0, @mmn 0, @mmmn 0), \
1119                (@mn nothing, @mmn just nothing, @mmmn just just nothing), \
1120                (@mmn nothing, @mmmn just nothing))";
1121            #[cfg(feature = "option-as-array")]
1122            let s = "(([int16 0], [[int16 0]], [[[int16 0]]]), \
1123                (@an [], [@an []], [[@an []]]), \
1124                (@aan [], [@aan []]))";
1125            assert_eq!(
1126                Value::new((
1127                    (Some(0_i16), Some(Some(0_i16)), Some(Some(Some(0_i16))),),
1128                    (None::<i16>, Some(None::<i16>), Some(Some(None::<i16>)),),
1129                    (None::<Option<i16>>, Some(None::<Option<i16>>)),
1130                ))
1131                .to_string(),
1132                s,
1133            );
1134
1135            #[cfg(unix)]
1136            assert_eq!(
1137                Value::new(vec![
1138                    Fd::from(unsafe { BorrowedFd::borrow_raw(0) }),
1139                    Fd::from(unsafe { BorrowedFd::borrow_raw(-100) })
1140                ])
1141                .to_string(),
1142                "[handle 0, -100]"
1143            );
1144
1145            #[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
1146            let s = "(@mb nothing, @mb nothing, \
1147                @ma{sv} {\"size\": <(800, 600)>}, \
1148                [<1>, <{\"dimension\": <([2.4, 1.], \
1149                @mmn 200, <(byte 0x03, \"Hello!\")>)>}>], \
1150                7777, objectpath \"/\", 8888)";
1151            #[cfg(feature = "option-as-array")]
1152            let s = "(@ab [], @ab [], [{\"size\": <(800, 600)>}], \
1153                [<1>, <{\"dimension\": <([2.4, 1.], [[int16 200]], \
1154                <(byte 0x03, \"Hello!\")>)>}>], 7777, objectpath \"/\", 8888)";
1155            assert_eq!(
1156                Value::new((
1157                    None::<bool>,
1158                    None::<bool>,
1159                    Some(
1160                        vec![("size", Value::new((800, 600)))]
1161                            .into_iter()
1162                            .collect::<HashMap<_, _>>()
1163                    ),
1164                    vec![
1165                        Value::new(1),
1166                        Value::new(
1167                            vec![(
1168                                "dimension",
1169                                Value::new((
1170                                    vec![2.4, 1.],
1171                                    Some(Some(200_i16)),
1172                                    Value::new((3_u8, "Hello!"))
1173                                ))
1174                            )]
1175                            .into_iter()
1176                            .collect::<HashMap<_, _>>()
1177                        )
1178                    ],
1179                    7777,
1180                    ObjectPath::from_static_str("/").unwrap(),
1181                    8888
1182                ))
1183                .to_string(),
1184                s,
1185            );
1186        }
1187    }
1188}