1 | #![allow (unknown_lints)] |
2 | use serde::{ |
3 | de::{DeserializeSeed, Deserializer, SeqAccess, Visitor}, |
4 | ser::{Serialize, SerializeSeq, Serializer}, |
5 | }; |
6 | use static_assertions::assert_impl_all; |
7 | use std::{ |
8 | convert::{TryFrom, TryInto}, |
9 | fmt::{Display, Write}, |
10 | }; |
11 | |
12 | use 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)] |
24 | pub struct Array<'a> { |
25 | element_signature: Signature<'a>, |
26 | elements: Vec<Value<'a>>, |
27 | signature: Signature<'a>, |
28 | } |
29 | |
30 | assert_impl_all!(Array<'_>: Send, Sync, Unpin); |
31 | |
32 | impl<'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 | |
108 | impl 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 | |
114 | pub(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]. |
164 | pub struct ArraySeed<'a> { |
165 | signature: Signature<'a>, |
166 | } |
167 | |
168 | impl<'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 | |
180 | assert_impl_all!(ArraySeed<'_>: Send, Sync, Unpin); |
181 | |
182 | impl<'a> DynamicType for Array<'a> { |
183 | fn dynamic_signature(&self) -> Signature<'_> { |
184 | self.signature.clone() |
185 | } |
186 | } |
187 | |
188 | impl<'a> DynamicType for ArraySeed<'a> { |
189 | fn dynamic_signature(&self) -> Signature<'_> { |
190 | self.signature.clone() |
191 | } |
192 | } |
193 | |
194 | impl<'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 | |
214 | impl<'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 | |
222 | impl<'a, T> From<Vec<T>> for Array<'a> |
223 | where |
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 | |
239 | impl<'a, T> From<&[T]> for Array<'a> |
240 | where |
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 | |
259 | impl<'a, T> From<&Vec<T>> for Array<'a> |
260 | where |
261 | T: Type + Into<Value<'a>> + Clone, |
262 | { |
263 | fn from(values: &Vec<T>) -> Self { |
264 | Self::from(&values[..]) |
265 | } |
266 | } |
267 | |
268 | impl<'a, T> TryFrom<Array<'a>> for Vec<T> |
269 | where |
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 | |
295 | impl<'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 | |
309 | impl<'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)] |
322 | struct ArrayVisitor<'a> { |
323 | signature: Signature<'a>, |
324 | } |
325 | |
326 | impl<'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 | |
344 | fn create_signature(element_signature: &Signature<'_>) -> Signature<'static> { |
345 | Signature::from_string_unchecked(signature:format!("a {element_signature}" )) |
346 | } |
347 | |