1use crate::{Buf, EncodeSize, Error, FixedSize, MaxEncodeSize, Read, Write};
33use bytes::BufMut;
34use core::{fmt::Debug, mem::size_of};
35use sealed::{SPrim, UPrim};
36
37const BITS_PER_BYTE: usize = 8;
39
40const DATA_BITS_PER_BYTE: usize = 7;
43
44const DATA_BITS_MASK: u8 = 0x7F;
46
47const CONTINUATION_BIT_MASK: u8 = 0x80;
53
54pub const MAX_U16_VARINT_SIZE: usize =
56 (size_of::<u16>() * BITS_PER_BYTE).div_ceil(DATA_BITS_PER_BYTE);
57
58pub const MAX_U32_VARINT_SIZE: usize =
60 (size_of::<u32>() * BITS_PER_BYTE).div_ceil(DATA_BITS_PER_BYTE);
61
62pub const MAX_U64_VARINT_SIZE: usize =
64 (size_of::<u64>() * BITS_PER_BYTE).div_ceil(DATA_BITS_PER_BYTE);
65
66pub const MAX_U128_VARINT_SIZE: usize =
68 (size_of::<u128>() * BITS_PER_BYTE).div_ceil(DATA_BITS_PER_BYTE);
69
70#[derive(Debug, Clone)]
88pub struct Decoder<U: UPrim> {
89 result: U,
90 bits_read: usize,
91}
92
93impl<U: UPrim> Default for Decoder<U> {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl<U: UPrim> Decoder<U> {
100 #[inline]
102 pub fn new() -> Self {
103 Self {
104 result: U::from(0),
105 bits_read: 0,
106 }
107 }
108
109 #[inline]
116 pub fn feed(&mut self, byte: u8) -> Result<Option<U>, Error> {
117 let max_bits = U::SIZE * BITS_PER_BYTE;
118
119 if byte == 0 && self.bits_read > 0 {
124 return Err(Error::InvalidVarint(U::SIZE));
125 }
126
127 let remaining_bits = max_bits.checked_sub(self.bits_read).unwrap();
135 if remaining_bits <= DATA_BITS_PER_BYTE {
136 let relevant_bits = BITS_PER_BYTE - byte.leading_zeros() as usize;
137 if relevant_bits > remaining_bits {
138 return Err(Error::InvalidVarint(U::SIZE));
139 }
140 }
141
142 self.result |= U::from(byte & DATA_BITS_MASK) << self.bits_read;
144
145 if byte & CONTINUATION_BIT_MASK == 0 {
147 return Ok(Some(self.result));
148 }
149
150 self.bits_read += DATA_BITS_PER_BYTE;
151 Ok(None)
152 }
153}
154
155#[doc(hidden)]
156mod sealed {
157 use super::*;
158 use core::ops::{BitOrAssign, Shl, ShrAssign};
159
160 pub trait UPrim:
162 Copy
163 + From<u8>
164 + Sized
165 + FixedSize
166 + ShrAssign<usize>
167 + Shl<usize, Output = Self>
168 + BitOrAssign<Self>
169 + PartialOrd
170 + Debug
171 {
172 fn leading_zeros(self) -> u32;
174
175 fn as_u8(self) -> u8;
177 }
178
179 macro_rules! impl_uint {
181 ($type:ty) => {
182 impl UPrim for $type {
183 #[inline(always)]
184 fn leading_zeros(self) -> u32 {
185 self.leading_zeros()
186 }
187
188 #[inline(always)]
189 fn as_u8(self) -> u8 {
190 self as u8
191 }
192 }
193 };
194 }
195 impl_uint!(u16);
196 impl_uint!(u32);
197 impl_uint!(u64);
198 impl_uint!(u128);
199
200 pub trait SPrim: Copy + Sized + FixedSize + PartialOrd + Debug {
207 type UnsignedEquivalent: UPrim;
210
211 fn as_zigzag(&self) -> Self::UnsignedEquivalent;
213
214 fn un_zigzag(value: Self::UnsignedEquivalent) -> Self;
216 }
217
218 #[inline(always)]
220 const fn assert_equal_size<T: Sized, U: Sized>() {
221 assert!(
222 size_of::<T>() == size_of::<U>(),
223 "Unsigned integer must be the same size as the signed integer"
224 );
225 }
226
227 macro_rules! impl_sint {
229 ($type:ty, $utype:ty) => {
230 impl SPrim for $type {
231 type UnsignedEquivalent = $utype;
232
233 #[inline]
234 fn as_zigzag(&self) -> $utype {
235 const {
237 assert_equal_size::<$type, $utype>();
238 }
239
240 let shr = size_of::<$utype>() * 8 - 1;
241 ((self << 1) ^ (self >> shr)) as $utype
242 }
243 #[inline]
244 fn un_zigzag(value: $utype) -> Self {
245 const {
247 assert_equal_size::<$type, $utype>();
248 }
249
250 ((value >> 1) as $type) ^ (-((value & 1) as $type))
251 }
252 }
253 };
254 }
255 impl_sint!(i16, u16);
256 impl_sint!(i32, u32);
257 impl_sint!(i64, u64);
258 impl_sint!(i128, u128);
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
264pub struct UInt<U: UPrim>(pub U);
265
266macro_rules! impl_varuint_into {
269 ($($type:ty),+) => {
270 $(
271 impl From<UInt<$type>> for $type {
272 fn from(val: UInt<$type>) -> Self {
273 val.0
274 }
275 }
276 )+
277 };
278}
279impl_varuint_into!(u16, u32, u64, u128);
280
281impl<U: UPrim> Write for UInt<U> {
282 fn write(&self, buf: &mut impl BufMut) {
283 write(self.0, buf);
284 }
285}
286
287impl<U: UPrim> Read for UInt<U> {
288 type Cfg = ();
289 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
290 read(buf).map(UInt)
291 }
292}
293
294impl<U: UPrim> EncodeSize for UInt<U> {
295 fn encode_size(&self) -> usize {
296 size(self.0)
297 }
298}
299
300macro_rules! impl_varuint_max {
302 ($($type:ty => $max:expr),+ $(,)?) => {
303 $(
304 impl MaxEncodeSize for UInt<$type> {
305 const MAX_ENCODE_SIZE: usize = $max;
306 }
307 )+
308 };
309}
310impl_varuint_max!(
311 u16 => MAX_U16_VARINT_SIZE,
312 u32 => MAX_U32_VARINT_SIZE,
313 u64 => MAX_U64_VARINT_SIZE,
314 u128 => MAX_U128_VARINT_SIZE,
315);
316
317#[cfg(feature = "arbitrary")]
318impl<U: UPrim> arbitrary::Arbitrary<'_> for UInt<U>
319where
320 U: for<'a> arbitrary::Arbitrary<'a>,
321{
322 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
323 let value = U::arbitrary(u)?;
324 Ok(Self(value))
325 }
326}
327
328#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
331pub struct SInt<S: SPrim>(pub S);
332
333macro_rules! impl_varsint_into {
336 ($($type:ty),+) => {
337 $(
338 impl From<SInt<$type>> for $type {
339 fn from(val: SInt<$type>) -> Self {
340 val.0
341 }
342 }
343 )+
344 };
345}
346impl_varsint_into!(i16, i32, i64, i128);
347
348impl<S: SPrim> Write for SInt<S> {
349 fn write(&self, buf: &mut impl BufMut) {
350 write_signed::<S>(self.0, buf);
351 }
352}
353
354impl<S: SPrim> Read for SInt<S> {
355 type Cfg = ();
356 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
357 read_signed::<S>(buf).map(SInt)
358 }
359}
360
361impl<S: SPrim> EncodeSize for SInt<S> {
362 fn encode_size(&self) -> usize {
363 size_signed::<S>(self.0)
364 }
365}
366
367#[cfg(feature = "arbitrary")]
368impl<S: SPrim> arbitrary::Arbitrary<'_> for SInt<S>
369where
370 S: for<'a> arbitrary::Arbitrary<'a>,
371{
372 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
373 let value = S::arbitrary(u)?;
374 Ok(Self(value))
375 }
376}
377
378fn write<T: UPrim>(value: T, buf: &mut impl BufMut) {
380 let continuation_threshold = T::from(CONTINUATION_BIT_MASK);
381 if value < continuation_threshold {
382 buf.put_u8(value.as_u8());
385 return;
386 }
387
388 let mut bytes = [0u8; MAX_U128_VARINT_SIZE];
390 let mut len = 0;
391 let mut val = value;
392 while val >= continuation_threshold {
393 bytes[len] = val.as_u8() | CONTINUATION_BIT_MASK;
394 len += 1;
395 val >>= 7;
396 }
397 bytes[len] = val.as_u8();
398 buf.put_slice(&bytes[..=len]);
399}
400
401fn read<T: UPrim>(buf: &mut impl Buf) -> Result<T, Error> {
407 let mut byte = buf.try_get_u8().map_err(|_| Error::EndOfBuffer)?;
409 if byte & CONTINUATION_BIT_MASK == 0 {
410 return Ok(T::from(byte));
411 }
412
413 let mut decoder = Decoder::<T>::new();
416 loop {
417 if let Some(value) = decoder.feed(byte)? {
418 return Ok(value);
419 }
420 byte = buf.try_get_u8().map_err(|_| Error::EndOfBuffer)?;
421 }
422}
423
424fn size<T: UPrim>(value: T) -> usize {
426 let total_bits = size_of::<T>() * 8;
427 let leading_zeros = value.leading_zeros() as usize;
428 let data_bits = total_bits - leading_zeros;
429 usize::max(1, data_bits.div_ceil(DATA_BITS_PER_BYTE))
430}
431
432fn write_signed<S: SPrim>(value: S, buf: &mut impl BufMut) {
434 write(value.as_zigzag(), buf);
435}
436
437fn read_signed<S: SPrim>(buf: &mut impl Buf) -> Result<S, Error> {
439 Ok(S::un_zigzag(read(buf)?))
440}
441
442fn size_signed<S: SPrim>(value: S) -> usize {
444 size(value.as_zigzag())
445}
446
447#[cfg(test)]
448mod tests {
449 use super::*;
450 use crate::{Copying, DecodeExt, Encode, error::Error};
451 use bytes::{Buf as _, Bytes};
452
453 #[test]
454 fn test_fragmented_varint() {
455 let mut buf = Bytes::from_static(&[0x80]).chain(Bytes::from_static(&[0x01, 0x07]));
456 assert_eq!(read::<u32>(&mut buf).unwrap(), 128);
457 assert_eq!(read::<u32>(&mut buf).unwrap(), 7);
458 assert_eq!(buf.remaining(), 0);
459 }
460
461 #[test]
462 fn test_end_of_buffer() {
463 let mut buf: Bytes = Bytes::from_static(&[]);
464 assert!(matches!(read::<u32>(&mut buf), Err(Error::EndOfBuffer)));
465
466 let mut buf: Bytes = Bytes::from_static(&[0x80, 0x8F]);
467 assert!(matches!(read::<u32>(&mut buf), Err(Error::EndOfBuffer)));
468
469 let mut buf: Bytes = Bytes::from_static(&[0xFF, 0x8F]);
470 assert!(matches!(read::<u32>(&mut buf), Err(Error::EndOfBuffer)));
471 }
472
473 #[test]
474 fn test_overflow() {
475 let mut buf: Bytes = Bytes::from_static(&[0xFF, 0xFF, 0xFF, 0xFF, 0x0F]);
476 assert_eq!(read::<u32>(&mut buf).unwrap(), u32::MAX);
477
478 let mut buf: Bytes = Bytes::from_static(&[0xFF, 0xFF, 0xFF, 0xFF, 0x1F]);
479 assert!(matches!(
480 read::<u32>(&mut buf),
481 Err(Error::InvalidVarint(u32::SIZE))
482 ));
483
484 let mut buf =
485 Bytes::from_static(&[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02]);
486 assert!(matches!(
487 read::<u64>(&mut buf),
488 Err(Error::InvalidVarint(u64::SIZE))
489 ));
490 }
491
492 #[test]
493 fn test_overcontinuation() {
494 let mut buf: Bytes = Bytes::from_static(&[0x80, 0x80, 0x80, 0x80, 0x80]);
495 let result = read::<u32>(&mut buf);
496 assert!(matches!(result, Err(Error::InvalidVarint(u32::SIZE))));
497 }
498
499 #[test]
500 fn test_zeroed_byte() {
501 let mut buf = Bytes::from_static(&[0xFF, 0x00]);
502 let result = read::<u64>(&mut buf);
503 assert!(matches!(result, Err(Error::InvalidVarint(u64::SIZE))));
504 }
505
506 fn varuint_round_trip<T: UPrim + TryFrom<u128>>() {
508 const CASES: &[u128] = &[
509 0,
510 1,
511 127,
512 128,
513 129,
514 0xFF,
515 0x100,
516 0x3FFF,
517 0x4000,
518 0x1_FFFF,
519 0xFF_FFFF,
520 0x1_FF_FF_FF_FF,
521 0xFF_FF_FF_FF_FF_FF,
522 0x1_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF,
523 u16::MAX as u128,
524 u32::MAX as u128,
525 u64::MAX as u128,
526 u128::MAX,
527 ];
528
529 for &raw in CASES {
530 let Ok(value) = raw.try_into() else { continue };
532 let value: T = value;
533
534 let mut buf = Vec::new();
536 write(value, &mut buf);
537 assert_eq!(buf.len(), size(value));
538
539 let mut slice = Copying(&buf);
541 let decoded: T = read(&mut slice).unwrap();
542 assert_eq!(decoded, value);
543 assert!(slice.0.is_empty());
544
545 let encoded = UInt(value).encode();
547 assert_eq!(UInt::<T>::decode(encoded).unwrap(), UInt(value));
548 }
549 }
550
551 #[test]
552 fn test_varuint() {
553 varuint_round_trip::<u16>();
554 varuint_round_trip::<u32>();
555 varuint_round_trip::<u64>();
556 varuint_round_trip::<u128>();
557 }
558
559 fn varsint_round_trip<T: SPrim + TryFrom<i128>>() {
560 const CASES: &[i128] = &[
561 0,
562 1,
563 -1,
564 2,
565 -2,
566 127,
567 -127,
568 128,
569 -128,
570 129,
571 -129,
572 0x7FFFFFFF,
573 -0x7FFFFFFF,
574 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
575 -0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
576 i16::MIN as i128,
577 i16::MAX as i128,
578 i32::MIN as i128,
579 i32::MAX as i128,
580 i64::MIN as i128,
581 i64::MAX as i128,
582 ];
583
584 for &raw in CASES {
585 let Ok(value) = raw.try_into() else { continue };
587 let value: T = value;
588
589 let mut buf = Vec::new();
591 write_signed(value, &mut buf);
592 assert_eq!(buf.len(), size_signed(value));
593
594 let mut slice = Copying(&buf);
596 let decoded: T = read_signed(&mut slice).unwrap();
597 assert_eq!(decoded, value);
598 assert!(slice.0.is_empty());
599
600 let encoded = SInt(value).encode();
602 assert_eq!(SInt::<T>::decode(encoded).unwrap(), SInt(value));
603 }
604 }
605
606 #[test]
607 fn test_varsint() {
608 varsint_round_trip::<i16>();
609 varsint_round_trip::<i32>();
610 varsint_round_trip::<i64>();
611 varsint_round_trip::<i128>();
612 }
613
614 #[test]
615 fn test_varuint_into() {
616 let v32: u32 = 0x1_FFFF;
617 let out32: u32 = UInt(v32).into();
618 assert_eq!(v32, out32);
619
620 let v64: u64 = 0x1_FF_FF_FF_FF;
621 let out64: u64 = UInt(v64).into();
622 assert_eq!(v64, out64);
623 }
624
625 #[test]
626 fn test_varsint_into() {
627 let s32: i32 = -123_456;
628 let out32: i32 = SInt(s32).into();
629 assert_eq!(s32, out32);
630
631 let s64: i64 = 987_654_321;
632 let out64: i64 = SInt(s64).into();
633 assert_eq!(s64, out64);
634 }
635
636 #[test]
637 fn test_conformity() {
638 assert_eq!(0usize.encode(), &[0x00][..]);
639 assert_eq!(1usize.encode(), &[0x01][..]);
640 assert_eq!(127usize.encode(), &[0x7F][..]);
641 assert_eq!(128usize.encode(), &[0x80, 0x01][..]);
642 assert_eq!(16383usize.encode(), &[0xFF, 0x7F][..]);
643 assert_eq!(16384usize.encode(), &[0x80, 0x80, 0x01][..]);
644 assert_eq!(2097151usize.encode(), &[0xFF, 0xFF, 0x7F][..]);
645 assert_eq!(2097152usize.encode(), &[0x80, 0x80, 0x80, 0x01][..]);
646 assert_eq!(
647 (u32::MAX as usize).encode(),
648 &[0xFF, 0xFF, 0xFF, 0xFF, 0x0F][..]
649 );
650 }
651
652 #[test]
653 fn test_all_u16_values() {
654 for i in 0..=u16::MAX {
656 let value = i;
657 let calculated_size = size(value);
658
659 let mut buf = Vec::new();
660 write(value, &mut buf);
661
662 assert_eq!(
663 buf.len(),
664 calculated_size,
665 "Size mismatch for u16 value {value}",
666 );
667
668 let uint = UInt(value);
670 assert_eq!(
671 uint.encode_size(),
672 buf.len(),
673 "UInt encode_size mismatch for value {value}",
674 );
675 }
676 }
677
678 #[test]
679 fn test_all_i16_values() {
680 for i in i16::MIN..=i16::MAX {
682 let value = i;
683 let calculated_size = size_signed(value);
684
685 let mut buf = Vec::new();
686 write_signed(value, &mut buf);
687
688 assert_eq!(
689 buf.len(),
690 calculated_size,
691 "Size mismatch for i16 value {value}",
692 );
693
694 let sint = SInt(value);
696 assert_eq!(
697 sint.encode_size(),
698 buf.len(),
699 "SInt encode_size mismatch for value {value}",
700 );
701
702 let mut slice = Copying(&buf);
704 let decoded: i16 = read_signed(&mut slice).unwrap();
705 assert_eq!(decoded, value, "Decode mismatch for value {value}");
706 assert!(
707 slice.0.is_empty(),
708 "Buffer not fully consumed for value {value}",
709 );
710 }
711 }
712
713 #[test]
714 fn test_exact_bit_boundaries() {
715 fn test_exact_bits<T: UPrim + TryFrom<u128> + core::fmt::Display>() {
717 for bits in 1..=128 {
718 let val = if bits == 128 {
721 u128::MAX
722 } else {
723 (1u128 << bits) - 1
724 };
725 let Ok(value) = T::try_from(val) else {
726 continue;
727 };
728
729 let expected_size = (bits as usize).div_ceil(DATA_BITS_PER_BYTE);
731 let calculated_size = size(value);
732 assert_eq!(
733 calculated_size, expected_size,
734 "Size calculation wrong for {val} with {bits} bits",
735 );
736
737 let mut buf = Vec::new();
739 write(value, &mut buf);
740 assert_eq!(
741 buf.len(),
742 expected_size,
743 "Encoded size wrong for {val} with {bits} bits",
744 );
745 }
746 }
747
748 test_exact_bits::<u16>();
749 test_exact_bits::<u32>();
750 test_exact_bits::<u64>();
751 test_exact_bits::<u128>();
752 }
753
754 #[test]
755 fn test_single_bit_boundaries() {
756 fn test_single_bits<T: UPrim + TryFrom<u128> + core::fmt::Display>() {
758 for bit_pos in 0..128 {
759 let val = 1u128 << bit_pos;
761 let Ok(value) = T::try_from(val) else {
762 continue;
763 };
764
765 let expected_size = ((bit_pos + 1) as usize).div_ceil(DATA_BITS_PER_BYTE);
767 let calculated_size = size(value);
768 assert_eq!(
769 calculated_size, expected_size,
770 "Size wrong for 1<<{bit_pos} = {val}",
771 );
772
773 let mut buf = Vec::new();
775 write(value, &mut buf);
776 assert_eq!(
777 buf.len(),
778 expected_size,
779 "Encoded size wrong for 1<<{bit_pos} = {val}",
780 );
781 }
782 }
783
784 test_single_bits::<u16>();
785 test_single_bits::<u32>();
786 test_single_bits::<u64>();
787 test_single_bits::<u128>();
788 }
789
790 #[test]
791 fn test_max_varint_size_constants() {
792 let mut buf = Vec::new();
793
794 write(u16::MAX, &mut buf);
795 assert_eq!(buf.len(), MAX_U16_VARINT_SIZE);
796 assert_eq!(buf.len(), UInt::<u16>::MAX_ENCODE_SIZE);
797 buf.clear();
798
799 write(u32::MAX, &mut buf);
800 assert_eq!(buf.len(), MAX_U32_VARINT_SIZE);
801 assert_eq!(buf.len(), UInt::<u32>::MAX_ENCODE_SIZE);
802 buf.clear();
803
804 write(u64::MAX, &mut buf);
805 assert_eq!(buf.len(), MAX_U64_VARINT_SIZE);
806 assert_eq!(buf.len(), UInt::<u64>::MAX_ENCODE_SIZE);
807 buf.clear();
808
809 write(u128::MAX, &mut buf);
810 assert_eq!(buf.len(), MAX_U128_VARINT_SIZE);
811 assert_eq!(buf.len(), UInt::<u128>::MAX_ENCODE_SIZE);
812 }
813
814 #[cfg(feature = "arbitrary")]
815 mod conformance {
816 use super::*;
817 use crate::conformance::CodecConformance;
818
819 commonware_conformance::conformance_tests! {
820 CodecConformance<UInt<u16>>,
821 CodecConformance<UInt<u32>>,
822 CodecConformance<UInt<u64>>,
823 CodecConformance<UInt<u128>>,
824 CodecConformance<SInt<i16>>,
825 CodecConformance<SInt<i32>>,
826 CodecConformance<SInt<i64>>,
827 CodecConformance<SInt<i128>>,
828 }
829 }
830}