Coverage Report

Created: 2025-12-14 07:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-inflate-0.2.54/src/bitstream.rs
Line
Count
Source
1
//! `BitStreamReader` API
2
//!
3
//! This module provides an interface to read and write bits (and bytes) for
4
//! huffman
5
6
pub struct BitStreamReader<'src>
7
{
8
    // buffer from which we are pulling in bits from
9
    // used in decompression.
10
    pub src:       &'src [u8],
11
    // position in our buffer,
12
    pub position:  usize,
13
    pub bits_left: u8,
14
    pub buffer:    u64,
15
    pub over_read: usize
16
}
17
18
impl<'src> BitStreamReader<'src>
19
{
20
    /// Create a new `BitStreamReader` instance
21
    ///
22
    /// # Expectations
23
    /// The buffer must be padded with fill bytes in the end,
24
    /// if not, this becomes UB in the refill phase.
25
0
    pub fn new(in_buffer: &'src [u8]) -> BitStreamReader<'src>
26
    {
27
0
        BitStreamReader {
28
0
            bits_left: 0,
29
0
            buffer:    0,
30
0
            src:       in_buffer,
31
0
            position:  0,
32
0
            over_read: 0
33
0
        }
34
0
    }
35
    /// Refill the bitstream ensuring the buffer has bits between
36
    /// 56 and 63.
37
    ///
38
    #[inline(always)]
39
0
    pub fn refill(&mut self)
40
    {
41
        /*
42
         * The refill always guarantees refills between 56-63
43
         *
44
         * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur.
45
         */
46
0
        let mut buf = [0; 8];
47
48
0
        match self.src.get(self.position..self.position + 8)
49
        {
50
0
            Some(bytes) =>
51
0
            {
52
0
                buf.copy_from_slice(bytes);
53
0
                // create a u64 from an array of u8's
54
0
                let new_buffer = u64::from_le_bytes(buf);
55
0
                // num indicates how many bytes we actually consumed.
56
0
                let num = 63 ^ self.bits_left;
57
0
                // offset position
58
0
                self.position += (num >> 3) as usize;
59
0
                // shift number of bits
60
0
                self.buffer |= new_buffer << self.bits_left;
61
0
                // update bits left
62
0
                // bits left are now between 56-63
63
0
                self.bits_left |= 56;
64
0
            }
65
0
            None => self.refill_slow()
66
        }
67
0
    }
68
    #[inline(always)]
69
0
    pub fn refill_inner_loop(&mut self)
70
    {
71
        /*
72
         * The refill always guarantees refills between 56-63
73
         *
74
         * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur.
75
         */
76
0
        let mut buf = [0; 8];
77
78
0
        if let Some(bytes) = self.src.get(self.position..self.position + 8)
79
        {
80
0
            {
81
0
                buf.copy_from_slice(bytes);
82
0
                // create a u64 from an array of u8's
83
0
                let new_buffer = u64::from_le_bytes(buf);
84
0
                // num indicates how many bytes we actually consumed.
85
0
                let num = 63 ^ self.bits_left;
86
0
                // offset position
87
0
                self.position += (num >> 3) as usize;
88
0
                // shift number of bits
89
0
                self.buffer |= new_buffer << self.bits_left;
90
0
                // update bits left
91
0
                // bits left are now between 56-63
92
0
                self.bits_left |= 56;
93
0
            }
94
0
        }
95
0
    }
96
    #[inline(never)]
97
0
    fn refill_slow(&mut self)
98
    {
99
0
        let bytes = &self.src[self.position..];
100
101
0
        for byte in bytes
102
        {
103
0
            if self.bits_left >= 56
104
            {
105
0
                break;
106
0
            }
107
108
0
            self.buffer |= u64::from(*byte) << self.bits_left;
109
0
            self.bits_left += 8;
110
0
            self.position += 1;
111
        }
112
0
        while self.bits_left < 56
113
0
        {
114
0
            self.bits_left += 8;
115
0
            self.over_read += 1;
116
0
        }
117
0
    }
118
119
    #[inline(always)]
120
0
    pub fn peek_bits<const LOOKAHEAD: usize>(&self) -> usize
121
    {
122
0
        debug_assert!(self.bits_left >= LOOKAHEAD as u8);
123
0
        (self.buffer & ((1 << LOOKAHEAD) - 1)) as usize
124
0
    }
Unexecuted instantiation: <zune_inflate::bitstream::BitStreamReader>::peek_bits::<7>
Unexecuted instantiation: <zune_inflate::bitstream::BitStreamReader>::peek_bits::<8>
Unexecuted instantiation: <zune_inflate::bitstream::BitStreamReader>::peek_bits::<11>
125
    #[inline(always)]
126
0
    pub fn peek_var_bits(&self, lookahead: usize) -> usize
127
    {
128
0
        debug_assert!(self.bits_left >= lookahead as u8);
129
0
        (self.buffer & ((1 << lookahead) - 1)) as usize
130
0
    }
131
132
    #[inline(always)]
133
0
    pub fn get_bits(&mut self, num_bits: u8) -> u64
134
    {
135
0
        debug_assert!(self.bits_left >= num_bits);
136
137
0
        let mask = (1_u64 << num_bits) - 1;
138
139
0
        let value = self.buffer & mask;
140
141
0
        self.buffer >>= num_bits;
142
143
0
        self.bits_left -= num_bits;
144
145
0
        value
146
0
    }
147
    /// Get number of bits left in the bit buffer.
148
0
    pub const fn get_bits_left(&self) -> u8
149
    {
150
0
        self.bits_left
151
0
    }
152
    /// Get position the stream is in this buffer
153
    /// Or alternatively, number of bits read.
154
0
    pub fn get_position(&self) -> usize
155
    {
156
0
        self.position
157
0
            .saturating_sub(usize::from(self.bits_left >> 3))
158
0
    }
159
160
    /// Reset buffer and bits left to zero.
161
0
    pub fn reset(&mut self)
162
    {
163
0
        self.buffer = 0;
164
0
        self.bits_left = 0;
165
0
    }
166
    /// Return true if the bit buffer can satisfy
167
    /// `bits` read without refilling,
168
0
    pub const fn has(&self, bits: u8) -> bool
169
    {
170
0
        self.bits_left >= bits
171
0
    }
172
173
    #[inline(always)]
174
0
    pub fn drop_bits(&mut self, bits: u8)
175
    {
176
0
        debug_assert!(self.bits_left >= bits);
177
0
        self.bits_left -= bits;
178
0
        self.buffer >>= bits;
179
0
    }
180
    /// Return the remaining bytes in this stream.
181
    ///
182
    /// This does not consider bits in the bit-buffer hence
183
    /// may not be accurate
184
0
    pub const fn remaining_bytes(&self) -> usize
185
    {
186
0
        self.src.len().saturating_sub(self.position)
187
0
    }
188
}