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}