• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

royaltm / rust-delharc / 29785215315

20 Jul 2026 10:49PM UTC coverage: 93.666% (-0.6%) from 94.242%
29785215315

push

github

royaltm
fix header: check for known dir separators instead of system dependent ones

5 of 6 new or added lines in 1 file covered. (83.33%)

193 existing lines in 13 files now uncovered.

3978 of 4247 relevant lines covered (93.67%)

43937550.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.26
/src/bitstream.rs
1
//! # Bit-stream tools.
2
use crate::error::{LhaResult, LhaError, DecompressionError};
3
use crate::stub_io::Read;
4

5
type BitBuf = usize;
6
const BITBUF_BYTESIZE: usize = size_of::<BitBuf>();
7
const BITBUF_BITSIZE: u32 = BitBuf::BITS;
8

9
/// This trait is implemented for all primitives that can receive bits using
10
/// [`BitRead::read_bits()`].
11
pub trait UBits: Copy {
12
    /// The size of this integer type in bits
13
    const BITS: u32;
14
    /// Convert the bit buffer to this integer value by truncating unused bits
15
    fn from_bits(bitbuf: BitBuf) -> Self;
16
}
17

18
/// This interface is for reading individual bits from a data stream.
19
pub trait BitRead {
20
    /// The error type returned from the underlying data reader.
21
    type Error;
22
    /// Read the next single bit from the stream. Return `true` if the bit
23
    /// is `1` and `false` if it's `0`.
24
    fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>>;
25
    /// Reads the next `n` bits from the stream.
26
    ///
27
    /// For example reading 4 bits into the `u8` type will result in: `0b0000abcd` where
28
    /// `a`, `b`, `c`, `d` are consecutive MSB -> LSB bits that were read from the source.
29
    ///
30
    /// Returns `0` if `n` is `0` without reading from the underlying reader.
31
    ///
32
    /// # Errors
33
    /// Returns an error if `n` exceed the bit capacity of `T`.
34
    fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>>;
35
    /// Creates a "by reference" adaptor for this instance of `BitRead`.
36
    /// The returned adaptor also implements `BitRead` and will simply borrow this current reader.
37
    #[allow(dead_code)]
UNCOV
38
    fn by_ref(&mut self) -> &mut Self {
×
UNCOV
39
        self
×
UNCOV
40
    }
×
41
}
42

43
/// A simple bit-stream reader, wrapped over a readable stream.
44
///
45
/// Bits are being read from consecutive data bytes, starting
46
/// from the highest bit of each byte.
47
#[derive(Debug)]
48
pub struct BitStream<R> {
49
    inner: R,
50
    // x..x10..0
51
    bits_buf: BitBuf,
52
}
53

54
macro_rules! impl_ubits {
55
    ($ty:ty) => {
56
        impl UBits for $ty {
57
            const BITS: u32 = <$ty>::BITS;
58
            #[inline(always)]
59
            fn from_bits(bitbuf: BitBuf) -> Self {
712,376,366✔
60
                bitbuf as $ty
712,376,366✔
61
            }
712,376,366✔
62
        }
63
    };
64
}
65

66
impl_ubits!(u8);
67
impl_ubits!(u16);
68
impl_ubits!(u32);
69
impl_ubits!(usize);
70
#[cfg(feature = "extend")]
71
impl_ubits!(u64);
72
#[cfg(feature = "extend")]
73
impl_ubits!(u128);
74

