1use crate::{
22 util::at_least, varint::UInt, EncodeSize, Error, FixedSize, RangeCfg, Read, ReadExt, Write,
23};
24use bytes::{Buf, BufMut};
25
26macro_rules! impl_numeric {
28 ($type:ty, $read_method:ident, $write_method:ident) => {
29 impl Write for $type {
30 #[inline]
31 fn write(&self, buf: &mut impl BufMut) {
32 buf.$write_method(*self);
33 }
34 }
35
36 impl Read for $type {
37 type Cfg = ();
38 #[inline]
39 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
40 at_least(buf, core::mem::size_of::<$type>())?;
41 Ok(buf.$read_method())
42 }
43 }
44
45 impl FixedSize for $type {
46 const SIZE: usize = core::mem::size_of::<$type>();
47 }
48 };
49}
50
51impl_numeric!(u8, get_u8, put_u8);
52impl_numeric!(u16, get_u16, put_u16);
53impl_numeric!(u32, get_u32, put_u32);
54impl_numeric!(u64, get_u64, put_u64);
55impl_numeric!(u128, get_u128, put_u128);
56impl_numeric!(i8, get_i8, put_i8);
57impl_numeric!(i16, get_i16, put_i16);
58impl_numeric!(i32, get_i32, put_i32);
59impl_numeric!(i64, get_i64, put_i64);
60impl_numeric!(i128, get_i128, put_i128);
61impl_numeric!(f32, get_f32, put_f32);
62impl_numeric!(f64, get_f64, put_f64);
63
64impl Write for usize {
66 #[inline]
67 fn write(&self, buf: &mut impl BufMut) {
68 let self_as_u32 = u32::try_from(*self).expect("write: usize value is larger than u32");
69 UInt(self_as_u32).write(buf);
70 }
71}
72
73impl Read for usize {
74 type Cfg = RangeCfg<Self>;
75
76 #[inline]
77 fn read_cfg(buf: &mut impl Buf, range: &Self::Cfg) -> Result<Self, Error> {
78 let self_as_u32: u32 = UInt::read(buf)?.into();
79 let result = Self::try_from(self_as_u32).map_err(|_| Error::InvalidUsize)?;
80 if !range.contains(&result) {
81 return Err(Error::InvalidLength(result));
82 }
83 Ok(result)
84 }
85}
86
87impl EncodeSize for usize {
88 #[inline]
89 fn encode_size(&self) -> usize {
90 let self_as_u32 =
91 u32::try_from(*self).expect("encode_size: usize value is larger than u32");
92 UInt(self_as_u32).encode_size()
93 }
94}
95
96impl Write for bool {
98 #[inline]
99 fn write(&self, buf: &mut impl BufMut) {
100 buf.put_u8(if *self { 1 } else { 0 });
101 }
102}
103
104impl Read for bool {
105 type Cfg = ();
106 #[inline]
107 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
108 match u8::read(buf)? {
109 0 => Ok(false),
110 1 => Ok(true),
111 _ => Err(Error::InvalidBool),
112 }
113 }
114}
115
116impl FixedSize for bool {
117 const SIZE: usize = 1;
118}
119
120impl<const N: usize> Write for [u8; N] {
122 #[inline]
123 fn write(&self, buf: &mut impl BufMut) {
124 buf.put(&self[..]);
125 }
126}
127
128impl<const N: usize> Read for [u8; N] {
129 type Cfg = ();
130 #[inline]
131 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
132 at_least(buf, N)?;
133 let mut dst = [0; N];
134 buf.copy_to_slice(&mut dst);
135 Ok(dst)
136 }
137}
138
139impl<const N: usize> FixedSize for [u8; N] {
140 const SIZE: usize = N;
141}
142
143impl Write for () {
144 #[inline]
145 fn write(&self, _buf: &mut impl BufMut) {}
146}
147
148impl Read for () {
149 type Cfg = ();
150
151 #[inline]
152 fn read_cfg(_buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, Error> {
153 Ok(())
154 }
155}
156
157impl FixedSize for () {
158 const SIZE: usize = 0;
159}
160
161impl<T: Write> Write for Option<T> {
163 #[inline]
164 fn write(&self, buf: &mut impl BufMut) {
165 self.is_some().write(buf);
166 if let Some(inner) = self {
167 inner.write(buf);
168 }
169 }
170}
171
172impl<T: EncodeSize> EncodeSize for Option<T> {
173 #[inline]
174 fn encode_size(&self) -> usize {
175 self.as_ref().map_or(1, |inner| 1 + inner.encode_size())
176 }
177}
178
179impl<T: Read> Read for Option<T> {
180 type Cfg = T::Cfg;
181
182 #[inline]
183 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
184 if bool::read(buf)? {
185 Ok(Some(T::read_cfg(buf, cfg)?))
186 } else {
187 Ok(None)
188 }
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195 use crate::{Decode, DecodeExt, Encode, EncodeFixed};
196 use bytes::{Bytes, BytesMut};
197 use paste::paste;
198
199 macro_rules! impl_num_test {
201 ($type:ty, $size:expr) => {
202 paste! {
203 #[test]
204 fn [<test_ $type>]() {
205 let expected_len = core::mem::size_of::<$type>();
206 let values: [$type; 5] =
207 [0 as $type, 1 as $type, 42 as $type, <$type>::MAX, <$type>::MIN];
208 for value in values.iter() {
209 let encoded = value.encode();
210 assert_eq!(encoded.len(), expected_len);
211 let decoded = <$type>::decode(encoded).unwrap();
212 assert_eq!(*value, decoded);
213 assert_eq!(value.encode_size(), expected_len);
214
215 let fixed: [u8; $size] = value.encode_fixed();
216 assert_eq!(fixed.len(), expected_len);
217 let decoded = <$type>::decode(Bytes::copy_from_slice(&fixed)).unwrap();
218 assert_eq!(*value, decoded);
219 }
220 }
221 }
222 };
223 }
224 impl_num_test!(u8, 1);
225 impl_num_test!(u16, 2);
226 impl_num_test!(u32, 4);
227 impl_num_test!(u64, 8);
228 impl_num_test!(u128, 16);
229 impl_num_test!(i8, 1);
230 impl_num_test!(i16, 2);
231 impl_num_test!(i32, 4);
232 impl_num_test!(i64, 8);
233 impl_num_test!(i128, 16);
234 impl_num_test!(f32, 4);
235 impl_num_test!(f64, 8);
236
237 #[test]
238 fn test_endianness() {
239 let encoded = 0x0102u16.encode();
241 assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02]));
242
243 let encoded = 0x01020304u32.encode();
245 assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02, 0x03, 0x04]));
246
247 let encoded = 1.0f32.encode();
249 assert_eq!(encoded, Bytes::from_static(&[0x3F, 0x80, 0x00, 0x00])); }
251
252 #[test]
253 fn test_bool() {
254 let values = [true, false];
255 for value in values.iter() {
256 let encoded = value.encode();
257 assert_eq!(encoded.len(), 1);
258 let decoded = bool::decode(encoded).unwrap();
259 assert_eq!(*value, decoded);
260 assert_eq!(value.encode_size(), 1);
261 }
262 }
263
264 #[test]
265 fn test_usize() {
266 let values = [0usize, 1, 42, u32::MAX as usize];
267 for value in values.iter() {
268 let encoded = value.encode();
269 assert_eq!(value.encode_size(), UInt(*value as u32).encode_size());
270 let decoded = usize::decode_cfg(encoded, &(..).into()).unwrap();
271 assert_eq!(*value, decoded);
272 }
273 }
274
275 #[cfg(target_pointer_width = "64")]
276 #[test]
277 #[should_panic(expected = "encode_size: usize value is larger than u32")]
278 fn test_usize_encode_panic() {
279 let value: usize = usize::MAX;
280 let _ = value.encode();
281 }
282
283 #[test]
284 #[should_panic(expected = "write: usize value is larger than u32")]
285 fn test_usize_write_panic() {
286 let mut buf = &mut BytesMut::new();
287 let value: usize = usize::MAX;
288 value.write(&mut buf);
289 }
290
291 #[test]
292 fn test_array() {
293 let values = [1u8, 2, 3];
294 let encoded = values.encode();
295 let decoded = <[u8; 3]>::decode(encoded).unwrap();
296 assert_eq!(values, decoded);
297 }
298
299 #[test]
300 fn test_option() {
301 let option_values = [Some(42u32), None];
302 for value in option_values {
303 let encoded = value.encode();
304 let decoded = Option::<u32>::decode(encoded).unwrap();
305 assert_eq!(value, decoded);
306 }
307 }
308
309 #[test]
310 fn test_option_length() {
311 let some = Some(42u32);
312 assert_eq!(some.encode_size(), 1 + 4);
313 assert_eq!(some.encode().len(), 1 + 4);
314 let none: Option<u32> = None;
315 assert_eq!(none.encode_size(), 1);
316 assert_eq!(none.encode().len(), 1);
317 }
318
319 #[test]
320 fn test_unit() {
321 let x = ();
322 assert!(<()>::decode(x.encode()).is_ok());
324 }
325
326 #[test]
327 fn test_conformity() {
328 assert_eq!(true.encode(), &[0x01][..]);
330 assert_eq!(false.encode(), &[0x00][..]);
331
332 assert_eq!(0u8.encode(), &[0x00][..]);
334 assert_eq!(255u8.encode(), &[0xFF][..]);
335 assert_eq!(0i8.encode(), &[0x00][..]);
336 assert_eq!((-1i8).encode(), &[0xFF][..]);
337 assert_eq!(127i8.encode(), &[0x7F][..]);
338 assert_eq!((-128i8).encode(), &[0x80][..]);
339
340 assert_eq!(0u16.encode(), &[0x00, 0x00][..]);
342 assert_eq!(0xABCDu16.encode(), &[0xAB, 0xCD][..]);
343 assert_eq!(u16::MAX.encode(), &[0xFF, 0xFF][..]);
344 assert_eq!(0i16.encode(), &[0x00, 0x00][..]);
345 assert_eq!((-1i16).encode(), &[0xFF, 0xFF][..]);
346 assert_eq!(0x1234i16.encode(), &[0x12, 0x34][..]);
347
348 assert_eq!(0u32.encode(), &[0x00, 0x00, 0x00, 0x00][..]);
350 assert_eq!(0xABCDEF01u32.encode(), &[0xAB, 0xCD, 0xEF, 0x01][..]);
351 assert_eq!(u32::MAX.encode(), &[0xFF, 0xFF, 0xFF, 0xFF][..]);
352 assert_eq!(0i32.encode(), &[0x00, 0x00, 0x00, 0x00][..]);
353 assert_eq!((-1i32).encode(), &[0xFF, 0xFF, 0xFF, 0xFF][..]);
354 assert_eq!(0x12345678i32.encode(), &[0x12, 0x34, 0x56, 0x78][..]);
355
356 assert_eq!(
358 0u64.encode(),
359 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
360 );
361 assert_eq!(
362 0x0123456789ABCDEFu64.encode(),
363 &[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF][..]
364 );
365 assert_eq!(
366 u64::MAX.encode(),
367 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]
368 );
369 assert_eq!(
370 0i64.encode(),
371 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
372 );
373 assert_eq!(
374 (-1i64).encode(),
375 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]
376 );
377
378 let u128_val = 0x0123456789ABCDEF0123456789ABCDEFu128;
380 let u128_bytes = [
381 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
382 0xCD, 0xEF,
383 ];
384 assert_eq!(u128_val.encode(), &u128_bytes[..]);
385 assert_eq!(u128::MAX.encode(), &[0xFF; 16][..]);
386 assert_eq!((-1i128).encode(), &[0xFF; 16][..]);
387
388 assert_eq!(0.0f32.encode(), 0.0f32.to_be_bytes()[..]);
389 assert_eq!(1.0f32.encode(), 1.0f32.to_be_bytes()[..]);
390 assert_eq!((-1.0f32).encode(), (-1.0f32).to_be_bytes()[..]);
391 assert_eq!(f32::MAX.encode(), f32::MAX.to_be_bytes()[..]);
392 assert_eq!(f32::MIN.encode(), f32::MIN.to_be_bytes()[..]);
393 assert_eq!(f32::NAN.encode(), f32::NAN.to_be_bytes()[..]);
394 assert_eq!(f32::INFINITY.encode(), f32::INFINITY.to_be_bytes()[..]);
395 assert_eq!(
396 f32::NEG_INFINITY.encode(),
397 f32::NEG_INFINITY.to_be_bytes()[..]
398 );
399
400 assert_eq!(1.0f32.encode(), &[0x3F, 0x80, 0x00, 0x00][..]);
402 assert_eq!((-1.0f32).encode(), &[0xBF, 0x80, 0x00, 0x00][..]);
403
404 assert_eq!(0.0f64.encode(), 0.0f64.to_be_bytes()[..]);
406 assert_eq!(1.0f64.encode(), 1.0f64.to_be_bytes()[..]);
407 assert_eq!((-1.0f64).encode(), (-1.0f64).to_be_bytes()[..]);
408 assert_eq!(f64::MAX.encode(), f64::MAX.to_be_bytes()[..]);
409 assert_eq!(f64::MIN.encode(), f64::MIN.to_be_bytes()[..]);
410 assert_eq!(f64::NAN.encode(), f64::NAN.to_be_bytes()[..]);
411 assert_eq!(f64::INFINITY.encode(), f64::INFINITY.to_be_bytes()[..]);
412 assert_eq!(
413 f64::NEG_INFINITY.encode(),
414 f64::NEG_INFINITY.to_be_bytes()[..]
415 );
416 assert_eq!(
417 1.0f64.encode(),
418 &[0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
419 );
420 assert_eq!(
421 (-1.0f64).encode(),
422 &[0xBF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
423 );
424
425 assert_eq!([1, 2, 3].encode(), &[0x01, 0x02, 0x03][..]);
427 assert_eq!([].encode(), &[][..]);
428
429 assert_eq!(Some(42u32).encode(), &[0x01, 0x00, 0x00, 0x00, 0x2A][..]);
431 assert_eq!(None::<u32>.encode(), &[0][..]);
432
433 assert_eq!(0usize.encode(), &[0x00][..]);
435 assert_eq!(1usize.encode(), &[0x01][..]);
436 assert_eq!(127usize.encode(), &[0x7F][..]);
437 assert_eq!(128usize.encode(), &[0x80, 0x01][..]);
438 assert_eq!(
439 (u32::MAX as usize).encode(),
440 &[0xFF, 0xFF, 0xFF, 0xFF, 0x0F][..]
441 );
442 }
443
444 #[cfg(feature = "arbitrary")]
445 mod conformance {
446 use crate::conformance::CodecConformance;
447
448 commonware_conformance::conformance_tests! {
449 CodecConformance<u8>,
450 CodecConformance<u16>,
451 CodecConformance<u32>,
452 CodecConformance<u64>,
453 CodecConformance<u128>,
454 CodecConformance<i8>,
455 CodecConformance<i16>,
456 CodecConformance<i32>,
457 CodecConformance<i64>,
458 CodecConformance<i128>,
459 CodecConformance<f32>,
460 CodecConformance<f64>,
461 CodecConformance<bool>,
462 CodecConformance<[u8; 32]>,
463 CodecConformance<Option<u64>>,
464 CodecConformance<()>,
465 }
466 }
467}