zvariant/
tuple.rs

1use crate::{
2    signature_parser::SignatureParser, utils::*, DynamicDeserialize, DynamicType, Signature,
3};
4use serde::{
5    de::{Deserialize, DeserializeSeed, Deserializer, Error, Visitor},
6    Serialize, Serializer,
7};
8use std::marker::PhantomData;
9
10/// A helper type to serialize or deserialize a tuple whose elements implement [DynamicType] but
11/// not [Type].
12///
13/// This is required because tuples already have an implementation of [DynamicType] via the blanket
14/// implementation of [DynamicType] where `T: Type`, but that results in a bound of [Type] on each
15/// element, which is stronger than needed for serializing.
16///
17/// [Type]: trait.Type.html
18#[derive(Debug, Copy, Clone)]
19pub struct DynamicTuple<T>(pub T);
20
21impl DynamicType for DynamicTuple<()> {
22    fn dynamic_signature(&self) -> Signature<'_> {
23        Signature::from_static_str_unchecked("")
24    }
25}
26
27impl<T: Serialize> Serialize for DynamicTuple<T> {
28    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
29        self.0.serialize(serializer)
30    }
31}
32
33impl<'de> Deserialize<'de> for DynamicTuple<()> {
34    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
35        <()>::deserialize(deserializer).map(DynamicTuple)
36    }
37}
38
39/// A helper type for [DynamicTuple]'s [DynamicDeserialize] implementation.
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct TupleSeed<'a, T, S> {
42    sig: Signature<'a>,
43    seeds: S,
44    marker: PhantomData<T>,
45}
46
47impl<'a, T, S> DynamicType for TupleSeed<'a, T, S> {
48    fn dynamic_signature(&self) -> Signature<'_> {
49        self.sig.clone()
50    }
51}
52
53struct TupleVisitor<T, S> {
54    seeds: S,
55    marker: PhantomData<T>,
56}
57
58macro_rules! tuple_impls {
59    ($($len:expr => ($($n:tt $name:ident)+))+) => {
60        $(
61            impl<$($name),+> DynamicType for DynamicTuple<($($name,)+)>
62            where
63                $($name: DynamicType,)+
64            {
65                fn dynamic_signature(&self) -> Signature<'_> {
66                    let mut sig = String::with_capacity(255);
67                    sig.push(STRUCT_SIG_START_CHAR);
68                    $(
69                        sig.push_str(DynamicType::dynamic_signature(&self.0.$n).as_str());
70                    )+
71                    sig.push(STRUCT_SIG_END_CHAR);
72
73                    Signature::from_string_unchecked(sig)
74                }
75            }
76
77            impl<'de, $($name),+> DeserializeSeed<'de> for TupleSeed<'de, ($($name,)+), ($(<$name as DynamicDeserialize<'de>>::Deserializer,)+)>
78            where
79                $($name: DynamicDeserialize<'de>,)+
80            {
81                type Value = DynamicTuple<($($name,)+)>;
82
83                fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
84                    deserializer.deserialize_tuple($len, TupleVisitor { seeds: self.seeds, marker: self.marker })
85                }
86            }
87
88            impl<'de, $($name),+> Visitor<'de> for TupleVisitor<($($name,)+), ($(<$name as DynamicDeserialize<'de>>::Deserializer,)+)>
89            where
90                $($name: DynamicDeserialize<'de>,)+
91            {
92                type Value = DynamicTuple<($($name,)+)>;
93
94                fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95                    formatter.write_str("a tuple")
96                }
97
98                fn visit_seq<V>(self, mut visitor: V) -> Result<DynamicTuple<($($name,)+)>, V::Error>
99                where
100                    V: serde::de::SeqAccess<'de>,
101                {
102                    Ok(DynamicTuple(($({
103                        match visitor.next_element_seed(self.seeds.$n) {
104                            Ok(Some(elt)) => elt,
105                            Ok(None) => return Err(V::Error::invalid_length($len, &"")),
106                            Err(e) => return Err(e),
107                        }
108                    },)+)))
109                }
110            }
111
112            impl<'de, $($name),+> DynamicDeserialize<'de> for DynamicTuple<($($name,)+)>
113            where
114                $($name: DynamicDeserialize<'de>,)+
115            {
116                type Deserializer = TupleSeed<'de, ($($name,)+), ($(<$name as DynamicDeserialize<'de>>::Deserializer,)+)>;
117
118                fn deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer>
119                    where S: TryInto<Signature<'de>>, S::Error: Into<zvariant::Error>
120                {
121                    let sig = signature.try_into().map_err(Into::into)?;
122                    if !sig.starts_with(zvariant::STRUCT_SIG_START_CHAR) {
123                        return Err(zvariant::Error::IncorrectType);
124                    }
125                    if !sig.ends_with(zvariant::STRUCT_SIG_END_CHAR) {
126                        return Err(zvariant::Error::IncorrectType);
127                    }
128
129                    let end = sig.len() - 1;
130                    let mut sig_parser = SignatureParser::new(sig.slice(1..end));
131
132                    let seeds = ($({
133                        let elt_sig = sig_parser.parse_next_signature()?;
134                        $name::deserializer_for_signature(elt_sig)?
135                    },)+);
136
137                    Ok(TupleSeed { sig, seeds, marker: PhantomData })
138                }
139            }
140        )+
141    }
142}
143
144tuple_impls! {
145    1 => (0 T0)
146    2 => (0 T0 1 T1)
147    3 => (0 T0 1 T1 2 T2)
148    4 => (0 T0 1 T1 2 T2 3 T3)
149    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
150    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
151    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
152    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
153    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
154    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
155    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
156    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)
157    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)
158    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)
159    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)
160    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)
161}