bin_layout/
len.rs

1//! ### Variable-Length Integer Encoding
2//!
3//! This encoding ensures that smaller integer values need fewer bytes to encode. Support types are `L2` and `L3`, both are encoded in little endian.
4//!
5//! By default, `L3` (u22) is used to encode length (integer) for record. But you override it by setting `L2` (u15) in features flag.
6//!  
7//! Encoding algorithm is very straightforward, reserving one or two most significant bits of the first byte to encode rest of the length.
8//!
9//! #### L2
10//!
11//! |  MSB  | Length | Usable Bits | Range    |
12//! | :---: | :----: | :---------: | :------- |
13//! |   0   |   1    |      7      | 0..127   |
14//! |   1   |   2    |     15      | 0..32767 |
15//!
16//! #### L3
17//!
18//! |  MSB  | Length | Usable Bits | Range      |
19//! | :---: | :----: | :---------: | :--------- |
20//! |   0   |   1    |      7      | 0..127     |
21//! |  10   |   2    |     14      | 0..16383   |
22//! |  11   |   3    |     22      | 0..4194303 |
23//!
24//!  
25//! For example, Binary representation of `0x_C0DE` is `0x_11_00000011_011110`
26//!  
27//! `L3(0x_C0DE)` is encoded in 3 bytes:
28//!  
29//! ```yml
30//! 1st byte: 11_011110      # MSB is 11, so read next 2 bytes
31//! 2nd byte:        11
32//! 3rd byte:        11
33//! ```
34//!
35//! Another example, `L3(107)` is encoded in just 1 byte:
36//!
37//! ```yml
38//! 1st byte: 0_1101011      # MSB is 0, So we don't have to read extra bytes.
39//! ```
40
41use crate::*;
42use std::{
43    convert::{Infallible, TryFrom},
44    fmt,
45};
46
47#[cfg(feature = "L2")]
48pub use L2 as Len;
49#[cfg(not(feature = "L2"))]
50pub use L3 as Len;
51
52macro_rules! def {
53    [$name:ident($ty:ty), BITS: $BITS:literal, TryFromErr: $err: ty, $encoder:item, $decoder:item] => {
54        #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
55        pub struct $name(pub $ty);
56        impl $name {
57            pub const MAX: $name = $name((1 << $BITS) - 1);
58            pub const BITS: u32 = $BITS;
59        }
60        impl Encoder for $name { #[inline] $encoder }
61        impl Decoder<'_> for $name { #[inline] $decoder }
62        impl TryFrom<usize> for $name {
63            type Error = String;
64            #[inline] fn try_from(num: usize) -> std::result::Result<Self, Self::Error> {
65                if num > (1 << $BITS) - 1 {
66                    Err(format!("Max payload length is {}, But got {num}", Self::MAX.0))
67                } else {
68                    Ok(Self(num as $ty))
69                }
70            }
71        }
72        impl TryFrom<$name> for usize {
73            type Error = $err;
74            #[inline] fn try_from(num: $name) -> std::result::Result<Self, Self::Error> { TryFrom::try_from(num.0) }
75        }
76        impl From<$ty> for $name { fn from(num: $ty) -> Self { Self(num) } }
77        impl fmt::Display for $name {
78            #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
79        }
80        impl core::ops::Deref for $name {
81            type Target = $ty;
82            #[inline] fn deref(&self) -> &Self::Target { &self.0 }
83        }
84        impl core::ops::DerefMut for $name {
85            #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
86        }
87    };
88}
89
90def!(
91    L2(u16),
92    BITS: 15,
93    TryFromErr: Infallible,
94    fn encoder(&self, c: &mut impl Write) -> io::Result<()> {
95        let num = self.0;
96        let b1 = num as u8;
97        // No MSB is set, Bcs `num` is less then `128`
98        if num < 128 { c.write_all(&[b1]) }
99        else {
100            debug_assert!(num <= 0x7FFF);
101            let b1 = 0x80 | b1; // 7 bits with MSB is set.
102            let b2 = (num >> 7) as u8; // next 8 bits
103            c.write_all(&[b1, b2])
104        }
105    },
106    fn decoder(c: &mut &[u8]) -> Result<Self> {
107        let mut num = u8::decoder(c)? as u16;
108        // if MSB is set, read another byte.
109        if num >> 7 == 1 {
110            let snd = u8::decoder(c)? as u16;
111            num = (num & 0x7F) | snd << 7; // num <- add 8 bits
112        }
113        Ok(Self(num))
114    }
115);
116
117def!(
118    L3(u32),
119    BITS: 22,
120    TryFromErr: std::num::TryFromIntError,
121    fn encoder(&self, c: &mut impl Write) -> io::Result<()> {
122        let num = self.0;
123        let b1 = num as u8;
124        if num < 128 { c.write_all(&[b1]) }
125        else {
126            let b1 = b1 & 0x3F; // read last 6 bits
127            let b2 = (num >> 6) as u8; // next 8 bits
128            if num < 0x4000 {
129                // set first 2 bits  of `b1` to `10`
130                c.write_all(&[0x80 | b1, b2])
131            }
132            else {
133                debug_assert!(num <= 0x3FFFFF);
134                let b3 = (num >> 14) as u8; // next 8 bits
135                // set first 2 bits  of `b1` to `11`
136                c.write_all(&[0xC0 | b1, b2, b3])
137            }
138        }
139    },
140    fn decoder(c: &mut &[u8]) -> Result<Self> {
141        let num = u8::decoder(c)? as u32;
142        // if 1st bit is `0`
143        let num = if num >> 7 == 0 { num }
144        // and 2nd bit is `0`
145        else if num >> 6 == 2 {
146            let b2 = u8::decoder(c)? as u32;
147            (num & 0x3F) | b2 << 6
148        } else  {
149            // At this point, only possible first 2 bits are `11`
150            let [b2, b3] = <&[u8; 2]>::decoder(c)?;
151            (num & 0x3F)  // get last 6 bits
152            | (*b2 as u32) << 6     // add 8 bits from 2nd byte
153            | (*b3 as u32) << 14    // add 8 bits from 3rd byte
154        };
155        Ok(Self(num))
156    }
157);
158
159#[cfg(test)]
160mod tests {
161    use super::*;
162
163    macro_rules! assert_len {
164        [$len: expr, $expect: expr] => {
165            let bytes = $len.encode();
166            assert_eq!(bytes, $expect);
167            assert_eq!($len, Decoder::decode(&bytes).unwrap());
168        };
169    }
170
171    #[test]
172    fn l2() {
173        assert_len!(L2(0), [0]);
174        assert_len!(L2(127), [127]);
175
176        assert_len!(L2(128), [128, 1]);
177        assert_len!(L2(32767), [255, 255]);
178    }
179
180    #[test]
181    fn l3() {
182        assert_len!(L3(0), [0]);
183        assert_len!(L3(127), [127]);
184
185        assert_len!(L3(128), [128, 2]);
186        assert_len!(L3(16383), [191, 255]);
187
188        assert_len!(L3(16384), [192, 0, 1]);
189        assert_len!(L3(4194303), [255, 255, 255]);
190    }
191}