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 u8);
504impl_builtin_primitive!(for i8);
505
506// Bool
507
508impl_fidl_convert!(for bool: bool);
509impl_fidl_constrained!(for bool);
510impl_fidl_copy_optimize!(for bool);
511
512unsafe impl<D: ?Sized> crate::Decode<D> for bool {
513    #[inline]
514    fn decode(slot: crate::Slot<'_, Self>, _: &mut D, _: ()) -> Result<(), crate::DecodeError> {
515        let value = unsafe { slot.as_ptr().cast::<u8>().read() };
516        match value {
517            0 | 1 => Ok(()),
518            invalid => Err(crate::DecodeError::InvalidBool(invalid)),
519        }
520    }
521}
522
523impl_fidl_encode!(for bool: bool);
524impl_fidl_wire!(for bool);
525
526// Integers
527
528macro_rules! impl_signed_integer_traits {
529    ($name:ident: $prim:ident) => {
530        impl_binop!(Add::add for $name: $prim);
531        impl_binassign!(AddAssign::add_assign for $name: $prim);
532        impl_clone_and_copy!(for $name);
533        impl_fmt!(Binary for $name);
534        impl_binop!(BitAnd::bitand for $name: $prim);
535        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
536        impl_binop!(BitOr::bitor for $name: $prim);
537        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
538        impl_binop!(BitXor::bitxor for $name: $prim);
539        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
540        impl_fmt!(Debug for $name);
541        impl_default!(for $name: $prim);
542        impl_fmt!(Display for $name);
543        impl_binop!(Div::div for $name: $prim);
544        impl_binassign!(DivAssign::div_assign for $name: $prim);
545        impl_from!(for $name: $prim);
546        impl_try_from_ptr_size!(isize for $name: $prim);
547        impl_hash!(for $name);
548        impl_fmt!(LowerExp for $name);
549        impl_fmt!(LowerHex for $name);
550        impl_binop!(Mul::mul for $name: $prim);
551        impl_binassign!(MulAssign::mul_assign for $name: $prim);
552        impl_unop!(Neg::neg for $name: $prim);
553        impl_unop!(Not::not for $name: $prim);
554        impl_fmt!(Octal for $name);
555        impl_partial_eq_and_eq!(for $name: $prim);
556        impl_partial_ord_and_ord!(for $name: $prim);
557        impl_product_and_sum!(for $name);
558        impl_binop!(Rem::rem for $name: $prim);
559        impl_binassign!(RemAssign::rem_assign for $name: $prim);
560        impl_binop!(Shl::shl for $name: $prim);
561        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
562        impl_binop!(Shr::shr for $name: $prim);
563        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
564        impl_binop!(Sub::sub for $name: $prim);
565        impl_binassign!(SubAssign::sub_assign for $name: $prim);
566        impl_fmt!(UpperExp for $name);
567        impl_fmt!(UpperHex for $name);
568
569        impl_fidl_convert!(for $name: $prim);
570        impl_fidl_constrained!(for $name);
571        impl_fidl_copy_optimize!(for $name: $prim);
572        impl_fidl_decode!(for $name);
573        impl_fidl_encode!(for $name: $prim);
574        impl_fidl_encode!(for $name: $name);
575        impl_fidl_wire!(for $name);
576    };
577}
578
579macro_rules! impl_unsigned_integer_traits {
580    ($name:ident: $prim:ident) => {
581        impl_binop!(Add::add for $name: $prim);
582        impl_binassign!(AddAssign::add_assign for $name: $prim);
583        impl_clone_and_copy!(for $name);
584        impl_fmt!(Binary for $name);
585        impl_binop!(BitAnd::bitand for $name: $prim);
586        impl_binassign!(BitAndAssign::bitand_assign for $name: $prim);
587        impl_binop!(BitOr::bitor for $name: $prim);
588        impl_binassign!(BitOrAssign::bitor_assign for $name: $prim);
589        impl_binop!(BitXor::bitxor for $name: $prim);
590        impl_binassign!(BitXorAssign::bitxor_assign for $name: $prim);
591        impl_fmt!(Debug for $name);
592        impl_default!(for $name: $prim);
593        impl_fmt!(Display for $name);
594        impl_binop!(Div::div for $name: $prim);
595        impl_binassign!(DivAssign::div_assign for $name: $prim);
596        impl_from!(for $name: $prim);
597        impl_try_from_ptr_size!(usize for $name: $prim);
598        impl_hash!(for $name);
599        impl_fmt!(LowerExp for $name);
600        impl_fmt!(LowerHex for $name);
601        impl_binop!(Mul::mul for $name: $prim);
602        impl_binassign!(MulAssign::mul_assign for $name: $prim);
603        impl_unop!(Not::not for $name: $prim);
604        impl_fmt!(Octal for $name);
605        impl_partial_eq_and_eq!(for $name: $prim);
606        impl_partial_ord_and_ord!(for $name: $prim);
607        impl_product_and_sum!(for $name);
608        impl_binop!(Rem::rem for $name: $prim);
609        impl_binassign!(RemAssign::rem_assign for $name: $prim);
610        impl_binop!(Shl::shl for $name: $prim);
611        impl_binassign!(ShlAssign::shl_assign for $name: $prim);
612        impl_binop!(Shr::shr for $name: $prim);
613        impl_binassign!(ShrAssign::shr_assign for $name: $prim);
614        impl_binop!(Sub::sub for $name: $prim);
615        impl_binassign!(SubAssign::sub_assign for $name: $prim);
616        impl_fmt!(UpperExp for $name);
617        impl_fmt!(UpperHex for $name);
618
619        impl_fidl_convert!(for $name: $prim);
620        impl_fidl_constrained!(for $name);
621        impl_fidl_copy_optimize!(for $name: $prim);
622        impl_fidl_decode!(for $name);
623        impl_fidl_encode!(for $name: $prim);
624        impl_fidl_encode!(for $name: $name);
625        impl_fidl_wire!(for $name);
626    };
627}
628
629macro_rules! impl_float_traits {
630    ($name:ident: $prim:ty) => {
631        impl_binop!(Add::add for $name: $prim);
632        impl_binassign!(AddAssign::add_assign for $name: $prim);
633        impl_clone_and_copy!(for $name);
634        impl_fmt!(Debug for $name);
635        impl_default!(for $name: $prim);
636        impl_fmt!(Display for $name);
637        impl_binop!(Div::div for $name: $prim);
638        impl_binassign!(DivAssign::div_assign for $name: $prim);
639        impl_from!(for $name: $prim);
640        impl_fmt!(LowerExp for $name);
641        impl_binop!(Mul::mul for $name: $prim);
642        impl_binassign!(MulAssign::mul_assign for $name: $prim);
643        impl_unop!(Neg::neg for $name: $prim);
644        impl_partial_eq_and_eq!(for $name: $prim);
645        impl_partial_ord!(for $name: $prim);
646        impl_product_and_sum!(for $name);
647        impl_binop!(Rem::rem for $name: $prim);
648        impl_binassign!(RemAssign::rem_assign for $name: $prim);
649        impl_binop!(Sub::sub for $name: $prim);
650        impl_binassign!(SubAssign::sub_assign for $name: $prim);
651        impl_fmt!(UpperExp for $name);
652
653        impl_fidl_convert!(for $name: $prim);
654        impl_fidl_constrained!(for $name);
655        impl_fidl_copy_optimize!(for $name: $prim);
656        impl_fidl_decode!(for $name);
657        impl_fidl_encode!(for $name: $prim);
658        impl_fidl_encode!(for $name: $name);
659        impl_fidl_wire!(for $name);
660    };
661}
662
663macro_rules! define_newtype {
664    ($name:ident: $prim:ty, $align:expr) => {
665        #[doc = concat!("A wire-encoded `", stringify!($prim), "`")]
666        #[repr(C, align($align))]
667        #[derive(zerocopy::FromBytes, zerocopy::IntoBytes)]
668        pub struct $name(pub $prim);
669
670        impl ::core::ops::Deref for $name {
671            type Target = $prim;
672
673            fn deref(&self) -> &Self::Target {
674                &self.0
675            }
676        }
677
678        impl ::core::ops::DerefMut for $name {
679            fn deref_mut(&mut self) -> &mut Self::Target {
680                &mut self.0
681            }
682        }
683    };
684}
685
686macro_rules! define_signed_integer {
687    ($name:ident: $prim:ident, $align:expr) => {
688        define_newtype!($name: $prim, $align);
689        impl_signed_integer_traits!($name: $prim);
690    }
691}
692
693define_signed_integer!(Int16: i16, 2);
694define_signed_integer!(Int32: i32, 4);
695define_signed_integer!(Int64: i64, 8);
696
697macro_rules! define_unsigned_integer {
698    ($name:ident: $prim:ident, $align:expr) => {
699        define_newtype!($name: $prim, $align);
700        impl_unsigned_integer_traits!($name: $prim);
701    }
702}
703
704define_unsigned_integer!(Uint16: u16, 2);
705define_unsigned_integer!(Uint32: u32, 4);
706define_unsigned_integer!(Uint64: u64, 8);
707
708macro_rules! define_float {
709    ($name:ident: $prim:ident, $align:expr) => {
710        define_newtype!($name: $prim, $align);
711        impl_float_traits!($name: $prim);
712    }
713}
714
715define_float!(Float32: f32, 4);
716define_float!(Float64: f64, 8);
717
718#[cfg(test)]
719mod tests {
720    use crate::{DecoderExt as _, EncoderExt as _, chunks, wire};
721
722    #[test]
723    fn decode_bool() {
724        #![allow(clippy::bool_assert_comparison)]
725
726        assert_eq!(
727            chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
728                .as_mut_slice()
729                .decode::<bool>()
730                .unwrap(),
731            true,
732        );
733        assert_eq!(
734            chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
735                .as_mut_slice()
736                .decode::<bool>()
737                .unwrap(),
738            false,
739        );
740    }
741
742    #[test]
743    fn encode_bool() {
744        assert_eq!(
745            Vec::encode(true).unwrap(),
746            chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
747        );
748        assert_eq!(
749            Vec::encode(false).unwrap(),
750            chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
751        );
752    }
753
754    #[test]
755    fn decode_ints() {
756        assert_eq!(
757            chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
758                .as_mut_slice()
759                .decode::<u8>()
760                .unwrap(),
761            0xa3u8,
762        );
763        assert_eq!(
764            chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
765                .as_mut_slice()
766                .decode::<i8>()
767                .unwrap(),
768            -0x45i8,
769        );
770
771        assert_eq!(
772            chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
773                .as_mut_slice()
774                .decode::<wire::Uint16>()
775                .unwrap(),
776            0x1234u16,
777        );
778        assert_eq!(
779            chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
780                .as_mut_slice()
781                .decode::<wire::Int16>()
782                .unwrap(),
783            -0x1234i16,
784        );
785
786        assert_eq!(
787            chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00]
788                .as_mut_slice()
789                .decode::<wire::Uint32>()
790                .unwrap(),
791            0x12345678u32,
792        );
793        assert_eq!(
794            chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00]
795                .as_mut_slice()
796                .decode::<wire::Int32>()
797                .unwrap(),
798            -0x12345678i32,
799        );
800
801        assert_eq!(
802            chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12]
803                .as_mut_slice()
804                .decode::<wire::Uint64>()
805                .unwrap(),
806            0x123456789abcdef0u64,
807        );
808        assert_eq!(
809            chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed]
810                .as_mut_slice()
811                .decode::<wire::Int64>()
812                .unwrap(),
813            -0x123456789abcdef0i64,
814        );
815    }
816
817    #[test]
818    fn encode_ints() {
819        assert_eq!(
820            Vec::encode(0xa3u8).unwrap(),
821            chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
822        );
823        assert_eq!(
824            Vec::encode(-0x45i8).unwrap(),
825            chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
826        );
827
828        assert_eq!(
829            Vec::encode(0x1234u16).unwrap(),
830            chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
831        );
832        assert_eq!(
833            Vec::encode(-0x1234i16).unwrap(),
834            chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
835        );
836
837        assert_eq!(
838            Vec::encode(0x12345678u32).unwrap(),
839            chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00]
840        );
841        assert_eq!(
842            Vec::encode(-0x12345678i32).unwrap(),
843            chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00]
844        );
845
846        assert_eq!(
847            Vec::encode(0x123456789abcdef0u64).unwrap(),
848            chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12],
849        );
850        assert_eq!(
851            Vec::encode(-0x123456789abcdef0i64).unwrap(),
852            chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed],
853        );
854    }
855
856    #[test]
857    fn decode_floats() {
858        assert_eq!(
859            chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00]
860                .as_mut_slice()
861                .decode::<wire::Float32>()
862                .unwrap(),
863            ::core::f32::consts::PI,
864        );
865        assert_eq!(
866            chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40]
867                .as_mut_slice()
868                .decode::<wire::Float64>()
869                .unwrap(),
870            ::core::f64::consts::PI,
871        );
872    }
873
874    #[test]
875    fn encode_floats() {
876        assert_eq!(
877            Vec::encode(::core::f32::consts::PI).unwrap(),
878            chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00],
879        );
880        assert_eq!(
881            Vec::encode(::core::f64::consts::PI).unwrap(),
882            chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40],
883        );
884    }
885}