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}