zvariant/
structure.rs

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