protobuf_codec/
oneof.rs

1#![allow(clippy::single_match, clippy::block_in_if_condition_stmt)]
2use crate::field::{FieldDecode, FieldEncode, RequiredFieldDecode, RequiredFieldEncode};
3use crate::wire::Tag;
4use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode};
5
6/// Value of `Oneof` that has 2-fields.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
8#[allow(missing_docs)]
9pub enum Branch2<A, B> {
10    A(A),
11    B(B),
12}
13
14/// Value of `Oneof` that has 3-fields.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
16#[allow(missing_docs)]
17pub enum Branch3<A, B, C> {
18    A(A),
19    B(B),
20    C(C),
21}
22
23/// Value of `Oneof` that has 4-fields.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
25#[allow(missing_docs)]
26pub enum Branch4<A, B, C, D> {
27    A(A),
28    B(B),
29    C(C),
30    D(D),
31}
32
33/// Value of `Oneof` that has 5-fields.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
35#[allow(missing_docs)]
36pub enum Branch5<A, B, C, D, E> {
37    A(A),
38    B(B),
39    C(C),
40    D(D),
41    E(E),
42}
43
44/// Value of `Oneof` that has 6-fields.
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
46#[allow(missing_docs)]
47pub enum Branch6<A, B, C, D, E, F> {
48    A(A),
49    B(B),
50    C(C),
51    D(D),
52    E(E),
53    F(F),
54}
55
56/// Value of `Oneof` that has 7-fields.
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
58#[allow(missing_docs)]
59pub enum Branch7<A, B, C, D, E, F, G> {
60    A(A),
61    B(B),
62    C(C),
63    D(D),
64    E(E),
65    F(F),
66    G(G),
67}
68
69/// Value of `Oneof` that has 8-fields.
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
71#[allow(missing_docs)]
72pub enum Branch8<A, B, C, D, E, F, G, H> {
73    A(A),
74    B(B),
75    C(C),
76    D(D),
77    E(E),
78    F(F),
79    G(G),
80    H(H),
81}
82
83/// Decoder and encoder for `Oneof` fields.
84#[derive(Debug, Default)]
85pub struct Oneof<F> {
86    fields: F,
87    index: usize,
88}
89impl<F> Oneof<F> {
90    /// Makes a new `Oneof` instance.
91    pub fn new(fields: F) -> Self {
92        Oneof { fields, index: 0 }
93    }
94}
95
96macro_rules! impl_field_decode {
97    ($oneof:ident, [$($f:ident),*], [$($i:tt),*]) => {
98        impl<$($f),*> Decode for Oneof<($($f),*,)>
99        where
100            $($f: RequiredFieldDecode),*
101        {
102            type Item = $oneof<$($f::Item),*>;
103
104            fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
105                if self.index == 0 {
106                    return Ok(0)
107                }
108                match self.index - 1 {
109                    $($i => track!(self.fields.$i.decode(buf, eos))),*,
110                    _ => unreachable!()
111                }
112            }
113
114            fn finish_decoding(&mut self) -> Result<Self::Item> {
115                let i = self.index;
116                self.index = 0;
117                track_assert_ne!(i, 0, ErrorKind::InvalidInput, "No `Oneof` field");
118                match i - 1 {
119                    $($i => track!(self.fields.$i.finish_decoding()).map($oneof::$f)),*,
120                    _ => unreachable!()
121                }
122            }
123
124            fn is_idle(&self) -> bool {
125                if self.index == 0 {
126                    return false;
127                }
128                match self.index - 1 {
129                    $($i => self.fields.$i.is_idle()),*,
130                    _ => unreachable!(),
131                }
132            }
133
134            fn requiring_bytes(&self) -> ByteCount {
135                if self.index == 0 {
136                    return ByteCount::Unknown;
137                }
138                match self.index - 1 {
139                    $($i => self.fields.$i.requiring_bytes()),*,
140                    _ => unreachable!()
141                }
142            }
143        }
144        impl<$($f),*> FieldDecode for Oneof<($($f),*,)>
145        where
146            $($f: RequiredFieldDecode),*
147        {
148            fn start_decoding(&mut self, tag: Tag) -> Result<bool> {
149                if self.index != 0 {
150                    match self.index - 1 {
151                        $($i => track!(self.fields.$i.finish_decoding()).map(|_| ())?),*,
152                        _ => {},
153                    }
154                    self.index = 0;
155                }
156
157                $(if track!(self.fields.$i.start_decoding(tag); tag)? {
158                    self.index = $i + 1;
159                    return Ok(true);
160                })*
161                Ok(false)
162            }
163        }
164        impl<$($f),*> RequiredFieldDecode for Oneof<($($f),*,)>
165        where
166            $($f: RequiredFieldDecode),*
167        {
168            fn is_present(&self) -> bool {
169                self.index != 0
170            }
171        }
172    }
173}
174
175macro_rules! impl_field_encode {
176    ($oneof:ident,[$($f:ident),*],[$($i:tt),*]) => {
177        impl<$($f),*> Encode for Oneof<($($f),*,)>
178        where
179            $($f: RequiredFieldEncode),*
180        {
181            type Item = $oneof<$($f::Item),*>;
182
183            fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
184                if self.index == 0 {
185                    return Ok(0);
186                }
187                match self.index - 1 {
188                    $($i => track!(self.fields.$i.encode(buf, eos))),*,
189                    _ => unreachable!()
190                }
191            }
192
193            fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
194                track_assert!(self.is_idle(), ErrorKind::EncoderFull);
195                match item {
196                    $($oneof::$f(v) => {
197                        self.index = $i + 1;
198                        track!(self.fields.$i.start_encoding(v))
199                    }),*
200                }
201            }
202
203            fn is_idle(&self) -> bool {
204                if self.index == 0 {
205                    return true;
206                }
207                match self.index - 1 {
208                    $($i => self.fields.$i.is_idle()),*,
209                    _ => unreachable!()
210                }
211            }
212
213            fn requiring_bytes(&self) -> ByteCount {
214                if self.index == 0 {
215                    return ByteCount::Finite(0);
216                }
217                match self.index - 1 {
218                    $($i => self.fields.$i.requiring_bytes()),*,
219                    _ => unreachable!()
220                }
221            }
222        }
223        impl<$($f),*> FieldEncode for Oneof<($($f),*,)>
224        where
225            $($f: RequiredFieldEncode),*
226        {
227        }
228        impl<$($f),*> RequiredFieldEncode for Oneof<($($f),*,)>
229        where
230            $($f: RequiredFieldEncode),*
231        {
232        }
233        impl<$($f),*> SizedEncode for Oneof<($($f),*,)>
234        where
235            $($f: RequiredFieldEncode + SizedEncode),*
236        {
237            fn exact_requiring_bytes(&self) -> u64 {
238                if self.index == 0 {
239                    return 0;
240                }
241                match self.index - 1 {
242                    $($i => self.fields.$i.exact_requiring_bytes()),*,
243                    _ => unreachable!(),
244                }
245            }
246        }
247    };
248}
249
250impl_field_decode!(Branch2, [A, B], [0, 1]);
251impl_field_decode!(Branch3, [A, B, C], [0, 1, 2]);
252impl_field_decode!(Branch4, [A, B, C, D], [0, 1, 2, 3]);
253impl_field_decode!(Branch5, [A, B, C, D, E], [0, 1, 2, 3, 4]);
254impl_field_decode!(Branch6, [A, B, C, D, E, F], [0, 1, 2, 3, 4, 5]);
255impl_field_decode!(Branch7, [A, B, C, D, E, F, G], [0, 1, 2, 3, 4, 5, 6]);
256impl_field_decode!(Branch8, [A, B, C, D, E, F, G, H], [0, 1, 2, 3, 4, 5, 6, 7]);
257
258impl_field_encode!(Branch2, [A, B], [0, 1]);
259impl_field_encode!(Branch3, [A, B, C], [0, 1, 2]);
260impl_field_encode!(Branch4, [A, B, C, D], [0, 1, 2, 3]);
261impl_field_encode!(Branch5, [A, B, C, D, E], [0, 1, 2, 3, 4]);
262impl_field_encode!(Branch6, [A, B, C, D, E, F], [0, 1, 2, 3, 4, 5]);
263impl_field_encode!(Branch7, [A, B, C, D, E, F, G], [0, 1, 2, 3, 4, 5, 6]);
264impl_field_encode!(Branch8, [A, B, C, D, E, F, G, H], [0, 1, 2, 3, 4, 5, 6, 7]);