1 | use core::str; |
2 | use std::{ |
3 | convert::TryFrom, |
4 | fmt::{Display, Write}, |
5 | marker::PhantomData, |
6 | }; |
7 | |
8 | use serde::{ |
9 | de::{ |
10 | Deserialize, DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Unexpected, |
11 | Visitor, |
12 | }, |
13 | ser::{Serialize, SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer}, |
14 | }; |
15 | use static_assertions::assert_impl_all; |
16 | |
17 | use 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" )] |
23 | use crate::{maybe_display_fmt, Maybe}; |
24 | |
25 | #[cfg (unix)] |
26 | use 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)] |
79 | pub 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 | |
106 | assert_impl_all!(Value<'_>: Send, Sync, Unpin); |
107 | |
108 | macro_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 | |
138 | impl<'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 | |
374 | impl 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 |
381 | pub(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 | |
478 | impl<'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 | |
495 | impl<'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 | |
510 | struct ValueVisitor; |
511 | |
512 | impl<'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 | |
555 | pub(crate) struct SignatureSeed<'de> { |
556 | pub signature: Signature<'de>, |
557 | } |
558 | |
559 | impl<'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 | |
603 | impl<'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 | |
611 | struct ValueSeed<'de, T> { |
612 | signature: Signature<'de>, |
613 | phantom: PhantomData<T>, |
614 | } |
615 | |
616 | impl<'de, T> ValueSeed<'de, T> |
617 | where |
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 | |
651 | macro_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 | |
663 | macro_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 | |
690 | impl<'de, T> Visitor<'de> for ValueSeed<'de, T> |
691 | where |
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 | |
831 | impl<'de, T> DeserializeSeed<'de> for ValueSeed<'de, T> |
832 | where |
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 | |
845 | impl<'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)] |
852 | mod 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 | |