1pub trait VarInt: Copy + Sized {
3 type Unsigned: Copy + VarIntOps;
5
6 fn to_unsigned(self) -> Self::Unsigned;
8
9 fn from_unsigned(value: Self::Unsigned) -> Self;
11
12 fn varint_size(self) -> usize;
14}
15
16pub trait VarIntOps: Copy + Sized {
18 const BITS: usize;
20
21 fn needs_another_byte(self) -> bool;
23
24 fn get_byte_with_continuation(self) -> u8;
26
27 fn get_final_byte(self) -> u8;
29
30 fn shift_right_7(self) -> Self;
32
33 fn from_byte(byte: u8, shift: usize) -> Self;
35
36 fn leading_zeros(self) -> usize;
38
39 fn bitor(self, other: Self) -> Self;
41}
42
43macro_rules! impl_varint_ops {
45 ($type:ty, $bits:expr) => {
46 impl VarIntOps for $type {
47 const BITS: usize = $bits;
48
49 #[inline]
50 fn needs_another_byte(self) -> bool {
51 self >= 0x80
52 }
53
54 #[inline]
55 fn get_byte_with_continuation(self) -> u8 {
56 (self as u8) | 0x80
57 }
58
59 #[inline]
60 fn get_final_byte(self) -> u8 {
61 self as u8
62 }
63
64 #[inline]
65 fn shift_right_7(self) -> Self {
66 self >> 7
67 }
68
69 #[inline]
70 fn from_byte(byte: u8, shift: usize) -> Self {
71 ((byte & 0x7F) as Self) << ((shift * 7) as u32)
72 }
73
74 #[inline]
75 fn leading_zeros(self) -> usize {
76 self.leading_zeros() as usize
77 }
78
79 #[inline]
80 fn bitor(self, other: Self) -> Self {
81 self | other
82 }
83 }
84 };
85}
86
87macro_rules! impl_unsigned_varint {
89 ($type:ty, $bits:expr) => {
90 impl VarInt for $type {
91 type Unsigned = Self;
92
93 #[inline]
94 fn to_unsigned(self) -> Self::Unsigned {
95 self
96 }
97
98 #[inline]
99 fn from_unsigned(value: Self::Unsigned) -> Self {
100 value
101 }
102
103 #[inline]
104 fn varint_size(self) -> usize {
105 if self == 0 {
106 return 1;
107 }
108 let bits_needed = Self::Unsigned::BITS - self.leading_zeros();
109 ((bits_needed + 6) / 7) as usize }
111 }
112 };
113}
114
115macro_rules! impl_signed_varint {
117 ($type:ty, $unsigned:ty) => {
118 impl VarInt for $type {
119 type Unsigned = $unsigned;
120
121 #[inline]
122 fn to_unsigned(self) -> Self::Unsigned {
123 self as $unsigned
124 }
125
126 #[inline]
127 fn from_unsigned(value: Self::Unsigned) -> Self {
128 value as Self
129 }
130
131 #[inline]
132 fn varint_size(self) -> usize {
133 let value = self.to_unsigned();
135
136 if value == 0 {
137 return 1;
138 }
139 let bits_needed = Self::Unsigned::BITS - value.leading_zeros();
140 ((bits_needed + 6) / 7) as usize
141 }
142 }
143 };
144}
145
146impl_varint_ops!(u8, 8);
148impl_varint_ops!(u16, 16);
149impl_varint_ops!(u32, 32);
150impl_varint_ops!(u64, 64);
151impl_varint_ops!(u128, 128);
152
153impl_unsigned_varint!(u8, 8);
154impl_unsigned_varint!(u16, 16);
155impl_unsigned_varint!(u32, 32);
156impl_unsigned_varint!(u64, 64);
157impl_unsigned_varint!(u128, 128);
158
159impl_signed_varint!(i8, u8);
160impl_signed_varint!(i16, u16);
161impl_signed_varint!(i32, u32);
162impl_signed_varint!(i64, u64);
163impl_signed_varint!(i128, u128);