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 PartialEq<$name> for $prim {
274            #[inline]
275            fn eq(&self, other: &$name) -> bool {
276                self.eq(&other.0)
277            }
278        }
279
280        impl Eq for $name {}
281    };
282}
283
284macro_rules! impl_partial_ord {
285    (for $name:ident : $prim:ty) => {
286        impl PartialOrd for $name {
287            #[inline]
288            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
289                self.0.partial_cmp(&other.0)
290            }
291        }
292
293        impl PartialOrd<$prim> for $name {
294            #[inline]
295            fn partial_cmp(&self, other: &$prim) -> Option<::core::cmp::Ordering> {
296                self.0.partial_cmp(other)
297            }
298        }
299    };
300}
301
302macro_rules! impl_product_and_sum {
303    (for $name:ident) => {
304        impl ::core::iter::Product for $name {
305            #[inline]
306            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
307                Self(iter.map(|x| x.0).product())
308            }
309        }
310
311        impl ::core::iter::Sum for $name {
312            #[inline]
313            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
314                Self(iter.map(|x| x.0).sum())
315            }
316        }
317    };
318}
319
320macro_rules! impl_signed_integer_traits {
321    ($name:ident: $prim:ident) => {
322        impl_binop!(Add::add for $name: $prim);
323        impl_binassign!(AddAssign::add_assign for $name: $prim);
324        impl_clone_and_copy!(for $name);
325        impl_fmt!(Binary for $name);
326        impl_binop!(BitAnd::bitand for $name: $prim);
327        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
328        impl_binop!(BitOr::bitor for $name: $prim);
329        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
330        impl_binop!(BitXor::bitxor for $name: $prim);
331        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
332        impl_fmt!(Debug for $name);
333        impl_default!(for $name: $prim);
334        impl_fmt!(Display for $name);
335        impl_binop!(Div::div for $name: $prim);
336        impl_binassign!(DivAssign::div_assign for $name: $prim);
337        impl_from!(for $name: $prim);
338        impl_try_from_ptr_size!(isize for $name: $prim);
339        impl_hash!(for $name);
340        impl_fmt!(LowerExp for $name);
341        impl_fmt!(LowerHex for $name);
342        impl_binop!(Mul::mul for $name: $prim);
343        impl_binassign!(MulAssign::mul_assign for $name: $prim);
344        impl_unop!(Neg::neg for $name: $prim);
345        impl_unop!(Not::not for $name: $prim);
346        impl_fmt!(Octal for $name);
347        impl_partial_eq_and_eq!(for $name: $prim);
348        impl_partial_ord_and_ord!(for $name: $prim);
349        impl_product_and_sum!(for $name);
350        impl_binop!(Rem::rem for $name: $prim);
351        impl_binassign!(RemAssign::rem_assign for $name: $prim);
352        impl_binop!(Shl::shl for $name: $prim);
353        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
354        impl_binop!(Shr::shr for $name: $prim);
355        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
356        impl_binop!(Sub::sub for $name: $prim);
357        impl_binassign!(SubAssign::sub_assign for $name: $prim);
358        impl_fmt!(UpperExp for $name);
359        impl_fmt!(UpperHex for $name);
360    };
361}
362
363macro_rules! impl_unsigned_integer_traits {
364    ($name:ident: $prim:ident) => {
365        impl_binop!(Add::add for $name: $prim);
366        impl_binassign!(AddAssign::add_assign for $name: $prim);
367        impl_clone_and_copy!(for $name);
368        impl_fmt!(Binary for $name);
369        impl_binop!(BitAnd::bitand for $name: $prim);
370        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
371        impl_binop!(BitOr::bitor for $name: $prim);
372        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
373        impl_binop!(BitXor::bitxor for $name: $prim);
374        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
375        impl_fmt!(Debug for $name);
376        impl_default!(for $name: $prim);
377        impl_fmt!(Display for $name);
378        impl_binop!(Div::div for $name: $prim);
379        impl_binassign!(DivAssign::div_assign for $name: $prim);
380        impl_from!(for $name: $prim);
381        impl_try_from_ptr_size!(usize for $name: $prim);
382        impl_hash!(for $name);
383        impl_fmt!(LowerExp for $name);
384        impl_fmt!(LowerHex for $name);
385        impl_binop!(Mul::mul for $name: $prim);
386        impl_binassign!(MulAssign::mul_assign for $name: $prim);
387        impl_unop!(Not::not for $name: $prim);
388        impl_fmt!(Octal for $name);
389        impl_partial_eq_and_eq!(for $name: $prim);
390        impl_partial_ord_and_ord!(for $name: $prim);
391        impl_product_and_sum!(for $name);
392        impl_binop!(Rem::rem for $name: $prim);
393        impl_binassign!(RemAssign::rem_assign for $name: $prim);
394        impl_binop!(Shl::shl for $name: $prim);
395        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
396        impl_binop!(Shr::shr for $name: $prim);
397        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
398        impl_binop!(Sub::sub for $name: $prim);
399        impl_binassign!(SubAssign::sub_assign for $name: $prim);
400        impl_fmt!(UpperExp for $name);
401        impl_fmt!(UpperHex for $name);
402    };
403}
404
405macro_rules! impl_float_traits {
406    ($name:ident: $prim:ty) => {
407        impl_binop!(Add::add for $name: $prim);
408        impl_binassign!(AddAssign::add_assign for $name: $prim);
409        impl_clone_and_copy!(for $name);
410        impl_fmt!(Debug for $name);
411        impl_default!(for $name: $prim);
412        impl_fmt!(Display for $name);
413        impl_binop!(Div::div for $name: $prim);
414        impl_binassign!(DivAssign::div_assign for $name: $prim);
415        impl_from!(for $name: $prim);
416        impl_fmt!(LowerExp for $name);
417        impl_binop!(Mul::mul for $name: $prim);
418        impl_binassign!(MulAssign::mul_assign for $name: $prim);
419        impl_unop!(Neg::neg for $name: $prim);
420        impl_partial_eq_and_eq!(for $name: $prim);
421        impl_partial_ord!(for $name: $prim);
422        impl_product_and_sum!(for $name);
423        impl_binop!(Rem::rem for $name: $prim);
424        impl_binassign!(RemAssign::rem_assign for $name: $prim);
425        impl_binop!(Sub::sub for $name: $prim);
426        impl_binassign!(SubAssign::sub_assign for $name: $prim);
427        impl_fmt!(UpperExp for $name);
428    };
429}
430
431macro_rules! define_newtype {
432    ($name:ident: $prim:ty, $align:expr) => {
433        #[doc = concat!("A wire-encoded `", stringify!($prim), "`")]
434        #[repr(C, align($align))]
435        #[derive(zerocopy::FromBytes, zerocopy::IntoBytes)]
436        pub struct $name(pub $prim);
437
438        impl ::core::ops::Deref for $name {
439            type Target = $prim;
440
441            fn deref(&self) -> &Self::Target {
442                &self.0
443            }
444        }
445
446        impl ::core::ops::DerefMut for $name {
447            fn deref_mut(&mut self) -> &mut Self::Target {
448                &mut self.0
449            }
450        }
451    };
452}
453
454macro_rules! define_signed_integer {
455    ($name:ident: $prim:ident, $align:expr) => {
456        define_newtype!($name: $prim, $align);
457        impl_signed_integer_traits!($name: $prim);
458    }
459}
460
461define_signed_integer!(WireI16: i16, 2);
462define_signed_integer!(WireI32: i32, 4);
463define_signed_integer!(WireI64: i64, 8);
464
465macro_rules! define_unsigned_integer {
466    ($name:ident: $prim:ident, $align:expr) => {
467        define_newtype!($name: $prim, $align);
468        impl_unsigned_integer_traits!($name: $prim);
469    }
470}
471
472define_unsigned_integer!(WireU16: u16, 2);
473define_unsigned_integer!(WireU32: u32, 4);
474define_unsigned_integer!(WireU64: u64, 8);
475
476macro_rules! define_float {
477    ($name:ident: $prim:ident, $align:expr) => {
478        define_newtype!($name: $prim, $align);
479        impl_float_traits!($name: $prim);
480    }
481}
482
483define_float!(WireF32: f32, 4);
484define_float!(WireF64: f64, 8);