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