Skip to main content

fidl_next_codec/wire/
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
8// Standard library traits
9
10macro_rules! impl_unop {
11    ($trait:ident:: $fn:ident for $name:ident : $prim:ty) => {
12        impl ::core::ops::$trait for $name {
13            type Output = <$prim as ::core::ops::$trait>::Output;
14
15            #[inline]
16            fn $fn(self) -> Self::Output {
17                self.0.$fn()
18            }
19        }
20    };
21}
22
23macro_rules! impl_binop_one {
24    ($trait:ident:: $fn:ident($self:ty, $other:ty) -> $output:ty) => {
25        impl ::core::ops::$trait<$other> for $self {
26            type Output = $output;
27
28            #[inline]
29            fn $fn(self, other: $other) -> Self::Output {
30                self.0.$fn(other.0)
31            }
32        }
33    };
34}
35
36macro_rules! impl_binop_both {
37    ($trait:ident:: $fn:ident($self:ty, $other:ty) -> $output:ty) => {
38        impl ::core::ops::$trait<$other> for $self {
39            type Output = $output;
40
41            #[inline]
42            fn $fn(self, other: $other) -> Self::Output {
43                self.0.$fn(other)
44            }
45        }
46
47        impl ::core::ops::$trait<$self> for $other {
48            type Output = $output;
49
50            #[inline]
51            fn $fn(self, other: $self) -> Self::Output {
52                self.$fn(other.0)
53            }
54        }
55    };
56}
57
58macro_rules! impl_binop {
59    ($trait:ident::$fn:ident for $name:ident: $prim:ty) => {
60        impl_binop_both!($trait::$fn ($name, $prim) -> $prim);
61        impl_binop_both!($trait::$fn (&'_ $name, $prim) -> $prim);
62        impl_binop_both!($trait::$fn ($name, &'_ $prim) -> $prim);
63        impl_binop_both!($trait::$fn (&'_ $name, &'_ $prim) -> $prim);
64
65        impl_binop_one!($trait::$fn ($name, $name) -> $prim);
66        impl_binop_one!($trait::$fn (&'_ $name, $name) -> $prim);
67        impl_binop_one!($trait::$fn ($name, &'_ $name) -> $prim);
68        impl_binop_one!($trait::$fn (&'_ $name, &'_ $name) -> $prim);
69    };
70}
71
72macro_rules! impl_binassign {
73    ($trait:ident:: $fn:ident for $name:ident : $prim:ty) => {
74        impl ::core::ops::$trait<$prim> for $name {
75            #[inline]
76            fn $fn(&mut self, other: $prim) {
77                let mut value = self.0;
78                value.$fn(other);
79                *self = Self(value);
80            }
81        }
82
83        impl ::core::ops::$trait<$name> for $name {
84            #[inline]
85            fn $fn(&mut self, other: $name) {
86                let mut value = self.0;
87                value.$fn(other.0);
88                *self = Self(value);
89            }
90        }
91
92        impl ::core::ops::$trait<&'_ $prim> for $name {
93            #[inline]
94            fn $fn(&mut self, other: &'_ $prim) {
95                let mut value = self.0;
96                value.$fn(other);
97                *self = Self(value);
98            }
99        }
100
101        impl ::core::ops::$trait<&'_ $name> for $name {
102            #[inline]
103            fn $fn(&mut self, other: &'_ $name) {
104                let mut value = self.0;
105                value.$fn(other.0);
106                *self = Self(value);
107            }
108        }
109    };
110}
111
112macro_rules! impl_clone_and_copy {
113    (for $name:ident) => {
114        impl Clone for $name {
115            #[inline]
116            fn clone(&self) -> Self {
117                *self
118            }
119        }
120
121        impl Copy for $name {}
122    };
123}
124
125macro_rules! impl_fmt {
126    ($trait:ident for $name:ident) => {
127        impl ::core::fmt::$trait for $name {
128            #[inline]
129            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
130                ::core::fmt::$trait::fmt(&self.0, f)
131            }
132        }
133    };
134}
135
136macro_rules! impl_default {
137    (for $name:ident : $prim:ty) => {
138        impl Default for $name {
139            #[inline]
140            fn default() -> Self {
141                Self(<$prim>::default())
142            }
143        }
144    };
145}
146
147macro_rules! impl_from {
148    (for $name:ident : $prim:ty) => {
149        impl From<$prim> for $name {
150            fn from(value: $prim) -> Self {
151                Self(value)
152            }
153        }
154
155        impl<'a> From<&'a $prim> for $name {
156            fn from(value: &'a $prim) -> Self {
157                Self(*value)
158            }
159        }
160
161        impl From<$name> for $prim {
162            fn from(value: $name) -> Self {
163                value.0
164            }
165        }
166
167        impl<'a> From<&'a $name> for $prim {
168            fn from(value: &'a $name) -> Self {
169                value.0
170            }
171        }
172    };
173}
174
175macro_rules! impl_try_from_ptr_size {
176    ($size:ident for $name:ident: $prim:ident) => {
177        impl TryFrom<$size> for $name {
178            type Error = <$prim as TryFrom<$size>>::Error;
179
180            #[inline]
181            fn try_from(value: $size) -> Result<Self, Self::Error> {
182                Ok(Self(<$prim>::try_from(value)?))
183            }
184        }
185
186        impl_try_into_ptr_size!($size for $name: $prim);
187    };
188}
189
190macro_rules! impl_try_into_ptr_size {
191    (isize for $name:ident: i16) => {
192        impl_into_ptr_size!(isize for $name);
193    };
194
195    (usize for $name:ident: u16) => {
196        impl_into_ptr_size!(usize for $name);
197    };
198
199    ($size:ident for $name:ident: $prim:ident) => {
200        impl TryFrom<$name> for $size {
201            type Error = <$size as TryFrom<$prim>>::Error;
202
203            #[inline]
204            fn try_from(value: $name) -> Result<Self, Self::Error> {
205                <$size>::try_from(value.0)
206            }
207        }
208    };
209}
210
211macro_rules! impl_into_ptr_size {
212    ($size:ident for $name:ident) => {
213        impl From<$name> for $size {
214            #[inline]
215            fn from(value: $name) -> Self {
216                <$size>::from(value.0)
217            }
218        }
219    };
220}
221
222macro_rules! impl_hash {
223    (for $name:ident) => {
224        impl core::hash::Hash for $name {
225            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
226                self.0.hash(state);
227            }
228        }
229    };
230}
231
232macro_rules! impl_partial_ord_and_ord {
233    (for $name:ident : $prim:ty) => {
234        impl PartialOrd for $name {
235            #[inline]
236            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
237                Some(self.cmp(other))
238            }
239        }
240
241        impl PartialOrd<$prim> for $name {
242            #[inline]
243            fn partial_cmp(&self, other: &$prim) -> Option<::core::cmp::Ordering> {
244                self.0.partial_cmp(other)
245            }
246        }
247
248        impl Ord for $name {
249            #[inline]
250            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
251                self.0.cmp(&other.0)
252            }
253        }
254    };
255}
256
257macro_rules! impl_partial_eq_and_eq {
258    (for $name:ident : $prim:ty) => {
259        impl PartialEq for $name {
260            #[inline]
261            fn eq(&self, other: &Self) -> bool {
262                let lhs = self.0;
263                let rhs = other.0;
264                lhs.eq(&rhs)
265            }
266        }
267
268        impl PartialEq<$prim> for $name {
269            #[inline]
270            fn eq(&self, other: &$prim) -> bool {
271                self.0.eq(other)
272            }
273        }
274
275        impl Eq for $name {}
276    };
277}
278
279macro_rules! impl_partial_ord {
280    (for $name:ident : $prim:ty) => {
281        impl PartialOrd for $name {
282            #[inline]
283            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
284                self.0.partial_cmp(&other.0)
285            }
286        }
287
288        impl PartialOrd<$prim> for $name {
289            #[inline]
290            fn partial_cmp(&self, other: &$prim) -> Option<::core::cmp::Ordering> {
291                self.0.partial_cmp(other)
292            }
293        }
294    };
295}
296
297macro_rules! impl_product_and_sum {
298    (for $name:ident) => {
299        impl ::core::iter::Product for $name {
300            #[inline]
301            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
302                Self(iter.map(|x| x.0).product())
303            }
304        }
305
306        impl ::core::iter::Sum for $name {
307            #[inline]
308            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
309                Self(iter.map(|x| x.0).sum())
310            }
311        }
312    };
313}
314
315macro_rules! impl_fidl_convert {
316    (for $name:ty : $prim:ty) => {
317        impl $crate::FromWire<$name> for $prim {
318            const COPY_OPTIMIZATION: $crate::CopyOptimization<$name, $prim> =
319                $crate::CopyOptimization::<$name, $prim>::PRIMITIVE;
320
321            #[inline]
322            fn from_wire(wire: $name) -> Self {
323                wire.into()
324            }
325        }
326
327        impl $crate::FromWireRef<$name> for $prim {
328            #[inline]
329            fn from_wire_ref(wire: &$name) -> Self {
330                (*wire).into()
331            }
332        }
333
334        impl $crate::IntoNatural for $name {
335            type Natural = $prim;
336        }
337    };
338}
339
340macro_rules! impl_fidl_constrained {
341    (for $name:ty) => {
342        impl $crate::Constrained for $name {
343            type Constraint = ();
344
345            fn validate(
346                _: $crate::Slot<'_, Self>,
347                _: Self::Constraint,
348            ) -> Result<(), $crate::ValidationError> {
349                Ok(())
350            }
351        }
352    };
353}
354
355macro_rules! impl_fidl_copy_optimize {
356    (for $name:ty) => {
357        impl $crate::CopyOptimization<$name, $name> {
358            /// Whether copy optimization between the two primitive types is
359            /// enabled.
360            pub const PRIMITIVE: Self = Self::identity();
361        }
362    };
363
364    (for $name:ty : $prim:ty) => {
365        impl_fidl_copy_optimize!(for $name);
366
367        impl $crate::CopyOptimization<$prim, $name> {
368            /// Whether copy optimization between the two primitive types is
369            /// enabled.
370            pub const PRIMITIVE: Self =
371                // SAFETY: Copy optimization for primitives is enabled if their
372                // size <= 1 or the target is little-endian.
373                unsafe {
374                    $crate::CopyOptimization::enable_if(
375                        size_of::<Self>() <= 1 || cfg!(target_endian = "little"),
376                    )
377                };
378        }
379
380        impl $crate::CopyOptimization<$name, $prim> {
381            /// Whether copy optimization between the two primitive types is
382            /// enabled.
383            pub const PRIMITIVE: Self =
384                // SAFETY: Copy optimization between these two primitives is
385                // commutative.
386                unsafe {
387                    $crate::CopyOptimization::enable_if(
388                        $crate::CopyOptimization::<$prim, $name>::PRIMITIVE.is_enabled(),
389                    )
390                };
391        }
392    }
393}
394
395macro_rules! impl_fidl_decode {
396    (for $name:ty) => {
397        unsafe impl<D: ?Sized> $crate::Decode<D> for $name {
398            #[inline]
399            fn decode(
400                _: $crate::Slot<'_, Self>,
401                _: &mut D,
402                _: (),
403            ) -> Result<(), $crate::DecodeError> {
404                Ok(())
405            }
406        }
407    };
408}
409
410macro_rules! impl_fidl_encode {
411    (for $name:ty : $prim:ty) => {
412        unsafe impl<E: ?Sized> $crate::Encode<$name, E> for $prim {
413            const COPY_OPTIMIZATION: $crate::CopyOptimization<$prim, $name> =
414                $crate::CopyOptimization::<$prim, $name>::PRIMITIVE;
415
416            #[inline]
417            fn encode(
418                self,
419                encoder: &mut E,
420                out: &mut ::core::mem::MaybeUninit<$name>,
421                constraint: <$name as $crate::Constrained>::Constraint,
422            ) -> Result<(), $crate::EncodeError> {
423                $crate::Encode::encode(&self, encoder, out, constraint)
424            }
425        }
426
427        unsafe impl<E: ?Sized> $crate::Encode<$name, E> for &$prim {
428            #[inline]
429            fn encode(
430                self,
431                _: &mut E,
432                out: &mut ::core::mem::MaybeUninit<$name>,
433                _: <$name as $crate::Constrained>::Constraint,
434            ) -> Result<(), $crate::EncodeError> {
435                out.write(<$name>::from(*self));
436                Ok(())
437            }
438        }
439
440        unsafe impl<E> $crate::EncodeOption<$crate::wire::Box<'static, $name>, E> for $prim
441        where
442            E: $crate::Encoder + ?Sized,
443        {
444            #[inline]
445            fn encode_option(
446                this: Option<Self>,
447                encoder: &mut E,
448                out: &mut ::core::mem::MaybeUninit<$crate::wire::Box<'static, $name>>,
449                constraint: <$name as $crate::Constrained>::Constraint,
450            ) -> Result<(), $crate::EncodeError> {
451                if let Some(value) = this {
452                    $crate::EncoderExt::encode_next_with_constraint(encoder, value, constraint)?;
453                    $crate::wire::Box::encode_present(out);
454                } else {
455                    $crate::wire::Box::encode_absent(out);
456                }
457
458                Ok(())
459            }
460        }
461
462        unsafe impl<E> $crate::EncodeOption<$crate::wire::Box<'static, $name>, E> for &$prim
463        where
464            E: $crate::Encoder + ?Sized,
465        {
466            #[inline]
467            fn encode_option(
468                this: Option<Self>,
469                encoder: &mut E,
470                out: &mut ::core::mem::MaybeUninit<$crate::wire::Box<'static, $name>>,
471                constraint: <$name as $crate::Constrained>::Constraint,
472            ) -> Result<(), $crate::EncodeError> {
473                <$prim>::encode_option(this.cloned(), encoder, out, constraint)
474            }
475        }
476    };
477}
478
479macro_rules! impl_fidl_wire {
480    (for $name:ty) => {
481        unsafe impl $crate::Wire for $name {
482            type Narrowed<'de> = Self;
483
484            #[inline]
485            fn zero_padding(_: &mut ::core::mem::MaybeUninit<Self>) {}
486        }
487    };
488}
489
490// Builtins
491
492macro_rules! impl_builtin_primitive {
493    (for $name:ty) => {
494        impl_fidl_convert!(for $name : $name);
495        impl_fidl_constrained!(for $name);
496        impl_fidl_copy_optimize!(for $name);
497        impl_fidl_decode!(for $name);
498        impl_fidl_encode!(for $name : $name);
499        impl_fidl_wire!(for $name);
500    };
501}
502
503impl_builtin_primitive!(for ());
504impl_builtin_primitive!(for u8);
505impl_builtin_primitive!(for i8);
506
507// Bool
508
509impl_fidl_convert!(for bool: bool);
510impl_fidl_constrained!(for bool);
511impl_fidl_copy_optimize!(for bool);
512
513unsafe impl<D: ?Sized> crate::Decode<D> for bool {
514    #[inline]
515    fn decode(slot: crate::Slot<'_, Self>, _: &mut D, _: ()) -> Result<(), crate::DecodeError> {
516        let value = unsafe { slot.as_ptr().cast::<u8>().read() };
517        match value {
518            0 | 1 => (),
519            invalid => return Err(crate::DecodeError::InvalidBool(invalid)),
520        }
521        Ok(())
522    }
523}
524
525impl_fidl_encode!(for bool: bool);
526impl_fidl_wire!(for bool);
527
528// Integers
529
530macro_rules! impl_signed_integer_traits {
531    ($name:ident: $prim:ident) => {
532        impl_binop!(Add::add for $name: $prim);
533        impl_binassign!(AddAssign::add_assign for $name: $prim);
534        impl_clone_and_copy!(for $name);
535        impl_fmt!(Binary for $name);
536        impl_binop!(BitAnd::bitand for $name: $prim);
537        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
538        impl_binop!(BitOr::bitor for $name: $prim);
539        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
540        impl_binop!(BitXor::bitxor for $name: $prim);
541        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
542        impl_fmt!(Debug for $name);
543        impl_default!(for $name: $prim);
544        impl_fmt!(Display for $name);
545        impl_binop!(Div::div for $name: $prim);
546        impl_binassign!(DivAssign::div_assign for $name: $prim);
547        impl_from!(for $name: $prim);
548        impl_try_from_ptr_size!(isize for $name: $prim);
549        impl_hash!(for $name);
550        impl_fmt!(LowerExp for $name);
551        impl_fmt!(LowerHex for $name);
552        impl_binop!(Mul::mul for $name: $prim);
553        impl_binassign!(MulAssign::mul_assign for $name: $prim);
554        impl_unop!(Neg::neg for $name: $prim);
555        impl_unop!(Not::not for $name: $prim);
556        impl_fmt!(Octal for $name);
557        impl_partial_eq_and_eq!(for $name: $prim);
558        impl_partial_ord_and_ord!(for $name: $prim);
559        impl_product_and_sum!(for $name);
560        impl_binop!(Rem::rem for $name: $prim);
561        impl_binassign!(RemAssign::rem_assign for $name: $prim);
562        impl_binop!(Shl::shl for $name: $prim);
563        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
564        impl_binop!(Shr::shr for $name: $prim);
565        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
566        impl_binop!(Sub::sub for $name: $prim);
567        impl_binassign!(SubAssign::sub_assign for $name: $prim);
568        impl_fmt!(UpperExp for $name);
569        impl_fmt!(UpperHex for $name);
570
571        impl_fidl_convert!(for $name: $prim);
572        impl_fidl_constrained!(for $name);
573        impl_fidl_copy_optimize!(for $name: $prim);
574        impl_fidl_decode!(for $name);
575        impl_fidl_encode!(for $name: $prim);
576        impl_fidl_encode!(for $name: $name);
577        impl_fidl_wire!(for $name);
578    };
579}
580
581macro_rules! impl_unsigned_integer_traits {
582    ($name:ident: $prim:ident) => {
583        impl_binop!(Add::add for $name: $prim);
584        impl_binassign!(AddAssign::add_assign for $name: $prim);
585        impl_clone_and_copy!(for $name);
586        impl_fmt!(Binary for $name);
587        impl_binop!(BitAnd::bitand for $name: $prim);
588        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
589        impl_binop!(BitOr::bitor for $name: $prim);
590        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
591        impl_binop!(BitXor::bitxor for $name: $prim);
592        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
593        impl_fmt!(Debug for $name);
594        impl_default!(for $name: $prim);
595        impl_fmt!(Display for $name);
596        impl_binop!(Div::div for $name: $prim);
597        impl_binassign!(DivAssign::div_assign for $name: $prim);
598        impl_from!(for $name: $prim);
599        impl_try_from_ptr_size!(usize for $name: $prim);
600        impl_hash!(for $name);
601        impl_fmt!(LowerExp for $name);
602        impl_fmt!(LowerHex for $name);
603        impl_binop!(Mul::mul for $name: $prim);
604        impl_binassign!(MulAssign::mul_assign for $name: $prim);
605        impl_unop!(Not::not for $name: $prim);
606        impl_fmt!(Octal for $name);
607        impl_partial_eq_and_eq!(for $name: $prim);
608        impl_partial_ord_and_ord!(for $name: $prim);
609        impl_product_and_sum!(for $name);
610        impl_binop!(Rem::rem for $name: $prim);
611        impl_binassign!(RemAssign::rem_assign for $name: $prim);
612        impl_binop!(Shl::shl for $name: $prim);
613        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
614        impl_binop!(Shr::shr for $name: $prim);
615        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
616        impl_binop!(Sub::sub for $name: $prim);
617        impl_binassign!(SubAssign::sub_assign for $name: $prim);
618        impl_fmt!(UpperExp for $name);
619        impl_fmt!(UpperHex for $name);
620
621        impl_fidl_convert!(for $name: $prim);
622        impl_fidl_constrained!(for $name);
623        impl_fidl_copy_optimize!(for $name: $prim);
624        impl_fidl_decode!(for $name);
625        impl_fidl_encode!(for $name: $prim);
626        impl_fidl_encode!(for $name: $name);
627        impl_fidl_wire!(for $name);
628    };
629}
630
631macro_rules! impl_float_traits {
632    ($name:ident: $prim:ty) => {
633        impl_binop!(Add::add for $name: $prim);
634        impl_binassign!(AddAssign::add_assign for $name: $prim);
635        impl_clone_and_copy!(for $name);
636        impl_fmt!(Debug for $name);
637        impl_default!(for $name: $prim);
638        impl_fmt!(Display for $name);
639        impl_binop!(Div::div for $name: $prim);
640        impl_binassign!(DivAssign::div_assign for $name: $prim);
641        impl_from!(for $name: $prim);
642        impl_fmt!(LowerExp for $name);
643        impl_binop!(Mul::mul for $name: $prim);
644        impl_binassign!(MulAssign::mul_assign for $name: $prim);
645        impl_unop!(Neg::neg for $name: $prim);
646        impl_partial_eq_and_eq!(for $name: $prim);
647        impl_partial_ord!(for $name: $prim);
648        impl_product_and_sum!(for $name);
649        impl_binop!(Rem::rem for $name: $prim);
650        impl_binassign!(RemAssign::rem_assign for $name: $prim);
651        impl_binop!(Sub::sub for $name: $prim);
652        impl_binassign!(SubAssign::sub_assign for $name: $prim);
653        impl_fmt!(UpperExp for $name);
654
655        impl_fidl_convert!(for $name: $prim);
656        impl_fidl_constrained!(for $name);
657        impl_fidl_copy_optimize!(for $name: $prim);
658        impl_fidl_decode!(for $name);
659        impl_fidl_encode!(for $name: $prim);
660        impl_fidl_encode!(for $name: $name);
661        impl_fidl_wire!(for $name);
662    };
663}
664
665macro_rules! define_newtype {
666    ($name:ident: $prim:ty, $align:expr) => {
667        #[doc = concat!("A wire-encoded `", stringify!($prim), "`")]
668        #[repr(C, align($align))]
669        #[derive(zerocopy::FromBytes, zerocopy::IntoBytes)]
670        pub struct $name(pub $prim);
671
672        impl ::core::ops::Deref for $name {
673            type Target = $prim;
674
675            fn deref(&self) -> &Self::Target {
676                &self.0
677            }
678        }
679
680        impl ::core::ops::DerefMut for $name {
681            fn deref_mut(&mut self) -> &mut Self::Target {
682                &mut self.0
683            }
684        }
685    };
686}
687
688macro_rules! define_signed_integer {
689    ($name:ident: $prim:ident, $align:expr) => {
690        define_newtype!($name: $prim, $align);
691        impl_signed_integer_traits!($name: $prim);
692    }
693}
694
695define_signed_integer!(Int16: i16, 2);
696define_signed_integer!(Int32: i32, 4);
697define_signed_integer!(Int64: i64, 8);
698
699macro_rules! define_unsigned_integer {
700    ($name:ident: $prim:ident, $align:expr) => {
701        define_newtype!($name: $prim, $align);
702        impl_unsigned_integer_traits!($name: $prim);
703    }
704}
705
706define_unsigned_integer!(Uint16: u16, 2);
707define_unsigned_integer!(Uint32: u32, 4);
708define_unsigned_integer!(Uint64: u64, 8);
709
710macro_rules! define_float {
711    ($name:ident: $prim:ident, $align:expr) => {
712        define_newtype!($name: $prim, $align);
713        impl_float_traits!($name: $prim);
714    }
715}
716
717define_float!(Float32: f32, 4);
718define_float!(Float64: f64, 8);
719
720#[cfg(test)]
721mod tests {
722    use crate::{DecoderExt as _, EncoderExt as _, chunks, wire};
723
724    #[test]
725    fn decode_unit() {
726        assert_eq!(chunks![].as_mut_slice().decode::<()>().unwrap(), ());
727    }
728
729    #[test]
730    fn encode_unit() {
731        assert_eq!(Vec::encode(()).unwrap(), chunks![]);
732    }
733
734    #[test]
735    fn decode_bool() {
736        #![allow(clippy::bool_assert_comparison)]
737
738        assert_eq!(
739            chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
740                .as_mut_slice()
741                .decode::<bool>()
742                .unwrap(),
743            true,
744        );
745        assert_eq!(
746            chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
747                .as_mut_slice()
748                .decode::<bool>()
749                .unwrap(),
750            false,
751        );
752    }
753
754    #[test]
755    fn encode_bool() {
756        assert_eq!(
757            Vec::encode(true).unwrap(),
758            chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
759        );
760        assert_eq!(
761            Vec::encode(false).unwrap(),
762            chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
763        );
764    }
765
766    #[test]
767    fn decode_ints() {
768        assert_eq!(
769            chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
770                .as_mut_slice()
771                .decode::<u8>()
772                .unwrap(),
773            0xa3u8,
774        );
775        assert_eq!(
776            chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
777                .as_mut_slice()
778                .decode::<i8>()
779                .unwrap(),
780            -0x45i8,
781        );
782
783        assert_eq!(
784            chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
785                .as_mut_slice()
786                .decode::<wire::Uint16>()
787                .unwrap(),
788            0x1234u16,
789        );
790        assert_eq!(
791            chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
792                .as_mut_slice()
793                .decode::<wire::Int16>()
794                .unwrap(),
795            -0x1234i16,
796        );
797
798        assert_eq!(
799            chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00]
800                .as_mut_slice()
801                .decode::<wire::Uint32>()
802                .unwrap(),
803            0x12345678u32,
804        );
805        assert_eq!(
806            chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00]
807                .as_mut_slice()
808                .decode::<wire::Int32>()
809                .unwrap(),
810            -0x12345678i32,
811        );
812
813        assert_eq!(
814            chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12]
815                .as_mut_slice()
816                .decode::<wire::Uint64>()
817                .unwrap(),
818            0x123456789abcdef0u64,
819        );
820        assert_eq!(
821            chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed]
822                .as_mut_slice()
823                .decode::<wire::Int64>()
824                .unwrap(),
825            -0x123456789abcdef0i64,
826        );
827    }
828
829    #[test]
830    fn encode_ints() {
831        assert_eq!(
832            Vec::encode(0xa3u8).unwrap(),
833            chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
834        );
835        assert_eq!(
836            Vec::encode(-0x45i8).unwrap(),
837            chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
838        );
839
840        assert_eq!(
841            Vec::encode(0x1234u16).unwrap(),
842            chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
843        );
844        assert_eq!(
845            Vec::encode(-0x1234i16).unwrap(),
846            chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
847        );
848
849        assert_eq!(
850            Vec::encode(0x12345678u32).unwrap(),
851            chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00]
852        );
853        assert_eq!(
854            Vec::encode(-0x12345678i32).unwrap(),
855            chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00]
856        );
857
858        assert_eq!(
859            Vec::encode(0x123456789abcdef0u64).unwrap(),
860            chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12],
861        );
862        assert_eq!(
863            Vec::encode(-0x123456789abcdef0i64).unwrap(),
864            chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed],
865        );
866    }
867
868    #[test]
869    fn decode_floats() {
870        assert_eq!(
871            chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00]
872                .as_mut_slice()
873                .decode::<wire::Float32>()
874                .unwrap(),
875            ::core::f32::consts::PI,
876        );
877        assert_eq!(
878            chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40]
879                .as_mut_slice()
880                .decode::<wire::Float64>()
881                .unwrap(),
882            ::core::f64::consts::PI,
883        );
884    }
885
886    #[test]
887    fn encode_floats() {
888        assert_eq!(
889            Vec::encode(::core::f32::consts::PI).unwrap(),
890            chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00],
891        );
892        assert_eq!(
893            Vec::encode(::core::f64::consts::PI).unwrap(),
894            chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40],
895        );
896    }
897}