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    pub(crate) fn try_into_owned(self) -> Result<Array<'static>> {
118        Ok(Array {
119            elements: self
120                .elements
121                .into_iter()
122                .map(|v| v.try_into_owned().map(Into::into))
123                .collect::<Result<_>>()?,
124            signature: self.signature.clone(),
125        })
126    }
127
128    /// Tries to clone the `Array`.
129    pub fn try_clone(&self) -> crate::Result<Self> {
130        let elements = self
131            .elements
132            .iter()
133            .map(|v| v.try_clone())
134            .collect::<crate::Result<Vec<_>>>()?;
135
136        Ok(Self {
137            elements,
138            signature: self.signature.clone(),
139        })
140    }
141}
142
143impl Display for Array<'_> {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        array_display_fmt(self, f, true)
146    }
147}
148
149pub(crate) fn array_display_fmt(
150    array: &Array<'_>,
151    f: &mut std::fmt::Formatter<'_>,
152    type_annotate: bool,
153) -> std::fmt::Result {
154    // Print as string if it is a bytestring (i.e., first nul character is the last byte)
155    if let [leading @ .., Value::U8(b'\0')] = array.as_ref() {
156        if !leading.contains(&Value::U8(b'\0')) {
157            let bytes = leading
158                .iter()
159                .map(|v| {
160                    v.downcast_ref::<u8>()
161                        .expect("item must have a signature of a byte")
162                })
163                .collect::<Vec<_>>();
164
165            let string = String::from_utf8_lossy(&bytes);
166            write!(f, "b{:?}", string.as_ref())?;
167
168            return Ok(());
169        }
170    }
171
172    if array.is_empty() {
173        if type_annotate {
174            write!(f, "@{} ", array.signature())?;
175        }
176        f.write_str("[]")?;
177    } else {
178        f.write_char('[')?;
179
180        // Annotate only the first item as the rest will be of the same type.
181        let mut type_annotate = type_annotate;
182
183        for (i, item) in array.iter().enumerate() {
184            value_display_fmt(item, f, type_annotate)?;
185            type_annotate = false;
186
187            if i + 1 < array.len() {
188                f.write_str(", ")?;
189            }
190        }
191
192        f.write_char(']')?;
193    }
194
195    Ok(())
196}
197
198/// Use this to deserialize an [Array].
199pub struct ArraySeed {
200    signature: Signature,
201    phantom: std::marker::PhantomData<()>,
202}
203
204impl ArraySeed {
205    fn new(signature: &Signature) -> ArraySeed {
206        ArraySeed {
207            signature: signature.clone(),
208            phantom: std::marker::PhantomData,
209        }
210    }
211}
212
213impl DynamicType for Array<'_> {
214    fn signature(&self) -> Signature {
215        self.signature.clone()
216    }
217}
218
219impl DynamicType for ArraySeed {
220    fn signature(&self) -> Signature {
221        self.signature.clone()
222    }
223}
224
225impl<'a> DynamicDeserialize<'a> for Array<'a> {
226    type Deserializer = ArraySeed;
227
228    fn deserializer_for_signature(signature: &Signature) -> zvariant::Result<Self::Deserializer> {
229        if !matches!(signature, Signature::Array(_)) {
230            return Err(zvariant::Error::SignatureMismatch(
231                signature.clone(),
232                "an array signature".to_owned(),
233            ));
234        };
235
236        Ok(ArraySeed::new(signature))
237    }
238}
239
240impl<'a> std::ops::Deref for Array<'a> {
241    type Target = [Value<'a>];
242
243    fn deref(&self) -> &Self::Target {
244        self.inner()
245    }
246}
247
248impl<'a, T> From<Vec<T>> for Array<'a>
249where
250    T: Type + Into<Value<'a>>,
251{
252    fn from(values: Vec<T>) -> Self {
253        let element_signature = T::SIGNATURE.clone();
254        let elements = values.into_iter().map(Value::new).collect();
255        let signature = Signature::array(element_signature);
256
257        Self {
258            elements,
259            signature,
260        }
261    }
262}
263
264impl<'a, T> From<&[T]> for Array<'a>
265where
266    T: Type + Into<Value<'a>> + Clone,
267{
268    fn from(values: &[T]) -> Self {
269        let element_signature = T::SIGNATURE.clone();
270        let elements = values
271            .iter()
272            .map(|value| Value::new(value.clone()))
273            .collect();
274        let signature = Signature::array(element_signature);
275
276        Self {
277            elements,
278            signature,
279        }
280    }
281}
282
283impl<'a, T> From<&Vec<T>> for Array<'a>
284where
285    T: Type + Into<Value<'a>> + Clone,
286{
287    fn from(values: &Vec<T>) -> Self {
288        Self::from(&values[..])
289    }
290}
291
292impl<'a, T> TryFrom<Array<'a>> for Vec<T>
293where
294    T: TryFrom<Value<'a>>,
295    T::Error: Into<crate::Error>,
296{
297    type Error = Error;
298
299    fn try_from(v: Array<'a>) -> core::result::Result<Self, Self::Error> {
300        // there is no try_map yet..
301        let mut res = vec![];
302        for e in v.elements.into_iter() {
303            let value = if let Value::Value(v) = e {
304                T::try_from(*v)
305            } else {
306                T::try_from(e)
307            }
308            .map_err(Into::into)?;
309
310            res.push(value);
311        }
312        Ok(res)
313    }
314}
315
316// TODO: this could be useful
317// impl<'a, 'b, T> TryFrom<&'a Array<'b>> for Vec<T>
318
319impl Serialize for Array<'_> {
320    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
321    where
322        S: Serializer,
323    {
324        let mut seq = serializer.serialize_seq(Some(self.elements.len()))?;
325        for element in &self.elements {
326            element.serialize_value_as_seq_element(&mut seq)?;
327        }
328
329        seq.end()
330    }
331}
332
333impl<'de> DeserializeSeed<'de> for ArraySeed {
334    type Value = Array<'de>;
335    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
336    where
337        D: Deserializer<'de>,
338    {
339        deserializer.deserialize_seq(ArrayVisitor {
340            signature: self.signature,
341        })
342    }
343}
344
345#[derive(Debug, Clone, PartialEq, Eq)]
346struct ArrayVisitor {
347    signature: Signature,
348}
349
350impl<'de> Visitor<'de> for ArrayVisitor {
351    type Value = Array<'de>;
352
353    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354        formatter.write_str("an Array value")
355    }
356
357    fn visit_seq<V>(self, visitor: V) -> std::result::Result<Array<'de>, V::Error>
358    where
359        V: SeqAccess<'de>,
360    {
361        SignatureSeed {
362            signature: &self.signature,
363        }
364        .visit_array(visitor)
365    }
366}