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