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