1#![allow(unknown_lints)]
2use serde::{
3 de::{DeserializeSeed, Deserializer, SeqAccess, Visitor},
4 ser::{Serialize, SerializeTupleStruct, Serializer},
5};
6use static_assertions::assert_impl_all;
7use std::{
8 convert::TryInto,
9 fmt::{Display, Write},
10};
11
12use crate::{
13 signature_parser::SignatureParser, value::SignatureSeed, value_display_fmt, DynamicDeserialize,
14 DynamicType, OwnedValue, Signature, Value,
15};
16
17/// Use this to efficiently build a [`Structure`].
18///
19/// [`Structure`]: struct.Structure.html
20#[derive(Debug, Default, Clone, PartialEq)]
21pub struct StructureBuilder<'a>(Vec<Value<'a>>);
22
23assert_impl_all!(StructureBuilder<'_>: Send, Sync, Unpin);
24
25impl<'a> StructureBuilder<'a> {
26 /// Create a new `StructureBuilder`.
27 ///
28 /// Same as `StructureBuilder::default()`.
29 pub fn new() -> Self {
30 Self::default()
31 }
32
33 /// Append `field` to `self`.
34 ///
35 /// This method returns `Self` so that you can use the builder pattern to create a complex
36 /// structure.
37 #[must_use]
38 pub fn add_field<T>(self, field: T) -> Self
39 where
40 T: DynamicType + Into<Value<'a>>,
41 {
42 self.append_field(Value::new(field))
43 }
44
45 /// Append `field` to `self`.
46 ///
47 /// Identical to `add_field`, except the field must be in the form of a `Value`.
48 #[must_use]
49 pub fn append_field<'e: 'a>(mut self, field: Value<'e>) -> Self {
50 self.0.push(field);
51
52 self
53 }
54
55 /// Append `field` to `self`.
56 ///
57 /// Identical to `add_field`, except it makes changes in-place.
58 pub fn push_field<T>(&mut self, field: T)
59 where
60 T: DynamicType + Into<Value<'a>>,
61 {
62 self.push_value(Value::new(field))
63 }
64
65 /// Append `field` to `self`.
66 ///
67 /// Identical to `append_field`, except it makes changes in-place.
68 pub fn push_value<'e: 'a>(&mut self, field: Value<'e>) {
69 self.0.push(field)
70 }
71
72 /// Build the `Structure`.
73 ///
74 /// [`Structure`]: struct.Structure.html
75 pub fn build(self) -> Structure<'a> {
76 let signature = create_signature_from_fields(&self.0);
77
78 Structure {
79 fields: self.0,
80 signature,
81 }
82 }
83
84 /// Same as `build` except Signature is provided.
85 pub(crate) fn build_with_signature<'s: 'a>(self, signature: Signature<'s>) -> Structure<'a> {
86 Structure {
87 fields: self.0,
88 signature,
89 }
90 }
91}
92
93/// Use this to deserialize a [`Structure`].
94///
95/// [`Structure`]: struct.Structure.html
96#[derive(Debug, Clone, PartialEq, Eq)]
97pub struct StructureSeed<'a>(Signature<'a>);
98
99assert_impl_all!(StructureSeed<'_>: Send, Sync, Unpin);
100
101impl<'a> StructureSeed<'a> {
102 /// Create a new `StructureSeed`
103 ///
104 /// The given signature must be a valid structure signature.
105 #[must_use]
106 pub fn new_unchecked(signature: Signature<'a>) -> Self {
107 StructureSeed(signature)
108 }
109}
110
111impl<'a> std::convert::TryFrom<Signature<'a>> for StructureSeed<'a> {
112 type Error = zvariant::Error;
113
114 fn try_from(signature: Signature<'a>) -> Result<Self, zvariant::Error> {
115 if signature.starts_with(zvariant::STRUCT_SIG_START_CHAR) {
116 Ok(StructureSeed(signature))
117 } else {
118 Err(zvariant::Error::IncorrectType)
119 }
120 }
121}
122
123impl<'de> DeserializeSeed<'de> for StructureSeed<'de> {
124 type Value = Structure<'de>;
125 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
126 where
127 D: Deserializer<'de>,
128 {
129 deserializer.deserialize_seq(visitor:StructureVisitor { signature: self.0 })
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
134struct StructureVisitor<'a> {
135 signature: Signature<'a>,
136}
137
138impl<'de> Visitor<'de> for StructureVisitor<'de> {
139 type Value = Structure<'de>;
140
141 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 formatter.write_str(data:"a Structure value")
143 }
144
145 fn visit_seq<V>(self, visitor: V) -> Result<Structure<'de>, V::Error>
146 where
147 V: SeqAccess<'de>,
148 {
149 SignatureSeed {
150 signature: self.signature,
151 }
152 .visit_struct(visitor)
153 }
154}
155
156/// A helper type to wrap structs in [`Value`].
157///
158/// API is provided to convert from, and to tuples.
159///
160/// [`Value`]: enum.Value.html
161#[derive(Debug, Clone, PartialEq)]
162pub struct Structure<'a> {
163 fields: Vec<Value<'a>>,
164 signature: Signature<'a>,
165}
166
167assert_impl_all!(Structure<'_>: Send, Sync, Unpin);
168
169impl<'a> Structure<'a> {
170 /// Get a reference to all the fields of `self`.
171 pub fn fields(&self) -> &[Value<'a>] {
172 &self.fields
173 }
174
175 /// Converts `self` to a `Vec` containing all its fields.
176 pub fn into_fields(self) -> Vec<Value<'a>> {
177 self.fields
178 }
179
180 /// Get the signature of this `Structure`.
181 ///
182 /// NB: This method potentially allocates and copies. Use [`full_signature`] if you'd like to
183 /// avoid that.
184 ///
185 /// [`full_signature`]: #method.full_signature
186 pub fn signature(&self) -> Signature<'static> {
187 self.signature.to_owned()
188 }
189
190 /// Get the signature of this `Structure`.
191 pub fn full_signature(&self) -> &Signature<'_> {
192 &self.signature
193 }
194
195 pub(crate) fn to_owned(&self) -> Structure<'static> {
196 Structure {
197 fields: self.fields.iter().map(|v| v.to_owned().into()).collect(),
198 signature: self.signature.to_owned(),
199 }
200 }
201}
202
203impl Display for Structure<'_> {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 structure_display_fmt(self, f, type_annotate:true)
206 }
207}
208
209pub(crate) fn structure_display_fmt(
210 structure: &Structure<'_>,
211 f: &mut std::fmt::Formatter<'_>,
212 type_annotate: bool,
213) -> std::fmt::Result {
214 f.write_char('(')?;
215
216 let fields: &[Value<'_>] = structure.fields();
217
218 match fields.len() {
219 0 => {}
220 1 => {
221 value_display_fmt(&fields[0], f, type_annotate)?;
222 f.write_char(',')?;
223 }
224 _ => {
225 for (i: usize, field: &Value<'_>) in fields.iter().enumerate() {
226 value_display_fmt(value:field, f, type_annotate)?;
227
228 if i + 1 < fields.len() {
229 f.write_str(data:", ")?;
230 }
231 }
232 }
233 }
234
235 f.write_char(')')
236}
237
238impl<'a> Default for Structure<'a> {
239 fn default() -> Self {
240 let signature: Signature<'_> = Signature::from_static_str_unchecked(signature:"()");
241
242 Self {
243 fields: vec![],
244 signature,
245 }
246 }
247}
248
249impl<'a> DynamicType for Structure<'a> {
250 fn dynamic_signature(&self) -> Signature<'_> {
251 self.signature.clone()
252 }
253}
254
255impl<'a> DynamicType for StructureSeed<'a> {
256 fn dynamic_signature(&self) -> Signature<'_> {
257 self.0.clone()
258 }
259}
260
261impl<'a> DynamicDeserialize<'a> for Structure<'a> {
262 type Deserializer = StructureSeed<'a>;
263
264 fn deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer>
265 where
266 S: TryInto<Signature<'a>>,
267 S::Error: Into<zvariant::Error>,
268 {
269 let mut signature = signature.try_into().map_err(Into::into)?;
270 if !signature.starts_with(zvariant::STRUCT_SIG_START_CHAR) {
271 // This is certainly not a valid struct signature
272 signature = format!("({signature})").try_into()?;
273 return signature.try_into();
274 }
275
276 // The signature might be something like "(i)u(i)" - we need to parse it to check.
277 let mut parser = SignatureParser::new(signature.clone());
278 parser.parse_next_signature()?;
279 if !parser.done() {
280 // more than one element - we must wrap it
281 signature = format!("({signature})").try_into()?;
282 }
283 signature.try_into()
284 }
285}
286
287impl<'a> Serialize for Structure<'a> {
288 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
289 where
290 S: Serializer,
291 {
292 let mut structure: ::SerializeTupleStruct =
293 serializer.serialize_tuple_struct(name:"zvariant::Structure", self.fields.len())?;
294 for field: &Value<'_> in &self.fields {
295 field.serialize_value_as_tuple_struct_field(&mut structure)?;
296 }
297 structure.end()
298 }
299}
300
301macro_rules! tuple_impls {
302 ($($len:expr => ($($n:tt $name:ident)+))+) => {
303 $(
304 impl<'a, $($name),+> From<($($name),+,)> for Structure<'a>
305 where
306 $($name: DynamicType + Into<Value<'a>>,)+
307 {
308 #[inline]
309 fn from(value: ($($name),+,)) -> Self {
310 StructureBuilder::new()
311 $(
312 .add_field(value. $n)
313 )+
314 .build()
315 }
316 }
317
318 impl<'a, E, $($name),+> std::convert::TryFrom<Structure<'a>> for ($($name),+,)
319 where
320 $($name: std::convert::TryFrom<Value<'a>, Error = E>,)+
321 crate::Error: From<E>,
322
323 {
324 type Error = crate::Error;
325
326 fn try_from(mut s: Structure<'a>) -> core::result::Result<Self, Self::Error> {
327 Ok((
328 $(
329 $name::try_from(s.fields.remove(0))?,
330 )+
331 ))
332 }
333 }
334
335 impl<'a, E, $($name),+> std::convert::TryFrom<Value<'a>> for ($($name),+,)
336 where
337 $($name: std::convert::TryFrom<Value<'a>, Error = E>,)+
338 crate::Error: From<E>,
339
340 {
341 type Error = crate::Error;
342
343 fn try_from(v: Value<'a>) -> core::result::Result<Self, Self::Error> {
344 Self::try_from(Structure::try_from(v)?)
345 }
346 }
347
348 impl<E, $($name),+> std::convert::TryFrom<OwnedValue> for ($($name),+,)
349 where
350 $($name: std::convert::TryFrom<Value<'static>, Error = E>,)+
351 crate::Error: From<E>,
352
353 {
354 type Error = crate::Error;
355
356 fn try_from(v: OwnedValue) -> core::result::Result<Self, Self::Error> {
357 Self::try_from(Value::from(v))
358 }
359 }
360 )+
361 }
362}
363
364tuple_impls! {
365 1 => (0 T0)
366 2 => (0 T0 1 T1)
367 3 => (0 T0 1 T1 2 T2)
368 4 => (0 T0 1 T1 2 T2 3 T3)
369 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
370 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
371 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
372 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
373 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
374 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
375 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
376 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
377 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
378 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
379 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
380 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
381}
382
383fn create_signature_from_fields(fields: &[Value<'_>]) -> Signature<'static> {
384 let mut signature: String = String::with_capacity(255);
385 signature.push(ch:'(');
386 for field: &Value<'_> in fields {
387 signature.push_str(&field.value_signature());
388 }
389 signature.push(ch:')');
390
391 Signature::from_string_unchecked(signature)
392}
393