zvariant/
array.rs

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