tiny_bitstream/
bitstream.rs

1use crate::constants::*;
2use crate::errors::*;
3
4use crate::debug_test;
5
6#[derive(Default)]
7pub struct BitEstream {
8    pub(crate) bits_container: BitContainer,
9    pub(crate) stream: Vec<u8>,
10    pub(crate) bit_pos: u8,
11}
12
13pub struct BitDstream {
14    pub(crate) bits_container: BitContainer,
15    pub(crate) stream: Vec<u8>,
16    pub(crate) bits_consumed: u8,
17}
18
19pub trait BitWriter<T> {
20    fn unchecked_write(&mut self, value: T, nb_bits: u8);
21}
22
23pub trait BitReader<T> {
24    fn read(&mut self, nb_bits: u8) -> Result<T>;
25}
26
27impl BitWriter<usize> for BitEstream {
28    fn unchecked_write(&mut self, mut value: usize, nb_bits: u8) {
29        assert!(nb_bits <= usize::BITS as u8);
30        if self.bit_pos == CTNR_SIZE {
31            self.flush_bits();
32        }
33        if nb_bits + self.bit_pos <= CTNR_SIZE {
34            self.bits_container |= (value & BIT_MASK[nb_bits as usize]) << self.bit_pos;
35            self.bit_pos += nb_bits;
36            return;
37        }
38        // take the rest and flush
39        let rest = CTNR_SIZE - self.bit_pos;
40        self.bits_container |= (value & BIT_MASK[rest as usize]) << self.bit_pos;
41        self.bit_pos += rest;
42        self.flush_bits();
43        value >>= rest;
44        self.unchecked_write(value, nb_bits - rest)
45    }
46}
47
48impl BitReader<usize> for BitDstream {
49    fn read(&mut self, nb_bits: u8) -> Result<usize> {
50        assert!(usize::BITS as u8 >= nb_bits);
51        if CTNR_SIZE == self.bits_consumed {
52            // relead container if needed
53            if self.reload_container()? {
54                throw!(ReadOverflow);
55            }
56        }
57        if (CTNR_SIZE - self.bits_consumed) >= nb_bits {
58            return self.read_bits(nb_bits);
59        }
60        let rest = CTNR_SIZE - self.bits_consumed;
61        let rem = nb_bits - rest;
62        let ret = self.read_bits(rest)? << rem;
63        if self.reload_container()? {
64            throw!(ReadOverflow);
65        }
66        Ok(self.read_bits(rem)? + ret)
67    }
68}
69
70impl BitEstream {
71    /// Replace the original BIT_initCStream
72    /// Return a new BitCstream, the vector should be already allocated with a
73    /// given capacity in byte
74    pub fn new() -> Self {
75        Default::default()
76    }
77
78    /// Add since `CTNR_SIZE` bits into stream `bit_container`.
79    /// Note : does not check for register overflow !
80    #[inline]
81    pub fn add_bits<T: Into<BitContainer>>(&mut self, value: T, nb_bits: u8) -> Result<()> {
82        if nb_bits > BIT_MASK_SIZE {
83            throw!(AddBits, format!("MASK size smaller than {}", nb_bits))
84        }
85        if nb_bits + self.bit_pos > CTNR_SIZE {
86            throw!(AddBits, "Container overflow")
87        }
88        self.bits_container |= (value.into() & BIT_MASK[nb_bits as usize]) << self.bit_pos;
89        self.bit_pos += nb_bits;
90        Ok(())
91    }
92
93    /// Add bits without masking checking the higher it of the value
94    /// work only if you're sur that the bits higher than the `nb_bits`
95    /// are 0. The result is undefined otherwise!
96    ///
97    /// > Note: It's not really faster anyway
98    #[inline]
99    pub fn unchecked_add_bits(&mut self, value: BitContainer, nb_bits: u8) -> Result<()> {
100        if value >> nb_bits != 0 || nb_bits + self.bit_pos > CTNR_SIZE {
101            throw!(
102                AddBits,
103                format!(
104                    "Error add bits fast (nb_bits {}) (bit_pos {})",
105                    nb_bits, self.bit_pos
106                )
107            )
108        }
109        self.bits_container |= value << self.bit_pos;
110        self.bit_pos += nb_bits;
111        Ok(())
112    }
113
114    /// Push nb_bytes into stream and clean pushed from container
115    ///
116    /// # Panic
117    /// If stream overflow
118    #[inline]
119    pub fn flush_bits(&mut self) {
120        let nb_bytes = (self.bit_pos >> 3) as usize;
121        self.stream.append(
122            &mut self
123                .bits_container
124                .to_le_bytes()
125                .to_vec()
126                .drain(0..nb_bytes)
127                .collect(),
128        );
129        self.bit_pos &= 7;
130        if nb_bytes == CTNR_BYTES_SIZE {
131            self.bits_container = 0
132        } else {
133            self.bits_container >>= nb_bytes << 3;
134        }
135    }
136
137    /// Flush remainings bits from the container with an endMark.
138    ///
139    /// # Return
140    /// Total size of the stream in bytes
141    ///
142    /// #Panic
143    /// Panic if overflow detected
144    #[inline]
145    pub fn close_stream(&mut self) -> Result<()> {
146        if self.bit_pos == CTNR_SIZE {
147            // Secure auto flush
148            self.flush_bits();
149        }
150        self.unchecked_add_bits(1, 1)?;
151        self.flush_bits();
152        if self.bits_container > 0 {
153            debug_test!("Push {:010b} into the stream", self.bits_container as u8);
154            self.stream.push(self.bits_container as u8);
155            self.bits_container = 0;
156        }
157        Ok(())
158    }
159}
160
161impl TryFrom<BitEstream> for BitDstream {
162    type Error = BitStreamError;
163
164    fn try_from(mut stream: BitEstream) -> Result<Self> {
165        if stream.stream.is_empty() {
166            throw!(EmptyStream)
167        }
168        let (bits_container, bits_consumed, _) = build_dstream_from_vec(&mut stream.stream)?;
169        Ok(BitDstream {
170            bits_container,
171            stream: stream.stream,
172            bits_consumed,
173        })
174    }
175}
176
177impl From<BitEstream> for Vec<u8> {
178    fn from(mut stream: BitEstream) -> Self {
179        stream.close_stream().unwrap();
180        stream.stream
181    }
182}
183
184impl From<&BitEstream> for Vec<u8> {
185    fn from(stream: &BitEstream) -> Self {
186        stream.stream.clone()
187    }
188}
189
190impl TryFrom<Vec<u8>> for BitDstream {
191    type Error = BitStreamError;
192
193    fn try_from(mut stream: Vec<u8>) -> Result<Self> {
194        if stream.is_empty() {
195            throw!(EmptyStream)
196        }
197        let (bits_container, bits_consumed, _) = build_dstream_from_vec(&mut stream)?;
198        Ok(BitDstream {
199            bits_container,
200            stream,
201            bits_consumed,
202        })
203    }
204}
205
206impl BitDstream {
207    /// Look a nb_bits in the container
208    ///
209    /// The container isn't modified
210    /// Return an error if nb_bits overflow container
211    #[inline]
212    pub fn look_bits(&mut self, nb_bits: u8) -> Result<BitContainer> {
213        debug_test!("Looking at bits {} {}", self.bits_consumed, nb_bits);
214        get_middle_bits(
215            self.bits_container,
216            // CTNR_SIZE - self.bits_consumed - nb_bits
217            CTNR_SIZE
218                .checked_sub(self.bits_consumed)
219                .unwrap_or_else(|| {
220                    panic!(
221                        "attempt to substract with overflow: \
222                substract the buffer container size {CTNR_SIZE} with current\
223                bits consumed by the reader {}",
224                        self.bits_consumed
225                    )
226                })
227                .checked_sub(nb_bits)
228                .unwrap_or_else(|| {
229                    panic!(
230                        "attempt to substract with overflow: \
231                substract the buffer container size {CTNR_SIZE} with current\
232                bits consumed by the reader {} and a given number of bits: {}",
233                        self.bits_consumed, nb_bits
234                    )
235                }),
236            nb_bits,
237        )
238    }
239
240    /// Skip a number of bits by incrementing the `bit_consumed`
241    /// counter.
242    #[inline]
243    pub fn skip_bits(&mut self, nb_bits: u8) {
244        self.bits_consumed += nb_bits
245    }
246
247    /// Read and consumed in the local `bits_container`
248    /// You've to be carefull and not read more than `CTNR_SIZE`
249    ///
250    /// Whatever it return an error if you overflow the bitcontainer.
251    /// That's the signal for reloading.
252    #[inline]
253    pub fn read_bits(&mut self, nb_bits: u8) -> Result<BitContainer> {
254        let bits = self.look_bits(nb_bits)?;
255        self.skip_bits(nb_bits);
256        Ok(bits)
257    }
258
259    /// Once you've read `CTNR_SIZE` bits, you probably would like to refill it
260    /// and continue to read the stream vector.
261    #[inline]
262    pub fn reload_container(&mut self) -> Result<bool> {
263        if self.bits_consumed > CTNR_SIZE {
264            throw!(BitsOverflow, "Stream consume overflow")
265        }
266        if self.stream.is_empty() {
267            return Ok(true);
268        }
269        let nb_bytes = (self.bits_consumed >> 3) as usize;
270        self.bits_consumed &= 7;
271        let mut ctnr = self.bits_container.to_le_bytes().to_vec();
272        let mut ctnr = ctnr.drain(..ctnr.len() - nb_bytes).collect::<Vec<u8>>();
273        self.stream.append(&mut ctnr);
274        let dstr = build_dstream_from_vec(&mut self.stream)?;
275        self.bits_consumed = if dstr.2 < CTNR_BYTES_SIZE {
276            CTNR_SIZE - (dstr.2 << 3) as u8
277        } else {
278            0
279        };
280        self.bits_container = dstr.0;
281        Ok(false)
282    }
283}
284
285/*******
286 * Inlined tools
287 *  */
288
289/// We assume that the v table has a len >= 4
290/// Construct a u32 from bytes little-endian
291#[inline]
292fn read_le(v: &[u8]) -> BitContainer {
293    debug_test!("Read LITTLE-ENDIAN : {:?}", v);
294    assert_eq!(
295        v.len(),
296        CTNR_BYTES_SIZE,
297        "Unexpected size of container, cannot transmute value"
298    );
299    BitContainer::from_le_bytes(v.try_into().unwrap())
300}
301
302#[inline]
303pub fn get_upper_bits(bits_container: BitContainer, start: u8) -> BitContainer {
304    bits_container >> start
305}
306
307#[inline]
308pub fn get_middle_bits(
309    bit_container: BitContainer,
310    start: u8,
311    nb_bits: u8,
312) -> Result<BitContainer> {
313    const REG_MASK: u8 = CTNR_SIZE - 1;
314    if nb_bits > BIT_MASK_SIZE {
315        throw!(BitsOverflow, format!("at get_middle_bits() : {}", nb_bits))
316    }
317    Ok((bit_container >> (start & REG_MASK)) & BIT_MASK[nb_bits as usize])
318}
319
320#[inline]
321pub fn get_lower_bits(bit_container: BitContainer, nb_bits: u8) -> Result<BitContainer> {
322    if nb_bits > BIT_MASK_SIZE {
323        throw!(BitsOverflow, format!("at get_lower_bits() : {}", nb_bits))
324    }
325    Ok(bit_container & BIT_MASK[nb_bits as usize])
326}
327
328/// Tools that return a `bits_container` and a `bits_consumed` from a
329/// bytes Vec<u8> inlined for performance. Used in TryFrom impl and
330/// in reload. Also finally return the number of `bytes` drained from
331/// the stream vector.
332#[inline]
333fn build_dstream_from_vec(stream: &mut Vec<u8>) -> Result<(BitContainer, u8, usize)> {
334    debug_test!(
335        "\nStart building a new build_dstream_from_vec of len : {}",
336        stream.len()
337    );
338    let bytes: usize;
339    let mut bits_container: BitContainer;
340    if stream.len() >= CTNR_BYTES_SIZE {
341        // Draining CTNR_BYTES_SIZE elements from stream
342        let bits: Vec<u8> = stream.drain(stream.len() - CTNR_BYTES_SIZE..).collect();
343        bits_container = read_le(&bits);
344        bytes = CTNR_BYTES_SIZE;
345    } else {
346        // Found a buffer len < `CTNR_BYTES_SIZE`
347        bytes = stream.len();
348        bits_container = stream[0] as BitContainer;
349        #[cfg(target_pointer_width = "64")]
350        {
351            if stream.len() == 7 {
352                bits_container += (stream.pop().unwrap() as BitContainer) << (CTNR_SIZE - 16);
353            }
354            if stream.len() == 6 {
355                bits_container += (stream.pop().unwrap() as BitContainer) << (CTNR_SIZE - 24);
356            }
357            if stream.len() == 5 {
358                bits_container += (stream.pop().unwrap() as BitContainer) << (CTNR_SIZE - 32);
359            }
360            if stream.len() == 4 {
361                bits_container += (stream.pop().unwrap() as BitContainer) << 24;
362            }
363        }
364        if stream.len() == 3 {
365            bits_container += (stream.pop().unwrap() as BitContainer) << 16;
366        }
367        if stream.len() == 2 {
368            bits_container += (stream.pop().unwrap() as BitContainer) << 8;
369        }
370        stream.clear(); /* Clear the last element already in the container */
371    }
372    Ok((bits_container, bits_container.leading_zeros() as u8, bytes))
373}