1 use serde::{
2 de::{DeserializeSeed, Deserializer, SeqAccess, Visitor},
3 ser::{Serialize, SerializeSeq, Serializer},
4 };
5 use static_assertions::assert_impl_all;
6 use std::convert::{TryFrom, TryInto};
7
8 use crate::{
9 value::SignatureSeed, DynamicDeserialize, DynamicType, Error, Result, Signature, Type, Value,
10 };
11
12 /// A helper type to wrap arrays in a [`Value`].
13 ///
14 /// API is provided to convert from, and to a [`Vec`].
15 ///
16 /// [`Value`]: enum.Value.html#variant.Array
17 /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
18 #[derive(Debug, Clone, PartialEq)]
19 pub struct Array<'a> {
20 element_signature: Signature<'a>,
21 elements: Vec<Value<'a>>,
22 signature: Signature<'a>,
23 }
24
25 assert_impl_all!(Array<'_>: Send, Sync, Unpin);
26
27 impl<'a> Array<'a> {
28 /// Create a new empty `Array`, given the signature of the elements.
new(element_signature: Signature<'_>) -> Array<'_>29 pub fn new(element_signature: Signature<'_>) -> Array<'_> {
30 let signature = create_signature(&element_signature);
31 Array {
32 element_signature,
33 elements: vec![],
34 signature,
35 }
36 }
37
new_full_signature(signature: Signature<'_>) -> Array<'_>38 pub(crate) fn new_full_signature(signature: Signature<'_>) -> Array<'_> {
39 let element_signature = signature.slice(1..);
40 Array {
41 element_signature,
42 elements: vec![],
43 signature,
44 }
45 }
46
47 /// Append `element`.
48 ///
49 /// # Errors
50 ///
51 /// if `element`'s signature doesn't match the element signature `self` was created for.
append<'e: 'a>(&mut self, element: Value<'e>) -> Result<()>52 pub fn append<'e: 'a>(&mut self, element: Value<'e>) -> Result<()> {
53 check_child_value_signature!(self.element_signature, element.value_signature(), "element");
54
55 self.elements.push(element);
56
57 Ok(())
58 }
59
60 /// Get all the elements.
get(&self) -> &[Value<'a>]61 pub fn get(&self) -> &[Value<'a>] {
62 &self.elements
63 }
64
65 /// Get the number of elements.
len(&self) -> usize66 pub fn len(&self) -> usize {
67 self.elements.len()
68 }
69
is_empty(&self) -> bool70 pub fn is_empty(&self) -> bool {
71 self.elements.len() == 0
72 }
73
74 /// Get the signature of this `Array`.
75 ///
76 /// NB: This method potentially allocates and copies. Use [`full_signature`] if you'd like to
77 /// avoid that.
78 ///
79 /// [`full_signature`]: #method.full_signature
signature(&self) -> Signature<'static>80 pub fn signature(&self) -> Signature<'static> {
81 self.signature.to_owned()
82 }
83
84 /// Get the signature of this `Array`.
full_signature(&self) -> &Signature<'_>85 pub fn full_signature(&self) -> &Signature<'_> {
86 &self.signature
87 }
88
89 /// Get the signature of the elements in the `Array`.
element_signature(&self) -> &Signature<'_>90 pub fn element_signature(&self) -> &Signature<'_> {
91 &self.element_signature
92 }
93
to_owned(&self) -> Array<'static>94 pub(crate) fn to_owned(&self) -> Array<'static> {
95 Array {
96 element_signature: self.element_signature.to_owned(),
97 elements: self.elements.iter().map(|v| v.to_owned()).collect(),
98 signature: self.signature.to_owned(),
99 }
100 }
101 }
102
103 /// Use this to deserialize an [Array].
104 pub struct ArraySeed<'a> {
105 signature: Signature<'a>,
106 }
107
108 impl<'a> ArraySeed<'a> {
109 /// Create a new empty `Array`, given the signature of the elements.
new(element_signature: Signature<'_>) -> ArraySeed<'_>110 pub fn new(element_signature: Signature<'_>) -> ArraySeed<'_> {
111 let signature = create_signature(&element_signature);
112 ArraySeed { signature }
113 }
114
new_full_signature(signature: Signature<'_>) -> ArraySeed<'_>115 pub(crate) fn new_full_signature(signature: Signature<'_>) -> ArraySeed<'_> {
116 ArraySeed { signature }
117 }
118 }
119
120 assert_impl_all!(ArraySeed<'_>: Send, Sync, Unpin);
121
122 impl<'a> DynamicType for Array<'a> {
dynamic_signature(&self) -> Signature<'_>123 fn dynamic_signature(&self) -> Signature<'_> {
124 self.signature.clone()
125 }
126 }
127
128 impl<'a> DynamicType for ArraySeed<'a> {
dynamic_signature(&self) -> Signature<'_>129 fn dynamic_signature(&self) -> Signature<'_> {
130 self.signature.clone()
131 }
132 }
133
134 impl<'a> DynamicDeserialize<'a> for Array<'a> {
135 type Deserializer = ArraySeed<'a>;
136
deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer> where S: TryInto<Signature<'a>>, S::Error: Into<zvariant::Error>,137 fn deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer>
138 where
139 S: TryInto<Signature<'a>>,
140 S::Error: Into<zvariant::Error>,
141 {
142 let signature = signature.try_into().map_err(Into::into)?;
143 if signature.starts_with(zvariant::ARRAY_SIGNATURE_CHAR) {
144 Ok(ArraySeed::new_full_signature(signature))
145 } else {
146 Err(zvariant::Error::SignatureMismatch(
147 signature.to_owned(),
148 "an array signature".to_owned(),
149 ))
150 }
151 }
152 }
153
154 impl<'a> std::ops::Deref for Array<'a> {
155 type Target = [Value<'a>];
156
deref(&self) -> &Self::Target157 fn deref(&self) -> &Self::Target {
158 self.get()
159 }
160 }
161
162 impl<'a, T> From<Vec<T>> for Array<'a>
163 where
164 T: Type + Into<Value<'a>>,
165 {
from(values: Vec<T>) -> Self166 fn from(values: Vec<T>) -> Self {
167 let element_signature = T::signature();
168 let elements = values.into_iter().map(Value::new).collect();
169 let signature = create_signature(&element_signature);
170
171 Self {
172 element_signature,
173 elements,
174 signature,
175 }
176 }
177 }
178
179 impl<'a, T> From<&[T]> for Array<'a>
180 where
181 T: Type + Into<Value<'a>> + Clone,
182 {
from(values: &[T]) -> Self183 fn from(values: &[T]) -> Self {
184 let element_signature = T::signature();
185 let elements = values
186 .iter()
187 .map(|value| Value::new(value.clone()))
188 .collect();
189 let signature = create_signature(&element_signature);
190
191 Self {
192 element_signature,
193 elements,
194 signature,
195 }
196 }
197 }
198
199 impl<'a, T> From<&Vec<T>> for Array<'a>
200 where
201 T: Type + Into<Value<'a>> + Clone,
202 {
from(values: &Vec<T>) -> Self203 fn from(values: &Vec<T>) -> Self {
204 Self::from(&values[..])
205 }
206 }
207
208 impl<'a, T> TryFrom<Array<'a>> for Vec<T>
209 where
210 T: TryFrom<Value<'a>>,
211 T::Error: Into<crate::Error>,
212 {
213 type Error = Error;
214
try_from(v: Array<'a>) -> core::result::Result<Self, Self::Error>215 fn try_from(v: Array<'a>) -> core::result::Result<Self, Self::Error> {
216 // there is no try_map yet..
217 let mut res = vec![];
218 for e in v.elements.into_iter() {
219 let value = if let Value::Value(v) = e {
220 T::try_from(*v)
221 } else {
222 T::try_from(e)
223 }
224 .map_err(Into::into)?;
225
226 res.push(value);
227 }
228 Ok(res)
229 }
230 }
231
232 // TODO: this could be useful
233 // impl<'a, 'b, T> TryFrom<&'a Array<'b>> for Vec<T>
234
235 impl<'a> Serialize for Array<'a> {
serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> where S: Serializer,236 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
237 where
238 S: Serializer,
239 {
240 let mut seq = serializer.serialize_seq(Some(self.elements.len()))?;
241 for element in &self.elements {
242 element.serialize_value_as_seq_element(&mut seq)?;
243 }
244
245 seq.end()
246 }
247 }
248
249 impl<'de> DeserializeSeed<'de> for ArraySeed<'de> {
250 type Value = Array<'de>;
deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error> where D: Deserializer<'de>,251 fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
252 where
253 D: Deserializer<'de>,
254 {
255 deserializer.deserialize_seq(ArrayVisitor {
256 signature: self.signature,
257 })
258 }
259 }
260
261 #[derive(Debug, Clone, PartialEq)]
262 struct ArrayVisitor<'a> {
263 signature: Signature<'a>,
264 }
265
266 impl<'de> Visitor<'de> for ArrayVisitor<'de> {
267 type Value = Array<'de>;
268
expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result269 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
270 formatter.write_str("an Array value")
271 }
272
visit_seq<V>(self, visitor: V) -> std::result::Result<Array<'de>, V::Error> where V: SeqAccess<'de>,273 fn visit_seq<V>(self, visitor: V) -> std::result::Result<Array<'de>, V::Error>
274 where
275 V: SeqAccess<'de>,
276 {
277 SignatureSeed {
278 signature: self.signature,
279 }
280 .visit_array(visitor)
281 }
282 }
283
create_signature(element_signature: &Signature<'_>) -> Signature<'static>284 fn create_signature(element_signature: &Signature<'_>) -> Signature<'static> {
285 Signature::from_string_unchecked(format!("a{}", element_signature))
286 }
287