gel_protogen/
macros.rs

1/// This macro is used to declare serialization traits for a type.
2#[macro_export]
3macro_rules! declare_type {
4    // Primitive types (no lifetime, fixed size)
5    ($ty:ident) =>
6    {
7        $crate::declare_type!($crate::prelude::DataType, $ty, flags=[primitive], {
8            fn to_usize(value: usize) -> $ty {
9                value as $ty
10            }
11            fn from_usize(value: $ty) -> usize {
12                value as usize
13            }
14        });
15
16        impl $crate::prelude::EncoderFor<$ty> for $ty {
17            fn encode_for(&self, buf: &mut $crate::BufWriter<'_>) {
18                buf.write(&self.to_be_bytes());
19            }
20        }
21
22        impl <'a> $crate::prelude::DecoderFor<'a, $ty> for $ty {
23            fn decode_for(buf: &mut &'a [u8]) -> Result<Self, $crate::prelude::ParseError> {
24                if let Some((chunk, next)) = buf.split_first_chunk::<{std::mem::size_of::<$ty>()}>() {
25                    let res = {
26                        let buf = *chunk;
27                        Ok($ty::from_be_bytes(buf))
28                    };
29                    *buf = next;
30                    res
31                } else {
32                    Err($crate::prelude::ParseError::TooShort)
33                }
34            }
35        }
36    };
37    ($datatype:path, $ty:ident , $( flags=[$($flag:ident),*], )?
38    {
39        $( fn to_usize($eusize:ident: usize) -> $eusize_self:ty $to_usize:block )?
40        $( fn from_usize($eusize2:ident: $eusize_self2:ty) -> usize $from_usize:block )?
41    }
42        ) => {
43        impl $datatype for $ty {
44            const META: $crate::prelude::StructFieldMeta = $crate::prelude::declare_meta!(
45                type = $ty,
46                constant_size = Some(std::mem::size_of::<$ty>()),
47                flags = [$($($flag),*)?]
48            );
49
50            $(
51                fn encode_usize<'__value_lifetime>(buf: &mut $crate::prelude::BufWriter<'_>, value: usize) {
52                    let $eusize = value;
53                    let value = $to_usize;
54                    $crate::prelude::EncoderFor::<$ty>::encode_for(&value, buf);
55                }
56                fn decode_usize(buf: &mut &[u8]) -> Result<usize, $crate::prelude::ParseError> {
57                    let $eusize2 = <$ty as $crate::prelude::DecoderFor<$ty>>::decode_for(buf)?;
58                    Ok($from_usize)
59                }
60            )?
61        }
62
63        impl $crate::prelude::DataTypeFixedSize for $ty {
64            const SIZE: usize = std::mem::size_of::<$ty>();
65        }
66
67    };
68
69    // Lifetime type, non-fixed size
70    ($datatype:path, $ty:ident<$lt:lifetime>, builder: $builder:ty, $( flags=[$($flag:ident),*], )?
71    {
72    }) => {
73        impl <$lt> $datatype
74            for $ty<$lt> {
75            const META: $crate::prelude::StructFieldMeta = $crate::prelude::declare_meta!(
76                type = $ty,
77                constant_size = None,
78                flags = [$($($flag),*)?]
79            );
80        }
81    };
82}
83
84#[macro_export]
85macro_rules! declare_meta {
86    (type = $ty:ident, constant_size = $constant_size:expr, flags = [$($flag:ident),*]) => {
87        $crate::paste!($crate::prelude::StructFieldMeta::new(stringify!($ty), $constant_size)
88            $(
89                .[< set_ $flag >]()
90            )*)
91
92    };
93}
94
95/// Generate encoders for array types from slices, arrays, and
96/// iterator-generating functions. Note that because we need to consume the
97/// iterator and we may need to iterate multiple times for measurement before
98/// serialization, we implement encoding for a function returning an iterator.
99///
100/// NOTE: For types that have a length generic, the length generic must appear
101/// second.
102#[macro_export]
103macro_rules! encoder_for_array {
104    (impl <$generic:ident $(, $length_generic:ident)?> for $ty:ty {
105        fn encode_for(&self, $buf:ident: &mut BufWriter<'_>, $it:ident: impl $iter:ident) $block:block
106    }) => {
107        /// Self encoder
108        impl<$generic : DataType, $($length_generic : DataType + 'static)?> EncoderFor<$ty> for $ty
109        where
110            $generic: EncoderFor<$generic>,
111            $generic: DecoderFor<'static, $generic>,
112        {
113            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
114                let $it = self.into_iter();
115                $block
116            }
117        }
118
119        /// Slice encoder
120        impl<$generic : DataType, $($length_generic : DataType + 'static, )? IT> EncoderFor<$ty>
121            for &'_ [IT]
122        where
123            IT: EncoderFor<$generic>,
124            $generic: DecoderFor<'static, $generic>,
125        {
126            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
127                let $it = self.into_iter();
128                $block
129            }
130        }
131
132        /// Array encoder
133        impl<$generic : DataType, $($length_generic : DataType + 'static, )? const N: usize, IT>
134            EncoderFor<$ty> for [IT; N]
135        where
136            IT: EncoderFor<$generic>,
137            $generic: DecoderFor<'static, $generic>,
138        {
139            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
140                let $it = self.into_iter();
141                $block
142            }
143        }
144
145        /// Array reference encoder
146        impl<$generic : DataType, $($length_generic : DataType + 'static, )? const N: usize, IT>
147            EncoderFor<$ty> for &'_ [IT; N]
148        where
149            IT: EncoderFor<$generic>,
150            $generic: DecoderFor<'static, $generic>,
151        {
152            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
153                let $it = self.into_iter();
154                $block
155            }
156        }
157
158        /// Function encoder: see the note about about non-restartable iterators.
159        impl<$generic : DataType, $($length_generic : DataType + 'static, )? F, I, II, IT> EncoderFor<$ty>
160            for F
161        where
162            F: Fn() -> I,
163            I: IntoIterator<Item = IT, IntoIter = II>,
164            IT: EncoderFor<$generic>,
165            II: $iter<Item = IT>,
166            $generic: DecoderFor<'static, $generic>,
167        {
168            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
169                let $it = self().into_iter();
170                $block
171            }
172        }
173
174        /// Direct Vec<T> encoder
175        impl<$generic : DataType, $($length_generic : DataType + 'static, )? IT> EncoderFor<$ty>
176            for Vec<IT>
177        where
178            IT: EncoderFor<$generic>,
179            $generic: DecoderFor<'static, $generic>,
180        {
181            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
182                let $it = self.iter();
183                $block
184            }
185        }
186
187        /// Direct &Vec<T> encoder
188        impl<$generic : DataType, $($length_generic : DataType + 'static, )? IT> EncoderFor<$ty>
189            for &'_ Vec<IT>
190        where
191            IT: EncoderFor<$generic>,
192            $generic: DecoderFor<'static, $generic>,
193        {
194            fn encode_for(&self, $buf: &mut $crate::BufWriter<'_>) {
195                let $it = self.iter();
196                $block
197            }
198        }
199    };
200}