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