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