75
impl<R: Read> BitStream<R> {
76
    /// Create and return a new `BitStream`.
77
    pub fn new(inner: R) -> BitStream<R> {
1,068✔
78
        BitStream { inner, bits_buf: 1 << (BITBUF_BITSIZE - 1) }
1,068✔
79
    }
1,068✔
80
    /// Unwrap this `BitStream`, returning the underlying reader.
81
    ///
82
    /// Note that any leftover data in the internal bit buffer is lost.
83
    /// Therefore, a following read from the underlying reader may lead to
84
    /// data loss.
85
    pub fn into_inner(self) -> R {
433✔
86
        self.inner
433✔
87
    }
433✔
88
    /// Get a reference to the underlying reader.
89
    ///
90
    /// Care should be taken to avoid modifying the internal I/O state of the
91
    /// underlying readers as doing so may corrupt the internal state of this
92
    /// `BitStream`.
UNCOV
93
    pub fn get_ref(&self) -> &R {
×
UNCOV
94
        &self.inner
×
UNCOV
95
    }
×
96
    /// Get a mutable reference to the underlying reader.
97
    ///
98
    /// Care should be taken to avoid modifying the internal I/O state of the
99
    /// underlying readers as doing so may corrupt the internal state of this
100
    /// `BitStream`.
UNCOV
101
    pub fn get_mut(&mut self) -> &mut R {
×
UNCOV
102
        &mut self.inner
×
UNCOV
103
    }
×
104
    /// The callers must take care to provide `n` in the range `1..=BITBUF_BITSIZE`.
105
    #[inline]
106
    fn next_bits(&mut self, n: u32) -> LhaResult<BitBuf, R> {
2,147,483,647✔
107
        debug_assert!(n != 0 && n <= BITBUF_BITSIZE);
2,147,483,647✔
108
        let have_bits = BITBUF_BITSIZE - self.bits_buf.trailing_zeros() - 1;
2,147,483,647✔
109
        let res = self.bits_buf >> (BITBUF_BITSIZE - n);
2,147,483,647✔
110

111
        if n <= have_bits {
2,147,483,647✔
112
            self.bits_buf <<= n;
2,147,483,647✔
113
            return Ok(res)
2,147,483,647✔
114
        }
91,916,796✔
115

116
        let missing_bits = n - have_bits;
91,916,796✔
117
        let mut buf = [0u8;BITBUF_BYTESIZE];
91,916,796✔
118
        let bits_read = 8u32 * self.inner.read_all(&mut buf)
91,916,796✔
119
                                .map_err(LhaError::Io)? as u32;
91,916,796✔
120
        if bits_read < missing_bits {
91,916,796✔
121
            return Err(LhaError::Io(R::unexpected_eof()))
4✔
122
        }
91,916,792✔
123
        let new_bits: BitBuf = BitBuf::from_be_bytes(buf);
91,916,792✔
124
        // clear trailing bits and merge
125
        let res = res & (res - 1)
91,916,792✔
126
                | new_bits >> (BITBUF_BITSIZE - missing_bits);
91,916,792✔
127
        self.bits_buf = if missing_bits == BITBUF_BITSIZE {
91,916,792✔
128
            0
1✔
129
        }
130
        else {
131
            new_bits << missing_bits
91,916,791✔
132
        } | 1 << (BITBUF_BITSIZE - 1 - (bits_read - missing_bits));
91,916,792✔
133
        Ok(res)
91,916,792✔
134
    }
2,147,483,647✔
135

136
    // #[inline]
137
    // fn read_exact_or_to_end(&mut self, mut buf: &mut[u8]) -> io::Result<usize> {
138
    //     let orig_len = buf.len();
139
    //     while !buf.is_empty() {
140
    //         match self.inner.read(buf) {
141
    //             Ok(0) => break,
142
    //             Ok(n) => buf = &mut buf[n..],
143
    //             Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
144
    //             Err(e) => return Err(e),
145
    //         }
146
    //     }
147
    //     Ok(orig_len - buf.len())
148
    // }
149
}
150

151
impl<R: BitRead> BitRead for &mut R {
152
    type Error = R::Error;
153

154
    #[inline]
155
    fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>> {
2,147,483,647✔
156
        (*self).read_bit()
2,147,483,647✔
157
    }
2,147,483,647✔
158

159
    #[inline]
UNCOV
160
    fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>> {
×
UNCOV
161
        (*self).read_bits(n)
×
UNCOV
162
    }
×
163
}
164

