1mod error;
8
9pub use self::error::*;
10
11use crate::{
12    Constrained, Slot, Wire, WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64,
13};
14
15pub unsafe trait Decode<D: ?Sized>: Wire + Constrained {
22    fn decode(
27        slot: Slot<'_, Self>,
28        decoder: &mut D,
29        constraint: Self::Constraint,
30    ) -> Result<(), DecodeError>;
31}
32
33macro_rules! impl_primitive {
34    ($ty:ty) => {
35        unsafe impl<D: ?Sized> Decode<D> for $ty {
36            #[inline]
37            fn decode(_: Slot<'_, Self>, _: &mut D, _: ()) -> Result<(), DecodeError> {
38                Ok(())
39            }
40        }
41    };
42}
43
44macro_rules! impl_primitives {
45    ($($ty:ty),* $(,)?) => {
46        $(
47            impl_primitive!($ty);
48        )*
49    }
50}
51
52impl_primitives! {
53    (),
54
55    i8,
56    WireI16,
57    WireI32,
58    WireI64,
59
60    u8,
61    WireU16,
62    WireU32,
63    WireU64,
64
65    WireF32,
66    WireF64,
67}
68
69unsafe impl<D: ?Sized> Decode<D> for bool {
70    #[inline]
71    fn decode(slot: Slot<'_, Self>, _: &mut D, _: ()) -> Result<(), DecodeError> {
72        let value = unsafe { slot.as_ptr().cast::<u8>().read() };
73        match value {
74            0 | 1 => (),
75            invalid => return Err(DecodeError::InvalidBool(invalid)),
76        }
77        Ok(())
78    }
79}
80
81unsafe impl<D: ?Sized, T: Decode<D>, const N: usize> Decode<D> for [T; N] {
82    fn decode(
83        mut slot: Slot<'_, Self>,
84        decoder: &mut D,
85        constraint: T::Constraint,
86    ) -> Result<(), DecodeError> {
87        for i in 0..N {
88            T::decode(slot.index(i), decoder, constraint)?;
89        }
90        Ok(())
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use crate::{WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64, chunks};
97
98    use crate::testing::{assert_decoded, assert_decoded_with_constraint};
99    use crate::wire::{WireBox, WireString, WireVector};
100    use crate::{WireOptionalString, WireOptionalVector};
101
102    #[test]
103    fn decode_unit() {
104        assert_decoded::<()>(&mut chunks![], |_| ());
105    }
106
107    #[test]
108    fn decode_bool() {
109        assert_decoded::<bool>(&mut chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
110            assert!(*x)
111        });
112        assert_decoded::<bool>(&mut chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
113            assert!(!*x)
114        });
115    }
116
117    #[test]
118    fn decode_ints() {
119        assert_decoded::<u8>(&mut chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
120            assert_eq!(*x, 0xa3u8)
121        });
122        assert_decoded::<i8>(&mut chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
123            assert_eq!(*x, -0x45i8)
124        });
125
126        assert_decoded::<WireU16>(
127            &mut chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
128            |x| assert_eq!(*x, 0x1234u16),
129        );
130        assert_decoded::<WireI16>(
131            &mut chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
132            |x| assert_eq!(*x, -0x1234i16),
133        );
134
135        assert_decoded::<WireU32>(
136            &mut chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00],
137            |x| assert_eq!(*x, 0x12345678u32),
138        );
139        assert_decoded::<WireI32>(
140            &mut chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00],
141            |x| assert_eq!(*x, -0x12345678i32),
142        );
143
144        assert_decoded::<WireU64>(
145            &mut chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12],
146            |x| assert_eq!(*x, 0x123456789abcdef0u64),
147        );
148        assert_decoded::<WireI64>(
149            &mut chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed],
150            |x| assert_eq!(*x, -0x123456789abcdef0i64),
151        );
152    }
153
154    #[test]
155    fn decode_floats() {
156        assert_decoded::<WireF32>(
157            &mut chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00],
158            |x| assert_eq!(*x, ::core::f32::consts::PI),
159        );
160        assert_decoded::<WireF64>(
161            &mut chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40],
162            |x| assert_eq!(*x, ::core::f64::consts::PI),
163        );
164    }
165
166    #[test]
167    fn decode_box() {
168        assert_decoded::<WireBox<'_, WireU64>>(
169            &mut chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
170            |x| assert_eq!(x.as_ref(), None),
171        );
172        assert_decoded::<WireBox<'_, WireU64>>(
173            &mut chunks![
174                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
175                0x34, 0x12,
176            ],
177            |x| assert_eq!(*x.as_ref().unwrap(), 0x123456789abcdef0u64),
178        );
179    }
180
181    #[test]
182    fn decode_vec() {
183        assert_decoded_with_constraint::<WireOptionalVector<'_, WireU32>>(
184            &mut chunks![
185                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186                0x00, 0x00,
187            ],
188            (1000, ()),
189            |x| assert!(x.as_ref().is_none()),
190        );
191        assert_decoded_with_constraint::<WireVector<'_, WireU32>>(
192            &mut chunks![
193                0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
194                0xff, 0xff, 0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a,
195            ],
196            (1000, ()),
197            |x| assert_eq!(x.as_slice(), [0x12345678, 0x9abcdef0].as_slice(),),
198        );
199        assert_decoded_with_constraint::<WireVector<'_, WireU32>>(
200            &mut chunks![
201                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
202                0xff, 0xff,
203            ],
204            (1000, ()),
205            |x| assert_eq!(x.len(), 0),
206        );
207    }
208
209    #[test]
210    fn decode_string() {
211        assert_decoded_with_constraint::<WireOptionalString<'_>>(
212            &mut chunks![
213                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214                0x00, 0x00,
215            ],
216            1000,
217            |x| assert!(x.is_none()),
218        );
219        assert_decoded_with_constraint::<WireString<'_>>(
220            &mut chunks![
221                0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
222                0xff, 0xff, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00,
223            ],
224            1000,
225            |x| assert_eq!(x.as_str(), "0123"),
226        );
227        assert_decoded_with_constraint::<WireString<'_>>(
228            &mut chunks![
229                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
230                0xff, 0xff,
231            ],
232            1000,
233            |x| assert_eq!(x.len(), 0),
234        );
235    }
236}