polyvalue/
macros.rs

1/// A macro that generates birectional converters between a type and Value
2/// It will be a `TryFrom<Value> for Source` and `Into<Value> for Source` implementation
3/// and take in 3 parameters:
4/// - `source`: The type to convert from/to
5/// - `into`: A closure that takes in a `Source` and returns a `Value`
6/// - `from`: A closure that takes in a `Value` and returns a `Result<Source, Error>`
7macro_rules! map_value {
8    (from = $target:ty, handle_into = ($ival:ident) $into:block, handle_from = ($fval:ident) $from:block) => {
9        impl TryFrom<$crate::Value> for $target {
10            type Error = crate::Error;
11
12            fn try_from($fval: $crate::Value) -> Result<Self, Self::Error> $from
13        }
14
15        impl From<$target> for $crate::Value {
16            fn from($ival: $target) -> Self $into
17        }
18    };
19}
20
21///
22/// A macro that generates a subtype converter for a given type.
23/// It will be a `TryFrom<Target> for Source`` implementation
24/// and take in 4 parameters:
25/// - `target`: The type to convert to
26/// - `source`: The type to convert from
27/// - `handler`: A closure that takes in a `Source` and returns a `Result<Target, Error>`
28macro_rules! map_type {
29    (Int, $source:ty) => {
30        map_type!(U8, $source);
31        map_type!(U16, $source);
32        map_type!(U32, $source);
33        map_type!(U64, $source);
34
35        map_type!(I8, $source);
36        map_type!(I16, $source);
37        map_type!(I32, $source);
38        map_type!(I64, $source);
39    };
40
41    ($target:ty, $source:ty) => {
42        impl TryFrom<$target> for $source {
43            type Error = crate::Error;
44            fn try_from(value: $target) -> Result<Self, Self::Error> {
45                Ok(Self::try_from(Value::from(value))?)
46            }
47        }
48    };
49}
50
51///
52/// A macro that generates a primitive converter for a given type.
53/// It will be a `From<Primitive>/Into<Primitive> for Source` implementation
54/// and take in 4 parameters:
55/// - `primitive`: The primitive type to convert to/from
56/// - `source`: The type to convert from/to
57/// - `into`: A closure that takes in a `Source` and returns a `Primitive`
58/// - `from`: A closure that takes in a `Primitive` and returns a `Source`
59macro_rules! map_primitive {
60    (from = $source:ty, primitive = $primitive:ty) => {
61        #[allow(clippy::from_over_into)]
62        impl Into<$primitive> for $source {
63            fn into(self) -> $primitive {
64                self.0
65            }
66        }
67
68        impl From<$primitive> for $source {
69            fn from(value: $primitive) -> Self {
70                <$source>::new(value)
71            }
72        }
73
74        impl From<$primitive> for $crate::Value {
75            fn from(value: $primitive) -> Self {
76                <$source>::new(value).into()
77            }
78        }
79
80        #[allow(clippy::from_over_into)]
81        impl TryInto<$primitive> for $crate::Value {
82            type Error = crate::Error;
83            fn try_into(self) -> Result<$primitive, Self::Error> {
84                let value: $source = self.try_into()?;
85                Ok(value.into())
86            }
87        }
88    };
89}
90
91/// A macro that generates an implementation of ValueTrait for a given type.
92/// Will also generate a Display and Debug implementation for the type.
93/// Those implementations will use the `TryInto<Str>` implementation.
94macro_rules! impl_value {
95    ($own_type:ty, $inner_type:ty, $to_string:expr, $debug:expr) => {
96        impl $crate::ValueTrait for $own_type {
97            type Inner = $inner_type;
98
99            fn new(inner: $inner_type) -> Self {
100                Self(inner)
101            }
102
103            fn inner(&self) -> &$inner_type {
104                &self.0
105            }
106
107            fn inner_mut(&mut self) -> &mut $inner_type {
108                &mut self.0
109            }
110
111            fn into_inner(self) -> $inner_type {
112                self.0
113            }
114        }
115
116        map_primitive!(from = $own_type, primitive = $inner_type);
117
118        impl std::fmt::Display for $own_type {
119            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120                write!(f, "{}", $to_string(self))
121            }
122        }
123
124        impl std::fmt::Debug for $own_type {
125            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126                $debug(self, f)
127            }
128        }
129    };
130    ($own_type:ty, $inner_type:ty, $to_string:expr) => {
131        impl_value!(
132            $own_type,
133            $inner_type,
134            $to_string,
135            |this: &Self, f: &mut std::fmt::Formatter<'_>| { write!(f, "{}", $to_string(this)) }
136        );
137    };
138}
139
140macro_rules! overload_operator {
141    ($type:ident, arithmetic) => {
142        overload_operator!($type, add);
143        overload_operator!($type, sub);
144        overload_operator!($type, mul);
145        overload_operator!($type, div);
146        overload_operator!($type, rem);
147        overload_operator!($type, neg);
148    };
149
150    ($type:ident, add) => {
151        impl std::ops::Add for $type {
152            type Output = Result<Self, crate::Error>;
153            fn add(self, rhs: Self) -> Self::Output {
154                Self::arithmetic_op(self, rhs, ArithmeticOperation::Add)
155            }
156        }
157    };
158
159    ($type:ident, sub) => {
160        impl std::ops::Sub for $type {
161            type Output = Result<Self, crate::Error>;
162            fn sub(self, rhs: Self) -> Self::Output {
163                Self::arithmetic_op(self, rhs, ArithmeticOperation::Subtract)
164            }
165        }
166    };
167
168    ($type:ident, mul) => {
169        impl std::ops::Mul for $type {
170            type Output = Result<Self, crate::Error>;
171            fn mul(self, rhs: Self) -> Self::Output {
172                Self::arithmetic_op(self, rhs, ArithmeticOperation::Multiply)
173            }
174        }
175    };
176
177    ($type:ident, div) => {
178        impl std::ops::Div for $type {
179            type Output = Result<Self, crate::Error>;
180            fn div(self, rhs: Self) -> Self::Output {
181                Self::arithmetic_op(self, rhs, ArithmeticOperation::Divide)
182            }
183        }
184    };
185
186    ($type:ident, rem) => {
187        impl std::ops::Rem for $type {
188            type Output = Result<Self, crate::Error>;
189            fn rem(self, rhs: Self) -> Self::Output {
190                Self::arithmetic_op(self, rhs, ArithmeticOperation::Modulo)
191            }
192        }
193    };
194
195    ($type:ident, neg) => {
196        impl std::ops::Neg for $type {
197            type Output = Result<Self, crate::Error>;
198            fn neg(self) -> Self::Output {
199                Self::arithmetic_neg(self)
200            }
201        }
202    };
203
204    // //////////////////////////////////////////////////////////////////////////////////
205    ($type:ident, bitwise) => {
206        overload_operator!($type, bitand);
207        overload_operator!($type, bitor);
208        overload_operator!($type, bitxor);
209        overload_operator!($type, shl);
210        overload_operator!($type, shr);
211    };
212
213    ($type:ident, bitand) => {
214        impl std::ops::BitAnd for $type {
215            type Output = Result<Self, crate::Error>;
216            fn bitand(self, rhs: Self) -> Self::Output {
217                Self::bitwise_op(self, rhs, BitwiseOperation::And)
218            }
219        }
220    };
221
222    ($type:ident, bitor) => {
223        impl std::ops::BitOr for $type {
224            type Output = Result<Self, crate::Error>;
225            fn bitor(self, rhs: Self) -> Self::Output {
226                Self::bitwise_op(self, rhs, BitwiseOperation::Or)
227            }
228        }
229    };
230
231    ($type:ident, bitxor) => {
232        impl std::ops::BitXor for $type {
233            type Output = Result<Self, crate::Error>;
234            fn bitxor(self, rhs: Self) -> Self::Output {
235                Self::bitwise_op(self, rhs, BitwiseOperation::Xor)
236            }
237        }
238    };
239
240    ($type:ident, shl) => {
241        impl std::ops::Shl for $type {
242            type Output = Result<Self, crate::Error>;
243            fn shl(self, rhs: Self) -> Self::Output {
244                Self::bitwise_op(self, rhs, BitwiseOperation::LeftShift)
245            }
246        }
247    };
248
249    ($type:ident, shr) => {
250        impl std::ops::Shr for $type {
251            type Output = Result<Self, crate::Error>;
252            fn shr(self, rhs: Self) -> Self::Output {
253                Self::bitwise_op(self, rhs, BitwiseOperation::RightShift)
254            }
255        }
256    };
257
258    // ///////////////////////////////////////////////////////////////////////////
259    ($type:ident, bool_not) => {
260        impl std::ops::Not for $type {
261            type Output = Result<Value, crate::Error>;
262            fn not(self) -> Self::Output {
263                Self::boolean_not(self)
264            }
265        }
266    };
267
268    // ///////////////////////////////////////////////////////////////////////////
269    ($type:ident, deref) => {
270        impl std::ops::Deref for $type {
271            type Target = <$type as ValueTrait>::Inner;
272            fn deref(&self) -> &Self::Target {
273                self.inner()
274            }
275        }
276
277        impl std::ops::DerefMut for $type {
278            fn deref_mut(&mut self) -> &mut Self::Target {
279                self.inner_mut()
280            }
281        }
282    };
283}