zvariant/
tuple.rs

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