zvariant/
array.rs

1#![allow(unknown_lints)]
2use serde::{
3    de::{DeserializeSeed, Deserializer, SeqAccess, Visitor},
4    ser::{Serialize, SerializeSeq, Serializer},
5};
6use std::fmt::{Display, Write};
7
8use crate::{
9    value::{value_display_fmt, SignatureSeed},
10    DynamicDeserialize, DynamicType, Error, Result, Signature, Type, Value,
11};
12
13/// A helper type to wrap arrays in a [`Value`].
14///
15/// API is provided to convert from, and to a [`Vec`].
16///
17/// [`Value`]: enum.Value.html#variant.Array
18/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
19#[derive(Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
20pub struct Array<'a> {
21    elements: Vec<Value<'a>>,
22    signature: Signature,
23}
24
25impl<'a> Array<'a> {
26    /// Create a new empty `Array`, given the signature of the elements.
27    pub fn new(element_signature: &Signature) -> Array<'a> {
28        let signature = Signature::array(element_signature.clone());
29
30        Array {
31            elements: vec![],
32            signature,
33        }
34    }
35
36    pub(crate) fn new_full_signature(signature: &Signature) -> Array<'a> {
37        assert!(matches!(signature, Signature::Array(_)));
38
39        Array {
40            elements: vec![],
41            signature: signature.clone(),
42        }
43    }
44
45    /// Append `element`.
46    ///
47    /// # Errors
48    ///
49    /// if `element`'s signature doesn't match the element signature `self` was created for.
50    pub fn append<'e: 'a>(&mut self, element: Value<'e>) -> Result<()> {
51        match &self.signature {
52            Signature::Array(child) if element.value_signature() != child.signature() => {
53                return Err(Error::SignatureMismatch(
54                    element.value_signature().clone(),
55                    child.signature().clone().to_string(),
56                ))
57            }
58            Signature::Array(_) => (),
59            _ => unreachable!("Incorrect `Array` signature"),
60        }
61
62        self.elements.push(element);
63
64        Ok(())
65    }
66
67    /// Get all the elements.
68    pub fn inner(&self) -> &[Value<'a>] {
69        &self.elements
70    }
71
72    /// Get the value at the given index.
73    pub fn get<V>(&'a self, idx: usize) -> Result<Option<V>>
74    where
75        V: TryFrom<&'a Value<'a>>,
76        <V as TryFrom<&'a Value<'a>>>::Error: Into<crate::Error>,
77    {
78        self.elements
79            .get(idx)
80            .map(|v| v.downcast_ref::<V>())
81            .transpose()
82    }
83
84    /// Get the number of elements.
85    pub fn len(&self) -> usize {
86        self.elements.len()
87    }
88
89    pub fn is_empty(&self) -> bool {
90        self.elements.len() == 0
91    }
92
93    /// The signature of the `Array`.
94    pub fn signature(&self) -> &Signature {
95        &self.signature
96    }
97
98    /// Get the signature of the elements in the `Array`.
99    pub fn element_signature(&self) -> &Signature {
100        match &self.signature {
101            Signature::Array(child) => child.signature(),
102            _ => unreachable!("Incorrect `Array` signature"),
103        }
104    }
105
106    pub(crate) fn try_to_owned(&self) -> Result<Array<'static>> {
107        Ok(Array {
108            elements: self
109                .elements
110                .iter()
111                .map(|v| v.try_to_owned().map(Into::into))
112                .collect::<Result<_>>()?,
113            signature: self.signature.clone(),
114        })
115    }
116
117    /// Tries to clone the `Array`.
118    pub fn try_clone(&self) -> crate::Result<Self> {
119        let elements = self
120            .elements
121            .iter()
122            .map(|v| v.try_clone())
123            .collect::<crate::Result<Vec<_>>>()?;
124
125        Ok(Self {
126            elements,
127            signature: self.signature.clone(),
128        })
129    }
130}
131
132impl Display for Array<'_> {
133    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        array_display_fmt(self, f, true)
135    }
136}
137
138pub(crate) fn array_display_fmt(
139    array: &Array<'_>,
140    f: &mut std::fmt::Formatter<'_>,
141    type_annotate: bool,
142) -> std::fmt::Result {
143    // Print as string if it is a bytestring (i.e., first nul character is the last byte)
144    if let [leading @ .., Value::U8(b'\0')] = array.as_ref() {
145        if !leading.contains(&Value::U8(b'\0')) {
146            let bytes = leading
147                .iter()
148                .map(|v| {
149                    v.downcast_ref::<u8>()
150                        .expect("item must have a signature of a byte")
151                })
152                .collect::<Vec<_>>();
153
154            let string = String::from_utf8_lossy(&bytes);
155            write!(f, "b{:?}", string.as_ref())?;
156
157            return Ok(());
158        }
159    }
160
161    if array.is_empty() {
162        if type_annotate {
163            write!(f, "@{} ", array.signature())?;
164        }
165        f.write_str("[]")?;
166    } else {
167        f.write_char('[')?;
168
169        // Annotate only the first item as the rest will be of the same type.
170        let mut type_annotate = type_annotate;
171
172        for (i, item) in array.iter().enumerate() {
173            value_display_fmt(item, f, type_annotate)?;
174            type_annotate = false;
175
176            if i + 1 < array.len() {
177                f.write_str(", ")?;
178            }
179        }
180
181        f.write_char(']')?;
182    }
183
184    Ok(())
185}
186
187/// Use this to deserialize an [Array].
188pub struct ArraySeed {
189    signature: Signature,
190    phantom: std::marker::PhantomData<()>,
191}
192
193impl ArraySeed {
194    fn new(signature: &Signature) -> ArraySeed {
195        ArraySeed {
196            signature: signature.clone(),
197            phantom: std::marker::PhantomData,
198        }
199    }
200}
201
202impl DynamicType for Array<'_> {
203    fn signature(&self) -> Signature {
204        self.signature.clone()
205    }
206}
207
208impl DynamicType for ArraySeed {
209    fn signature(&self) -> Signature {
210        self.signature.clone()
211    }
212}
213
214impl<'a> DynamicDeserialize<'a> for Array<'a> {
215    type Deserializer = ArraySeed;
216
217    fn deserializer_for_signature(signature: &Signature) -> zvariant::Result<Self::Deserializer> {
218        if !matches!(signature, Signature::Array(_)) {
219            return Err(zvariant::Error::SignatureMismatch(
220                signature.clone(),
221                "an array signature".to_owned(),
222            ));
223        };
224
225        Ok(ArraySeed::new(signature))
226    }
227}
228
229impl<'a> std::ops::Deref for Array<'a> {
230    type Target = [Value<'a>];
231
232    fn deref(&self) -> &Self::Target {
233        self.inner()
234    }
235}
236
237impl<'a, T> From<Vec<T>> for Array<'a>
238where
239    T: Type + Into<Value<'a>>,
240{
241    fn from(values: Vec<T>) -> Self {
242        let element_signature = T::SIGNATURE.clone();
243        let elements = values.into_iter().map(Value::new).collect();
244        let signature = Signature::array(element_signature);
245
246        Self {
247            elements,
248            signature,
249        }
250    }
251}
252
253impl<'a, T> From<&[T]> for Array<'a>
254where
255    T: Type + Into<Value<'a>> + Clone,
256{
257    fn from(values: &[T]) -> Self {
258        let element_signature = T::SIGNATURE.clone();
259        let elements = values
260            .iter()
261            .map(|value| Value::new(value.clone()))
262            .collect();
263        let signature = Signature::array(element_signature);
264
265        Self {
266            elements,
267            signature,
268        }
269    }
270}
271
272impl<'a, T> From<&Vec<T>> for Array<'a>
273where
274    T: Type + Into<Value<'a>> + Clone,
275{
276    fn from(values: &Vec<T>) -> Self {
277        Self::from(&values[..])
278    }
279}
280
281impl<'a, T> TryFrom<Array<'a>> for Vec<T>
282where
283    T: TryFrom<Value<'a>>,
284    T::Error: Into<crate::Error>,
285{
286    type Error = Error;
287
288    fn try_from(v: Array<'a>) -> core::result::Result<Self, Self::Error> {
289        // there is no try_map yet..
290        let mut res = vec![];
291        for e in v.elements.into_iter() {
292            let value = if let Value::Value(v) = e {
293                T::try_from(*v)
294            } else {
295                T::try_from(e)
296            }
297            .map_err(Into::into)?;
298
299            res.push(value);
300        }
301        Ok(res)
302    }
303}
304
305// TODO: this could be useful
306// impl<'a, 'b, T> TryFrom<&'a Array<'b>> for Vec<T>
307
308impl Serialize for Array<'_> {
309    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
310    where
311        S: Serializer,
312    {
313        let mut seq = serializer.serialize_seq(Some(self.elements.len()))?;
314        for element in &self.elements {
315            element.serialize_value_as_seq_element(&mut seq)?;
316        }
317
318        seq.end()
319    }
320}
321
322impl<'de> DeserializeSeed<'de> for ArraySeed {
323    type Value = Array<'de>;
324    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
325    where
326        D: Deserializer<'de>,
327    {
328        deserializer.deserialize_seq(ArrayVisitor {
329            signature: self.signature,
330        })
331    }
332}
333
334#[derive(Debug, Clone, PartialEq, Eq)]
335struct ArrayVisitor {
336    signature: Signature,
337}
338
339impl<'de> Visitor<'de> for ArrayVisitor {
340    type Value = Array<'de>;
341
342    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
343        formatter.write_str("an Array value")
344    }
345
346    fn visit_seq<V>(self, visitor: V) -> std::result::Result<Array<'de>, V::Error>
347    where
348        V: SeqAccess<'de>,
349    {
350        SignatureSeed {
351            signature: &self.signature,
352        }
353        .visit_array(visitor)
354    }
355}