165
impl<R: Read> BitRead for BitStream<R> {
166
    type Error = R::Error;
167

168
    #[inline]
169
    fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>> {
2,147,483,647✔
170
        self.next_bits(1).map(|bits| bits != 0)
2,147,483,647✔
171
    }
2,147,483,647✔
172

173
    fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>> {
642,244,812✔
174
        match n {
630,557,672✔
175
            0 => Ok(0),
11,687,140✔
176
            n if n <= T::BITS => self.next_bits(n),
630,557,672✔
UNCOV
177
            _ => Err(LhaError::Decompress(DecompressionError::BitSizeOverflow))
×
178
        }.map(T::from_bits)
642,244,812✔
179
    }
642,244,812✔
180
}
181

182
#[cfg(feature = "std")]
183
#[cfg(test)]
184
mod tests {
185
    use std::io;
186
    use super::*;
187
    #[test]
188
    fn bit_stream_works() {
1✔
189
        assert_eq!(BITBUF_BYTESIZE, size_of::<usize>());
1✔
190
        assert!(BITBUF_BITSIZE >= 32);
1✔
191
        assert_eq!(BITBUF_BITSIZE, BITBUF_BYTESIZE as u32 * 8);
1✔
192
        let mut somebits: &[u8] = &[];
1✔
193
        let mut brdr = BitStream::new(&mut somebits);
1✔
194
        let err: io::Error = brdr.read_bit().unwrap_err().into();
1✔
195
        assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
1✔
196
        let err: io::Error = brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap_err().into();
1✔
197
        assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
1✔
198
        let mut somebits: &[u8] = &[0];
1✔
199
        let mut brdr = BitStream::new(&mut somebits);
1✔
200
        for _ in 0..8 {
1✔
201
            assert_eq!(brdr.read_bit().unwrap(), false);
8✔
202
        }
203
        let mut somebits: &[u8] = &[!0];
1✔
204
        let mut brdr = BitStream::new(&mut somebits);
1✔
205
        for _ in 0..8 {
1✔
206
            assert_eq!(brdr.read_bit().unwrap(), true);
8✔
207
        }
208
        let mut somebits: &[u8] = &[0b01001100, 0b01110000, 0b11110000, 0b01111100, 0b00001111, 0b11000000, 0b01111111,
1✔
209
                                    0b00000000, 0b11111111, 0b00000000, 0b01111111, 0b11000000, 0b00001111, 0b11111100,
1✔
210
                                    0b00000000, 0b01111111, 0b11110000, 0b00000000, 0b11111111, 0b11110000, 0b00000000,
1✔
211
                                    0b01111111, 0b11111100, 0b00000000, 0b00001111, 0b11111111, 0b11000000, 0b00000000,
1✔
212
                                    0b01111111, 0b11111111];
1✔
213
        assert_eq!(brdr.read_bits::<usize>(0).unwrap(), 0);
1✔
214
        let mut brdr = BitStream::new(&mut somebits);
1✔
215
        for n in 1..16 {
15✔
216
            assert_eq!(brdr.read_bits::<u16>(n).unwrap(), 0);
15✔
217
            assert_eq!(brdr.read_bits::<u16>(n).unwrap(), (1 << n) - 1);
15✔
218
        }
219
        assert_eq!(brdr.read_bits::<usize>(0).unwrap(), 0);
1✔
220
        let err: io::Error = brdr.read_bit().unwrap_err().into();
1✔
221
        assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
1✔
222

223
        let mut somebits: &[u8] = &[1,2,3,4,5,6,7,8];
1✔
224
        let mut brdr = BitStream::new(&mut somebits);
1✔
225
        match BITBUF_BITSIZE {
1✔
226
            #[cfg(target_pointer_width = "64")]
227
            64 => {
228
                assert_eq!(brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap(), 0x0102030405060708);
1✔
229
            }
230
            #[cfg(target_pointer_width = "32")]
231
            32 => {
232
                assert_eq!(brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap(), 0x01020304);
233
            }
UNCOV
234
            _ => unimplemented!()
×
235
        }
236
    }
1✔
237
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc