fidl_next_codec/
primitives.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#[cfg(not(target_endian = "little"))]
6compile_error!("only little-endian targets are supported by FIDL");
7
8macro_rules! impl_unop {
9    ($trait:ident:: $fn:ident for $name:ident : $prim:ty) => {
10        impl ::core::ops::$trait for $name {
11            type Output = <$prim as ::core::ops::$trait>::Output;
12
13            #[inline]
14            fn $fn(self) -> Self::Output {
15                self.0.$fn()
16            }
17        }
18    };
19}
20
21macro_rules! impl_binop_one {
22    ($trait:ident:: $fn:ident($self:ty, $other:ty) -> $output:ty) => {
23        impl ::core::ops::$trait<$other> for $self {
24            type Output = $output;
25
26            #[inline]
27            fn $fn(self, other: $other) -> Self::Output {
28                self.0.$fn(other.0)
29            }
30        }
31    };
32}
33
34macro_rules! impl_binop_both {
35    ($trait:ident:: $fn:ident($self:ty, $other:ty) -> $output:ty) => {
36        impl ::core::ops::$trait<$other> for $self {
37            type Output = $output;
38
39            #[inline]
40            fn $fn(self, other: $other) -> Self::Output {
41                self.0.$fn(other)
42            }
43        }
44
45        impl ::core::ops::$trait<$self> for $other {
46            type Output = $output;
47
48            #[inline]
49            fn $fn(self, other: $self) -> Self::Output {
50                self.$fn(other.0)
51            }
52        }
53    };
54}
55
56macro_rules! impl_binop {
57    ($trait:ident::$fn:ident for $name:ident: $prim:ty) => {
58        impl_binop_both!($trait::$fn ($name, $prim) -> $prim);
59        impl_binop_both!($trait::$fn (&'_ $name, $prim) -> $prim);
60        impl_binop_both!($trait::$fn ($name, &'_ $prim) -> $prim);
61        impl_binop_both!($trait::$fn (&'_ $name, &'_ $prim) -> $prim);
62
63        impl_binop_one!($trait::$fn ($name, $name) -> $prim);
64        impl_binop_one!($trait::$fn (&'_ $name, $name) -> $prim);
65        impl_binop_one!($trait::$fn ($name, &'_ $name) -> $prim);
66        impl_binop_one!($trait::$fn (&'_ $name, &'_ $name) -> $prim);
67    };
68}
69
70macro_rules! impl_binassign {
71    ($trait:ident:: $fn:ident for $name:ident : $prim:ty) => {
72        impl ::core::ops::$trait<$prim> for $name {
73            #[inline]
74            fn $fn(&mut self, other: $prim) {
75                let mut value = self.0;
76                value.$fn(other);
77                *self = Self(value);
78            }
79        }
80
81        impl ::core::ops::$trait<$name> for $name {
82            #[inline]
83            fn $fn(&mut self, other: $name) {
84                let mut value = self.0;
85                value.$fn(other.0);
86                *self = Self(value);
87            }
88        }
89
90        impl ::core::ops::$trait<&'_ $prim> for $name {
91            #[inline]
92            fn $fn(&mut self, other: &'_ $prim) {
93                let mut value = self.0;
94                value.$fn(other);
95                *self = Self(value);
96            }
97        }
98
99        impl ::core::ops::$trait<&'_ $name> for $name {
100            #[inline]
101            fn $fn(&mut self, other: &'_ $name) {
102                let mut value = self.0;
103                value.$fn(other.0);
104                *self = Self(value);
105            }
106        }
107    };
108}
109
110macro_rules! impl_clone_and_copy {
111    (for $name:ident) => {
112        impl Clone for $name {
113            #[inline]
114            fn clone(&self) -> Self {
115                *self
116            }
117        }
118
119        impl Copy for $name {}
120    };
121}
122
123macro_rules! impl_fmt {
124    ($trait:ident for $name:ident) => {
125        impl ::core::fmt::$trait for $name {
126            #[inline]
127            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
128                ::core::fmt::$trait::fmt(&self.0, f)
129            }
130        }
131    };
132}
133
134macro_rules! impl_default {
135    (for $name:ident : $prim:ty) => {
136        impl Default for $name {
137            #[inline]
138            fn default() -> Self {
139                Self(<$prim>::default())
140            }
141        }
142    };
143}
144
145macro_rules! impl_from {
146    (for $name:ident : $prim:ty) => {
147        impl From<$prim> for $name {
148            fn from(value: $prim) -> Self {
149                Self(value)
150            }
151        }
152
153        impl<'a> From<&'a $prim> for $name {
154            fn from(value: &'a $prim) -> Self {
155                Self(*value)
156            }
157        }
158
159        impl From<$name> for $prim {
160            fn from(value: $name) -> Self {
161                value.0
162            }
163        }
164
165        impl<'a> From<&'a $name> for $prim {
166            fn from(value: &'a $name) -> Self {
167                value.0
168            }
169        }
170    };
171}
172
173macro_rules! impl_try_from_ptr_size {
174    ($size:ident for $name:ident: $prim:ident) => {
175        impl TryFrom<$size> for $name {
176            type Error = <$prim as TryFrom<$size>>::Error;
177
178            #[inline]
179            fn try_from(value: $size) -> Result<Self, Self::Error> {
180                Ok(Self(<$prim>::try_from(value)?))
181            }
182        }
183
184        impl_try_into_ptr_size!($size for $name: $prim);
185    };
186}
187
188macro_rules! impl_try_into_ptr_size {
189    (isize for $name:ident: i16) => {
190        impl_into_ptr_size!(isize for $name);
191    };
192
193    (usize for $name:ident: u16) => {
194        impl_into_ptr_size!(usize for $name);
195    };
196
197    ($size:ident for $name:ident: $prim:ident) => {
198        impl TryFrom<$name> for $size {
199            type Error = <$size as TryFrom<$prim>>::Error;
200
201            #[inline]
202            fn try_from(value: $name) -> Result<Self, Self::Error> {
203                <$size>::try_from(value.0)
204            }
205        }
206    };
207}
208
209macro_rules! impl_into_ptr_size {
210    ($size:ident for $name:ident) => {
211        impl From<$name> for $size {
212            #[inline]
213            fn from(value: $name) -> Self {
214                <$size>::from(value.0)
215            }
216        }
217    };
218}
219
220macro_rules! impl_hash {
221    (for $name:ident) => {
222        impl core::hash::Hash for $name {
223            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
224                self.0.hash(state);
225            }
226        }
227    };
228}
229
230macro_rules! impl_partial_ord_and_ord {
231    (for $name:ident : $prim:ty) => {
232        impl PartialOrd for $name {
233            #[inline]
234            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
235                Some(self.cmp(other))
236            }
237        }
238
239        impl PartialOrd<$prim> for $name {
240            #[inline]
241            fn partial_cmp(&self, other: &$prim) -> Option<::core::cmp::Ordering> {
242                self.0.partial_cmp(other)
243            }
244        }
245
246        impl Ord for $name {
247            #[inline]
248            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
249                self.0.cmp(&other.0)
250            }
251        }
252    };
253}
254
255macro_rules! impl_partial_eq_and_eq {
256    (for $name:ident : $prim:ty) => {
257        impl PartialEq for $name {
258            #[inline]
259            fn eq(&self, other: &Self) -> bool {
260                let lhs = self.0;
261                let rhs = other.0;
262                lhs.eq(&rhs)
263            }
264        }
265
266        impl PartialEq<$prim> for $name {
267            #[inline]
268            fn eq(&self, other: &$prim) -> bool {
269                self.0.eq(other)
270            }
271        }
272
273        impl Eq for $name {}
274    };
275}
276
277macro_rules! impl_partial_ord {
278    (for $name:ident : $prim:ty) => {
279        impl PartialOrd for $name {
280            #[inline]
281            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
282                self.0.partial_cmp(&other.0)
283            }
284        }
285
286        impl PartialOrd<$prim> for $name {
287            #[inline]
288            fn partial_cmp(&self, other: &$prim) -> Option<::core::cmp::Ordering> {
289                self.0.partial_cmp(other)
290            }
291        }
292    };
293}
294
295macro_rules! impl_product_and_sum {
296    (for $name:ident) => {
297        impl ::core::iter::Product for $name {
298            #[inline]
299            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
300                Self(iter.map(|x| x.0).product())
301            }
302        }
303
304        impl ::core::iter::Sum for $name {
305            #[inline]
306            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
307                Self(iter.map(|x| x.0).sum())
308            }
309        }
310    };
311}
312
313macro_rules! impl_signed_integer_traits {
314    ($name:ident: $prim:ident) => {
315        impl_binop!(Add::add for $name: $prim);
316        impl_binassign!(AddAssign::add_assign for $name: $prim);
317        impl_clone_and_copy!(for $name);
318        impl_fmt!(Binary for $name);
319        impl_binop!(BitAnd::bitand for $name: $prim);
320        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
321        impl_binop!(BitOr::bitor for $name: $prim);
322        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
323        impl_binop!(BitXor::bitxor for $name: $prim);
324        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
325        impl_fmt!(Debug for $name);
326        impl_default!(for $name: $prim);
327        impl_fmt!(Display for $name);
328        impl_binop!(Div::div for $name: $prim);
329        impl_binassign!(DivAssign::div_assign for $name: $prim);
330        impl_from!(for $name: $prim);
331        impl_try_from_ptr_size!(isize for $name: $prim);
332        impl_hash!(for $name);
333        impl_fmt!(LowerExp for $name);
334        impl_fmt!(LowerHex for $name);
335        impl_binop!(Mul::mul for $name: $prim);
336        impl_binassign!(MulAssign::mul_assign for $name: $prim);
337        impl_unop!(Neg::neg for $name: $prim);
338        impl_unop!(Not::not for $name: $prim);
339        impl_fmt!(Octal for $name);
340        impl_partial_eq_and_eq!(for $name: $prim);
341        impl_partial_ord_and_ord!(for $name: $prim);
342        impl_product_and_sum!(for $name);
343        impl_binop!(Rem::rem for $name: $prim);
344        impl_binassign!(RemAssign::rem_assign for $name: $prim);
345        impl_binop!(Shl::shl for $name: $prim);
346        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
347        impl_binop!(Shr::shr for $name: $prim);
348        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
349        impl_binop!(Sub::sub for $name: $prim);
350        impl_binassign!(SubAssign::sub_assign for $name: $prim);
351        impl_fmt!(UpperExp for $name);
352        impl_fmt!(UpperHex for $name);
353    };
354}
355
356macro_rules! impl_unsigned_integer_traits {
357    ($name:ident: $prim:ident) => {
358        impl_binop!(Add::add for $name: $prim);
359        impl_binassign!(AddAssign::add_assign for $name: $prim);
360        impl_clone_and_copy!(for $name);
361        impl_fmt!(Binary for $name);
362        impl_binop!(BitAnd::bitand for $name: $prim);
363        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
364        impl_binop!(BitOr::bitor for $name: $prim);
365        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
366        impl_binop!(BitXor::bitxor for $name: $prim);
367        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
368        impl_fmt!(Debug for $name);
369        impl_default!(for $name: $prim);
370        impl_fmt!(Display for $name);
371        impl_binop!(Div::div for $name: $prim);
372        impl_binassign!(DivAssign::div_assign for $name: $prim);
373        impl_from!(for $name: $prim);
374        impl_try_from_ptr_size!(usize for $name: $prim);
375        impl_hash!(for $name);
376        impl_fmt!(LowerExp for $name);
377        impl_fmt!(LowerHex for $name);
378        impl_binop!(Mul::mul for $name: $prim);
379        impl_binassign!(MulAssign::mul_assign for $name: $prim);
380        impl_unop!(Not::not for $name: $prim);
381        impl_fmt!(Octal for $name);
382        impl_partial_eq_and_eq!(for $name: $prim);
383        impl_partial_ord_and_ord!(for $name: $prim);
384        impl_product_and_sum!(for $name);
385        impl_binop!(Rem::rem for $name: $prim);
386        impl_binassign!(RemAssign::rem_assign for $name: $prim);
387        impl_binop!(Shl::shl for $name: $prim);
388        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
389        impl_binop!(Shr::shr for $name: $prim);
390        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
391        impl_binop!(Sub::sub for $name: $prim);
392        impl_binassign!(SubAssign::sub_assign for $name: $prim);
393        impl_fmt!(UpperExp for $name);
394        impl_fmt!(UpperHex for $name);
395    };
396}
397
398macro_rules! impl_float_traits {
399    ($name:ident: $prim:ty) => {
400        impl_binop!(Add::add for $name: $prim);
401        impl_binassign!(AddAssign::add_assign for $name: $prim);
402        impl_clone_and_copy!(for $name);
403        impl_fmt!(Debug for $name);
404        impl_default!(for $name: $prim);
405        impl_fmt!(Display for $name);
406        impl_binop!(Div::div for $name: $prim);
407        impl_binassign!(DivAssign::div_assign for $name: $prim);
408        impl_from!(for $name: $prim);
409        impl_fmt!(LowerExp for $name);
410        impl_binop!(Mul::mul for $name: $prim);
411        impl_binassign!(MulAssign::mul_assign for $name: $prim);
412        impl_unop!(Neg::neg for $name: $prim);
413        impl_partial_eq_and_eq!(for $name: $prim);
414        impl_partial_ord!(for $name: $prim);
415        impl_product_and_sum!(for $name);
416        impl_binop!(Rem::rem for $name: $prim);
417        impl_binassign!(RemAssign::rem_assign for $name: $prim);
418        impl_binop!(Sub::sub for $name: $prim);
419        impl_binassign!(SubAssign::sub_assign for $name: $prim);
420        impl_fmt!(UpperExp for $name);
421    };
422}
423
424macro_rules! define_newtype {
425    ($name:ident: $prim:ty, $align:expr) => {
426        #[doc = concat!("A wire-encoded `", stringify!($prim), "`")]
427        #[repr(C, align($align))]
428        #[derive(zerocopy::FromBytes, zerocopy::IntoBytes)]
429        pub struct $name(pub $prim);
430
431        impl ::core::ops::Deref for $name {
432            type Target = $prim;
433
434            fn deref(&self) -> &Self::Target {
435                &self.0
436            }
437        }
438
439        impl ::core::ops::DerefMut for $name {
440            fn deref_mut(&mut self) -> &mut Self::Target {
441                &mut self.0
442            }
443        }
444    };
445}
446
447macro_rules! define_signed_integer {
448    ($name:ident: $prim:ident, $align:expr) => {
449        define_newtype!($name: $prim, $align);
450        impl_signed_integer_traits!($name: $prim);
451    }
452}
453
454define_signed_integer!(WireI16: i16, 2);
455define_signed_integer!(WireI32: i32, 4);
456define_signed_integer!(WireI64: i64, 8);
457
458macro_rules! define_unsigned_integer {
459    ($name:ident: $prim:ident, $align:expr) => {
460        define_newtype!($name: $prim, $align);
461        impl_unsigned_integer_traits!($name: $prim);
462    }
463}
464
465define_unsigned_integer!(WireU16: u16, 2);
466define_unsigned_integer!(WireU32: u32, 4);
467define_unsigned_integer!(WireU64: u64, 8);
468
469macro_rules! define_float {
470    ($name:ident: $prim:ident, $align:expr) => {
471        define_newtype!($name: $prim, $align);
472        impl_float_traits!($name: $prim);
473    }
474}
475
476define_float!(WireF32: f32, 4);
477define_float!(WireF64: f64, 8);