1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! ### Variable-Length Integer Encoding
//!
//! This encoding ensures that smaller integer values need fewer bytes to encode. Support types are `L2` and `L3`.
//!
//! By default, `L2` (u15) is used to encode length (integer) for record. But you override it by setting `L3` (u22) in features flag.
//!  
//! Encoding algorithm is very straightforward, reserving one or two most significant bits of the first byte to encode rest of the length.
//!
//! #### L2
//!
//! |  MSB  | Length | Usable Bits | Range    |
//! | :---: | :----: | :---------: | :------- |
//! |   0   |   1    |      7      | 0..127   |
//! |   1   |   2    |     15      | 0..32767 |
//!
//!
//! #### L3
//!
//! |  MSB  | Length | Usable Bits | Range      |
//! | :---: | :----: | :---------: | :--------- |
//! |   0   |   1    |      7      | 0..127     |
//! |  10   |   2    |     14      | 0..16383   |
//! |  11   |   3    |     22      | 0..4194303 |
//!
//!  
//! For example, Binary representation of `0x_C0DE` is `0x_11_00000011_011110`
//!  
//! `L3(0x_C0DE)` is encoded in 3 bytes:
//!  
//! ```text
//! 1st byte: 11_011110      # MSB is 11, so read next 2 bytes
//! 2nd byte:        11
//! 3rd byte:        11
//! ```
//!
//! Another example, `L3(107)` is encoded in just 1 byte:
//!
//! ```text
//! 1st byte: 0_1101011      # MSB is 0, So we don't have to read another bytes.
//! ```
use crate::*;

#[cfg(not(feature = "L3"))]
pub use L2 as Lencoder;
#[cfg(feature = "L3")]
pub use L3 as Lencoder;


macro_rules! def {
    [$name:ident($ty:ty), LenSize: $size:literal, MAX: $MAX:literal, $encoder:item, $decoder:item] => {
        #[derive(Default, Debug, Clone, Copy)]
        pub struct $name(pub $ty);
        impl $name { pub const MAX: $ty = $MAX; }

        impl Encoder for $name {
            const SIZE: usize = $size;
            #[inline] $encoder
        }
        impl<E: Error> Decoder<'_, E> for $name { #[inline] $decoder }
        impl From<$ty> for $name { fn from(num: $ty) -> Self { Self(num) } }
        impl core::ops::Deref for $name {
            type Target = $ty;
            fn deref(&self) -> &Self::Target { &self.0 }
        }
        impl core::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
        }
    };
}   

def!(
    L2(u16),
    LenSize: 2,
    MAX: 0x7FFF,
    fn encoder(self, c: &mut Cursor<impl Bytes>) {
        let num = self.0;
        let b1 = num as u8;
        if num < 128 {
            b1.encoder(c); // No MSB is set, Bcs `num` is less then `128`
        } else {
            debug_assert!(num <= Self::MAX);
            let b1 = 0x80 | b1; // 7 bits with MSB is set.
            let b2 = (num >> 7) as u8; // next 8 bits
            c.write_slice([b1, b2]);
        }
    },
    fn decoder(c: &mut Cursor<&[u8]>) -> Result<Self, E> {
        let mut num = u8::decoder(c)? as u16;
        // if MSB is set, read another byte.
        if num >> 7 == 1 {
            let snd = u8::decoder(c)? as u16;
            num = (num & 0x7F) | snd << 7; // num <- add 8 bits
        }
        Ok(Self(num))
    }
);
def!(
    L3(u32),
    LenSize: 3,
    MAX: 0x3FFFFF,
    fn encoder(self, c: &mut Cursor<impl Bytes>) {
        let num = self.0;
        let b1 = num as u8;
        if num < 128 {
            b1.encoder(c);
        }
        else {
            let b1 = b1 & 0x3F; // read last 6 bits
            let b2 = (num >> 6) as u8; // next 8 bits
            if num < 0x4000 {
                // set first 2 bits  of `b1` to `10`
                c.write_slice([0x80 | b1, b2]);
            }
            else {
                debug_assert!(num <= Self::MAX);
                let b3 = (num >> 14) as u8; // next 8 bits
                // set first 2 bits  of `b1` to `11`
                c.write_slice([0xC0 | b1, b2, b3]);
            }
        }
    },
    fn decoder(c: &mut Cursor<& [u8]>) -> Result<Self, E> {
        let num = u8::decoder(c)? as u32;
        // if 1st bit is `0`
        let num = if num >> 7 == 0 { num }
        // and 2nd bit is `0`
        else if num >> 6 == 2 {
            let b2 = u8::decoder(c)? as u32;
            (num & 0x3F) | b2 << 6
        } else  {
            // At this point, only possible first 2 bits are `11`
            let b2 = *c.data.get(c.offset).ok_or_else(E::insufficient_bytes)? as u32;
            let b3 = *c.data.get(c.offset + 1).ok_or_else(E::insufficient_bytes)? as u32;
            c.offset += 2;

            (num & 0x3F)  // get last 6 bits
            | b2 << 6     // add 8 bits from 2nd byte
            | b3 << 14    // add 8 bits from 3rd byte
        };
        Ok(Self(num))
    }
);