uvarint/decode.rs
1use crate::error::UVarintError;
2
3/// Decodes a variable-length unsigned 32-bit integer from a byte slice.
4///
5/// # Varint Encoding Format
6///
7/// Varints use the lower 7 bits of each byte for data, and the most significant
8/// bit (MSB) as a continuation flag:
9/// - MSB = 1: More bytes follow
10/// - MSB = 0: This is the last byte
11///
12/// Bytes are stored in little-endian order (least significant bits first).
13///
14/// # Examples
15///
16/// ```
17/// use uvarint::decode::decode_u32;
18///
19/// // Two bytes: 300
20/// // 300 = 0b1_0010_1100 (needs 9 bits)
21/// // Split into 7-bit chunks: [010_1100] [0000_010]
22/// // Reverse order & add continuation bits: [1010_1100] [0000_0010]
23/// assert_eq!(decode_u32(&[0xAC, 0x02]).unwrap(), (2, 300));
24/// ```
25///
26/// # Step-by-Step Decoding Process
27///
28/// For the value 300 encoded as `[0xAC, 0x02]`:
29///
30/// **Byte 1: 0xAC (0b1010_1100)**
31/// ```text
32/// data_bits = 0xAC & 0x7F // Mask out MSB
33/// = 0b1010_1100 & 0b0111_1111
34/// = 0b0010_1100 (44 in decimal)
35/// value = 44 << 0 = 44
36/// continuation = 0xAC & 0x80 // Check MSB
37/// = 0b1000_0000 (non-zero, continue!)
38/// ```
39///
40/// **Byte 2: 0x02 (0b0000_0010)**
41/// ```text
42/// data_bits = 0x02 & 0x7F
43/// = 0b0000_0010 (2 in decimal)
44/// value = 44 | (2 << 7) // Shift by 7 bits for each byte
45/// = 44 | 256
46/// = 300
47/// continuation = 0x02 & 0x80
48/// = 0 (MSB is 0, done!)
49/// ```
50pub fn decode_u32(data: &[u8]) -> Result<(usize, u32), UVarintError> {
51 let mut value: u32 = 0;
52
53 for (i, &byte) in data.iter().take(5).enumerate() {
54 let data_bits = (byte & 0x7F) as u32;
55
56 value = value
57 .checked_add(
58 data_bits
59 .checked_shl(i as u32 * 7)
60 .ok_or(UVarintError::Overflow)?,
61 )
62 .ok_or(UVarintError::Overflow)?;
63
64 if (byte & 0x80) == 0 {
65 return Ok((i + 1, value));
66 }
67 }
68
69 Err(UVarintError::Incomplete)
70}
71
72/// Decodes a variable-length unsigned 64-bit integer from a byte slice.
73///
74/// # Varint Encoding Format
75///
76/// Varints use the lower 7 bits of each byte for data, and the most significant
77/// bit (MSB) as a continuation flag:
78/// - MSB = 1: More bytes follow
79/// - MSB = 0: This is the last byte
80///
81/// Bytes are stored in little-endian order (least significant bits first).
82///
83/// # Examples
84///
85/// ```
86/// use uvarint::decode::decode_u64;
87///
88/// // Two bytes: 300
89/// // 300 = 0b1_0010_1100 (needs 9 bits)
90/// // Split into 7-bit chunks: [010_1100] [0000_010]
91/// // Reverse order & add continuation bits: [1010_1100] [0000_0010]
92/// assert_eq!(decode_u64(&[0xAC, 0x02]).unwrap(), (2, 300));
93/// ```
94///
95/// # Step-by-Step Decoding Process
96///
97/// For the value 300 encoded as `[0xAC, 0x02]`:
98///
99/// **Byte 1: 0xAC (0b1010_1100)**
100/// ```text
101/// data_bits = 0xAC & 0x7F // Mask out MSB
102/// = 0b1010_1100 & 0b0111_1111
103/// = 0b0010_1100 (44 in decimal)
104/// value = 44 << 0 = 44
105/// continuation = 0xAC & 0x80 // Check MSB
106/// = 0b1000_0000 (non-zero, continue!)
107/// ```
108///
109/// **Byte 2: 0x02 (0b0000_0010)**
110/// ```text
111/// data_bits = 0x02 & 0x7F
112/// = 0b0000_0010 (2 in decimal)
113/// value = 44 | (2 << 7) // Shift by 7 bits for each byte
114/// = 44 | 256
115/// = 300
116/// continuation = 0x02 & 0x80
117/// = 0 (MSB is 0, done!)
118/// ```
119pub fn decode_u64(data: &[u8]) -> Result<(usize, u64), UVarintError> {
120 let mut value: u64 = 0;
121
122 for (i, &byte) in data.iter().take(10).enumerate() {
123 let data_bits = (byte & 0x7F) as u64;
124
125 value = value
126 .checked_add(
127 data_bits
128 .checked_shl(i as u32 * 7)
129 .ok_or(UVarintError::Overflow)?,
130 )
131 .ok_or(UVarintError::Overflow)?;
132
133 if (byte & 0x80) == 0 {
134 return Ok((i + 1, value));
135 }
136 }
137
138 Err(UVarintError::Incomplete)
139}
140
141/// Decodes a variable-length unsigned 128-bit integer from a byte slice.
142///
143/// # Varint Encoding Format
144///
145/// Varints use the lower 7 bits of each byte for data, and the most significant
146/// bit (MSB) as a continuation flag:
147/// - MSB = 1: More bytes follow
148/// - MSB = 0: This is the last byte
149///
150/// Bytes are stored in little-endian order (least significant bits first).
151///
152/// # Examples
153///
154/// ```
155/// use uvarint::decode::decode_u128;
156///
157/// // Two bytes: 300
158/// // 300 = 0b1_0010_1100 (needs 9 bits)
159/// // Split into 7-bit chunks: [010_1100] [0000_010]
160/// // Reverse order & add continuation bits: [1010_1100] [0000_0010]
161/// assert_eq!(decode_u128(&[0xAC, 0x02]).unwrap(), (2, 300));
162/// ```
163pub fn decode_u128(data: &[u8]) -> Result<(usize, u128), UVarintError> {
164 let mut value: u128 = 0;
165
166 for (i, &byte) in data.iter().take(19).enumerate() {
167 let data_bits = (byte & 0x7F) as u128;
168
169 value = value
170 .checked_add(
171 data_bits
172 .checked_shl(i as u32 * 7)
173 .ok_or(UVarintError::Overflow)?,
174 )
175 .ok_or(UVarintError::Overflow)?;
176
177 if (byte & 0x80) == 0 {
178 return Ok((i + 1, value));
179 }
180 }
181
182 Err(UVarintError::Incomplete)
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_single_byte_u32_values() {
191 assert_eq!(decode_u32(&[0x00]).unwrap(), (1, 0));
192 assert_eq!(decode_u32(&[0x01]).unwrap(), (1, 1));
193 assert_eq!(decode_u32(&[0x05]).unwrap(), (1, 5));
194 assert_eq!(decode_u32(&[0x7F]).unwrap(), (1, 127));
195 }
196
197 #[test]
198 fn test_two_byte_u32_values() {
199 assert_eq!(decode_u32(&[0x80, 0x01]).unwrap(), (2, 128));
200 assert_eq!(decode_u32(&[0xAC, 0x02]).unwrap(), (2, 300));
201 assert_eq!(decode_u32(&[0xFF, 0x7F]).unwrap(), (2, 16_383));
202 }
203
204 #[test]
205 fn test_single_byte_u64_values() {
206 assert_eq!(decode_u64(&[0x00]).unwrap(), (1, 0));
207 assert_eq!(decode_u64(&[0x01]).unwrap(), (1, 1));
208 assert_eq!(decode_u64(&[0x05]).unwrap(), (1, 5));
209 assert_eq!(decode_u64(&[0x7F]).unwrap(), (1, 127));
210 }
211
212 #[test]
213 fn test_two_byte_u64_values() {
214 assert_eq!(decode_u64(&[0x80, 0x01]).unwrap(), (2, 128));
215 assert_eq!(decode_u64(&[0xAC, 0x02]).unwrap(), (2, 300));
216 assert_eq!(decode_u64(&[0xFF, 0x7F]).unwrap(), (2, 16_383));
217 }
218
219 #[test]
220 fn test_single_byte_u128_values() {
221 assert_eq!(decode_u128(&[0x00]).unwrap(), (1, 0));
222 assert_eq!(decode_u128(&[0x01]).unwrap(), (1, 1));
223 assert_eq!(decode_u128(&[0x05]).unwrap(), (1, 5));
224 assert_eq!(decode_u128(&[0x7F]).unwrap(), (1, 127));
225 }
226
227 #[test]
228 fn test_two_byte_u128_values() {
229 // 128 = 0b1000_0000
230 // Split: [000_0000] [000_0001]
231 // Encode: [1000_0000] [0000_0001]
232 assert_eq!(decode_u128(&[0x80, 0x01]).unwrap(), (2, 128));
233
234 // 300 = 0b1_0010_1100
235 // Split: [010_1100] [000_0010]
236 // Encode: [1010_1100] [0000_0010]
237 assert_eq!(decode_u128(&[0xAC, 0x02]).unwrap(), (2, 300));
238
239 // 16,383 = 0b11_1111_1111_1111 (max 2-byte value)
240 // Split: [111_1111] [111_1111]
241 // Encode: [1111_1111] [0111_1111]
242 assert_eq!(decode_u128(&[0xFF, 0x7F]).unwrap(), (2, 16_383));
243 }
244}