1 | use core::str; |
2 | use std::marker::PhantomData; |
3 | |
4 | use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; |
5 | use static_assertions::assert_impl_all; |
6 | |
7 | use crate::{Signature, Type, Value}; |
8 | |
9 | /// A wrapper to deserialize a value to `T: Type + Deserialize`. |
10 | /// |
11 | /// When the type of a value is well-known, you may avoid the cost and complexity of wrapping to a |
12 | /// generic [`Value`] and instead use this wrapper. |
13 | /// |
14 | /// ``` |
15 | /// # use zvariant::{to_bytes, EncodingContext, DeserializeValue, SerializeValue, from_slice}; |
16 | /// # |
17 | /// # let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0); |
18 | /// # let array = [0, 1, 2]; |
19 | /// # let v = SerializeValue(&array); |
20 | /// # let encoded = to_bytes(ctxt, &v).unwrap(); |
21 | /// let decoded: DeserializeValue<[u8; 3]> = from_slice(&encoded, ctxt).unwrap(); |
22 | /// # assert_eq!(decoded.0, array); |
23 | /// ``` |
24 | /// |
25 | /// [`Value`]: enum.Value.html |
26 | pub struct DeserializeValue<'de, T: Type + Deserialize<'de>>( |
27 | pub T, |
28 | std::marker::PhantomData<&'de T>, |
29 | ); |
30 | |
31 | assert_impl_all!(DeserializeValue<'_, i32>: Send, Sync, Unpin); |
32 | |
33 | impl<'de, T: Type + Deserialize<'de>> Deserialize<'de> for DeserializeValue<'de, T> { |
34 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
35 | where |
36 | D: Deserializer<'de>, |
37 | { |
38 | const FIELDS: &[&str] = &["zvariant::Value::Signature" , "zvariant::Value::Value" ]; |
39 | Ok(DeserializeValue( |
40 | deserializer.deserialize_struct( |
41 | name:"zvariant::Value" , |
42 | FIELDS, |
43 | visitor:DeserializeValueVisitor(PhantomData), |
44 | )?, |
45 | PhantomData, |
46 | )) |
47 | } |
48 | } |
49 | |
50 | struct DeserializeValueVisitor<T>(PhantomData<T>); |
51 | |
52 | impl<'de, T: Type + Deserialize<'de>> Visitor<'de> for DeserializeValueVisitor<T> { |
53 | type Value = T; |
54 | |
55 | fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
56 | formatter.write_str("zvariant::Value" ) |
57 | } |
58 | |
59 | fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error> |
60 | where |
61 | V: SeqAccess<'de>, |
62 | { |
63 | let sig: Signature<'_> = seq |
64 | .next_element()? |
65 | .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?; |
66 | if sig != T::signature() { |
67 | return Err(serde::de::Error::invalid_value( |
68 | serde::de::Unexpected::Str(&sig), |
69 | &"the value signature" , |
70 | )); |
71 | } |
72 | |
73 | seq.next_element()? |
74 | .ok_or_else(|| serde::de::Error::invalid_length(1, &self)) |
75 | } |
76 | } |
77 | |
78 | impl<'de, T: Type + Deserialize<'de>> Type for DeserializeValue<'de, T> { |
79 | fn signature() -> Signature<'static> { |
80 | Value::signature() |
81 | } |
82 | } |
83 | |