alkahest/
vlq.rs

1use crate::{
2    buffer::Buffer,
3    deserialize::{Deserialize, DeserializeError, Deserializer},
4    formula::Formula,
5    serialize::{write_bytes, Serialize, Sizes},
6};
7
8/// Formula for Variable-Length Quantity encoding.
9///
10/// If bit 8 is set then bits 0-6 contain length of the value in bytes.
11/// Otherwise bits 4-7 contain the length of the value in bytes,
12/// and bits 0-3 contain first 4 bits of the encoded value.
13///
14/// If bit 8 is set then bit 7 must be unset. It is reserved for
15/// chaining value length to the next byte for big integers from
16/// 2^ 63 and larger.
17///
18///
19/// # Examples
20///
21/// Type of the value can be different than the type of the serialized value.
22///
23/// ```
24/// # use alkahest::*;
25///
26/// let mut buffer = [0u8; 1024];
27/// let (size, root) = serialize::<Vlq, u8>(0, &mut buffer).unwrap();
28/// let value = deserialize_with_size::<Vlq, u16>(&buffer[..size], root).unwrap();
29/// assert_eq!(0, value);
30/// ```
31///
32/// It may be smaller, unlike fixed size formulas.
33/// The only requirement is that the target type is large enough
34/// to hold the value.
35///
36/// ```
37/// # use alkahest::*;
38///
39/// let mut buffer = [0u8; 1024];
40///
41/// let (size, root) = serialize::<Vlq, u32>(8573, &mut buffer).unwrap();
42/// let value = deserialize_with_size::<Vlq, u16>(&buffer[..size], root).unwrap();
43/// assert_eq!(8573, value);
44/// ```
45///
46/// If deserialize type can't fit the value, an error is returned.
47///
48/// ```
49/// # use alkahest::*;
50///
51/// let mut buffer = [0u8; 1024];
52///
53/// let (size, root) = serialize::<Vlq, u32>(70000, &mut buffer).unwrap();
54/// let err = deserialize_with_size::<Vlq, u16>(&buffer[..size], root).unwrap_err();
55/// assert!(matches!(err, DeserializeError::IntegerOverflow));
56/// ```
57pub struct Vlq;
58
59impl Formula for Vlq {
60    const MAX_STACK_SIZE: Option<usize> = None;
61    const EXACT_SIZE: bool = false;
62    const HEAPLESS: bool = true;
63}
64
65trait VlqType: Copy {
66    fn less_eq(&self, byte: u8) -> bool;
67
68    /// Shifts the value right by 8 bits, and assigns the result to `self`.
69    fn shr_byte_assign(&mut self) -> u8;
70
71    /// Returns new value with the least significant byte set to `lsb`.
72    fn from_lsb(lsb: u8) -> Self;
73
74    /// Shifts left by 8 bits and sets the least significant byte to `lsb`.
75    /// Returns false if shift would overflow.
76    fn shl_byte_set(&mut self, lsb: u8) -> bool;
77}
78
79impl VlqType for u8 {
80    #[inline(always)]
81    fn less_eq(&self, byte: u8) -> bool {
82        *self <= byte
83    }
84
85    #[inline(always)]
86    fn shr_byte_assign(&mut self) -> u8 {
87        core::mem::replace(self, 0)
88    }
89
90    #[inline(always)]
91    fn from_lsb(lsb: u8) -> Self {
92        lsb
93    }
94
95    #[inline(always)]
96    fn shl_byte_set(&mut self, lsb: u8) -> bool {
97        if *self > 0 {
98            return false;
99        }
100        *self = lsb;
101        true
102    }
103}
104
105macro_rules! impl_vlq_int {
106    ($($a:ident)*) => {
107        $(
108            impl VlqType for $a {
109                #[inline(always)]
110                fn less_eq(&self, byte: u8) -> bool {
111                    *self <= $a::from(byte)
112                }
113
114                #[inline(always)]
115                fn shr_byte_assign(&mut self) -> u8 {
116                    let lsb = *self as u8;
117                    *self >>= 8;
118                    lsb
119                }
120
121                #[inline(always)]
122                fn from_lsb(lsb: u8) -> Self {
123                    $a::from(lsb)
124                }
125
126                #[inline(always)]
127                fn shl_byte_set(&mut self, lsb: u8) -> bool {
128                    if self.leading_zeros() < 8 {
129                        return false;
130                    }
131                    *self <<= 8;
132                    *self |= $a::from(lsb);
133                    true
134                }
135            }
136        )*
137    };
138}
139
140impl_vlq_int!(u16 u32 u64 u128 usize);
141
142impl<T> Serialize<Vlq> for T
143where
144    T: VlqType,
145{
146    #[inline(always)]
147    fn size_hint(&self) -> Option<Sizes> {
148        Some(size_hint(*self))
149    }
150
151    #[inline(always)]
152    fn serialize<B>(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
153    where
154        B: Buffer,
155    {
156        serialize(self, sizes, buffer)
157    }
158}
159
160impl<'de, T> Deserialize<'de, Vlq> for T
161where
162    T: VlqType,
163{
164    #[inline(always)]
165    fn deserialize(de: Deserializer<'de>) -> Result<Self, DeserializeError> {
166        deserialize(de)
167    }
168
169    #[inline(always)]
170    fn deserialize_in_place(
171        &mut self,
172        deserializer: Deserializer<'de>,
173    ) -> Result<(), DeserializeError> {
174        *self = deserialize(deserializer)?;
175        Ok(())
176    }
177}
178
179#[inline(always)]
180fn size_hint<T>(mut value: T) -> Sizes
181where
182    T: VlqType,
183{
184    let mut tail = 0;
185    loop {
186        if tail >= 8 {
187            if value.less_eq(0) {
188                break;
189            }
190        } else if value.less_eq(0xF) {
191            break;
192        }
193
194        if tail == 63 {
195            unimplemented!(
196                "Encoding for values that require more than 63 bytes is not implemented yet."
197            )
198        }
199        tail += 1;
200        value.shr_byte_assign();
201    }
202    Sizes::with_stack(tail + 1)
203}
204
205#[inline(always)]
206fn serialize<T, B>(mut value: T, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
207where
208    T: VlqType,
209    B: Buffer,
210{
211    let mut bytes = [0u8; 64];
212    let mut tail = 0;
213
214    loop {
215        if tail >= 8 {
216            if value.less_eq(0) {
217                bytes[usize::from(tail)] = 0x80 | tail;
218                return write_bytes(&bytes[..=usize::from(tail)], sizes, buffer);
219            }
220        } else if value.less_eq(0xF) {
221            let lsb = value.shr_byte_assign();
222            bytes[usize::from(tail)] = (tail << 4) | lsb;
223            return write_bytes(&bytes[..=usize::from(tail)], sizes, buffer);
224        }
225
226        if tail == 63 {
227            unimplemented!(
228                "Encoding for values that require more than 63 bytes is not implemented yet."
229            )
230        }
231
232        let lsb = value.shr_byte_assign();
233        bytes[usize::from(tail)] = lsb;
234        tail += 1;
235    }
236}
237
238#[inline(always)]
239fn deserialize<T>(mut de: Deserializer) -> Result<T, DeserializeError>
240where
241    T: VlqType,
242{
243    let header = de.read_bytes(1)?[0];
244
245    let (tail, msb) = match header {
246        0x00..=0x7F => (header >> 4, header & 0x0F),
247        0x80..=0xBF => (header & 0x3F, 0),
248        0xC0..=0xFF => {
249            unimplemented!(
250                "Decoding for values that require more than 63 bytes is not implemented yet."
251            )
252        }
253    };
254
255    let mut value = T::from_lsb(msb);
256
257    let tail = de.read_bytes(usize::from(tail))?;
258
259    for byte in tail.iter().rev() {
260        if !value.shl_byte_set(*byte) {
261            return Err(DeserializeError::IntegerOverflow);
262        }
263    }
264
265    Ok(value)
266}