musli/int/
continuation.rs

1//! A variable-length 7-bit encoder where each bit indicates if there is a
2//! continuation of the sequence or not.
3
4use crate::int;
5use crate::reader::Reader;
6use crate::writer::Writer;
7use crate::Context;
8
9const MASK_BYTE: u8 = 0b0111_1111;
10const CONT_BYTE: u8 = 0b1000_0000;
11
12/// Decode the given length using variable int encoding.
13#[inline(never)]
14pub fn decode<'de, C, R, T>(cx: &C, mut r: R) -> Result<T, C::Error>
15where
16    C: ?Sized + Context,
17    R: Reader<'de>,
18    T: int::Unsigned,
19{
20    let mut b = r.read_byte(cx)?;
21
22    if b & CONT_BYTE == 0 {
23        return Ok(T::from_byte(b));
24    }
25
26    let mut value = T::from_byte(b & MASK_BYTE);
27    let mut shift = 0u32;
28
29    while b & CONT_BYTE == CONT_BYTE {
30        shift += 7;
31
32        if shift >= T::BITS {
33            return Err(cx.message("Bits overflow"));
34        }
35
36        b = r.read_byte(cx)?;
37        value = value.wrapping_add(T::from_byte(b & MASK_BYTE).wrapping_shl(shift));
38    }
39
40    Ok(value)
41}
42
43/// Encode the given length using variable length encoding.
44#[inline(never)]
45pub fn encode<C, W, T>(cx: &C, mut w: W, mut value: T) -> Result<(), C::Error>
46where
47    C: ?Sized + Context,
48    W: Writer,
49    T: int::Unsigned,
50{
51    let mut b = value.as_byte();
52
53    if value < T::from_byte(CONT_BYTE) {
54        w.write_byte(cx, b)?;
55        return Ok(());
56    }
57
58    loop {
59        value = value >> 7;
60
61        if value.is_zero() {
62            w.write_byte(cx, b & MASK_BYTE)?;
63            break;
64        }
65
66        w.write_byte(cx, b | CONT_BYTE)?;
67        b = value.as_byte();
68    }
69
70    Ok(())
71}