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

vigna / dsi-bitstream-rs / 22518245728

28 Feb 2026 09:40AM UTC coverage: 57.751% (+3.1%) from 54.618%
22518245728

push

github

vigna
delta_gamma in filenames

2213 of 3832 relevant lines covered (57.75%)

2595204.38 hits per line

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

62.41
/src/impls/buf_bit_reader.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Tommaso Fontana
3
 * SPDX-FileCopyrightText: 2023 Inria
4
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
5
 *
6
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7
 */
8

9
use num_primitive::PrimitiveInteger;
10
use num_traits::{AsPrimitive, ConstOne, ConstZero};
11

12
use crate::codes::params::{DefaultReadParams, ReadParams};
13
use crate::traits::*;
14
#[cfg(feature = "mem_dbg")]
15
use mem_dbg::{MemDbg, MemSize};
16

17
/// An internal shortcut to the double type of the word of a
18
/// [`WordRead`].
19
type BB<WR> = <<WR as WordRead>::Word as DoubleType>::DoubleType;
20

21
/// An implementation of [`BitRead`] and [`BitSeek`] for a [`WordRead`] and a
22
/// [`WordSeek`].
23
///
24
/// This implementation uses a bit buffer to store bits that are not yet read.
25
/// The buffer is sized as twice the word size of the underlying [`WordRead`].
26
/// Typically, the best choice is to have a buffer that is sized as `usize`,
27
/// which means that the word of the underlying [`WordRead`] should be half of
28
/// that (i.e., `u32` for a 64-bit architecture). However, results will vary
29
/// depending on the CPU.
30
///
31
/// The peek word is equal to the bit buffer. The value returned
32
/// by [`peek_bits`](crate::traits::BitRead::peek_bits) contains at least as
33
/// many bits as the word size plus one (extended with zeros beyond end of
34
/// stream).
35
///
36
/// The convenience functions [`from_path`] and [`from_file`] (requiring the
37
/// `std` feature) create a [`BufBitReader`] around a buffered file reader.
38
///
39
/// This implementation is usually faster than
40
/// [`BitReader`](crate::impls::BitReader).
41
///
42
/// The additional type parameter `RP` is used to select the parameters for the
43
/// instantaneous codes, but the casual user should be happy with the default
44
/// value. See [`ReadParams`] for more details.
45
///
46
/// For additional flexibility, when the `std` feature is enabled, this
47
/// structure implements [`std::io::Read`]. Note that because of coherence
48
/// rules it is not possible to implement [`std::io::Read`] for a generic
49
/// [`BitRead`].
50

51
#[derive(Debug)]
52
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
53
pub struct BufBitReader<E: Endianness, WR: WordRead, RP: ReadParams = DefaultReadParams>
54
where
55
    WR::Word: DoubleType,
56
{
57
    /// The [`WordRead`] used to fill the buffer.
58
    backend: WR,
59
    /// The 2-word bit buffer that is used to read the codes. It is never full,
60
    /// but it may be empty. Only the upper (BE) or lower (LE)
61
    /// `bits_in_buffer` bits are valid; the other bits are always zeroes.
62
    buffer: BB<WR>,
63
    /// Number of valid upper (BE) or lower (LE) bits in the buffer.
64
    /// It is always smaller than `BB::<WR>::BITS`.
65
    bits_in_buffer: usize,
66
    _marker: core::marker::PhantomData<(E, RP)>,
67
}
68

69
/// Creates a new [`BufBitReader`] with [default read
70
/// parameters](`DefaultReadParams`) from a file path using the provided
71
/// endianness and read word.
72
///
73
/// # Examples
74
///
75
/// ```no_run
76
/// use dsi_bitstream::prelude::*;
77
/// let mut reader = buf_bit_reader::from_path::<LE, u32>("data.bin")?;
78
/// # Ok::<(), Box<dyn core::error::Error>>(())
79
/// ```
80
#[cfg(feature = "std")]
81
pub fn from_path<E: Endianness, W: Word + DoubleType>(
1✔
82
    path: impl AsRef<std::path::Path>,
83
) -> std::io::Result<
84
    BufBitReader<E, super::WordAdapter<W, std::io::BufReader<std::fs::File>>, DefaultReadParams>,
85
>
86
where
87
    W::Bytes: Default + AsMut<[u8]>,
88
{
89
    Ok(from_file::<E, W>(std::fs::File::open(path)?))
3✔
90
}
91

92
/// Creates a new [`BufBitReader`] with [default read
93
/// parameters](`DefaultReadParams`) from a file using the provided
94
/// endianness and read word.
95
///
96
/// See also [`from_path`] for a version that takes a path.
97
#[must_use]
98
#[cfg(feature = "std")]
99
pub fn from_file<E: Endianness, W: Word + DoubleType>(
1✔
100
    file: std::fs::File,
101
) -> BufBitReader<E, super::WordAdapter<W, std::io::BufReader<std::fs::File>>, DefaultReadParams>
102
where
103
    W::Bytes: Default + AsMut<[u8]>,
104
{
105
    BufBitReader::new(super::WordAdapter::new(std::io::BufReader::new(file)))
4✔
106
}
107

108
impl<E: Endianness, WR: WordRead + Clone, RP: ReadParams> core::clone::Clone
109
    for BufBitReader<E, WR, RP>
110
where
111
    WR::Word: DoubleType,
112
{
113
    fn clone(&self) -> Self {
×
114
        Self {
115
            backend: self.backend.clone(),
×
116
            buffer: self.buffer,
×
117
            bits_in_buffer: self.bits_in_buffer,
×
118
            _marker: core::marker::PhantomData,
119
        }
120
    }
121
}
122

123
impl<E: Endianness, WR: WordRead, RP: ReadParams> BufBitReader<E, WR, RP>
124
where
125
    WR::Word: DoubleType,
126
{
127
    const WORD_BITS: usize = WR::Word::BITS as usize;
128
    const BUFFER_BITS: usize = BB::<WR>::BITS as usize;
129

130
    /// Creates a new [`BufBitReader`] around a [`WordRead`].
131
    ///
132
    /// # Examples
133
    /// ```
134
    /// use dsi_bitstream::prelude::*;
135
    /// let words: [u32; 2] = [0x0043b59f, 0xccf16077];
136
    /// let word_reader = MemWordReader::new_inf(&words);
137
    /// let mut buf_bit_reader = <BufBitReader<BE, _>>::new(word_reader);
138
    /// ```
139
    #[must_use]
140
    pub fn new(backend: WR) -> Self {
483,933✔
141
        Self {
142
            backend,
143
            buffer: BB::<WR>::ZERO,
144
            bits_in_buffer: 0,
145
            _marker: core::marker::PhantomData,
146
        }
147
    }
148

149
    /// Consumes this reader and returns the underlying [`WordRead`].
150
    #[must_use]
151
    pub fn into_inner(self) -> WR {
×
152
        self.backend
×
153
    }
154
}
155

156
//
157
// Big-endian implementation
158
//
159

160
impl<WR: WordRead, RP: ReadParams> BufBitReader<BE, WR, RP>
161
where
162
    WR::Word: DoubleType,
163
{
164
    /// Ensures that in the buffer there are at least `Self::WORD_BITS` bits to read.
165
    /// This method can be called only if there are at least
166
    /// `Self::WORD_BITS` free bits in the buffer.
167
    #[inline(always)]
168
    fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
1,936,883✔
169
        debug_assert!(Self::BUFFER_BITS - self.bits_in_buffer >= Self::WORD_BITS);
3,873,766✔
170

171
        let new_word: BB<WR> = self.backend.read_word()?.to_be().as_double();
11,621,298✔
172
        self.bits_in_buffer += Self::WORD_BITS;
1,936,883✔
173
        self.buffer |= new_word << (Self::BUFFER_BITS - self.bits_in_buffer);
3,873,766✔
174
        Ok(())
1,936,883✔
175
    }
176
}
177

178
impl<WR: WordRead, RP: ReadParams> BitRead<BE> for BufBitReader<BE, WR, RP>
179
where
180
    WR::Word: DoubleType,
181
{
182
    type Error = <WR as WordRead>::Error;
183
    type PeekWord = BB<WR>;
184
    const PEEK_BITS: usize = <WR as WordRead>::Word::BITS as usize + 1;
185

186
    #[inline(always)]
187
    fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
6,016,659✔
188
        debug_assert!(n_bits > 0);
12,033,318✔
189
        debug_assert!(n_bits <= Self::PeekWord::BITS as usize);
12,033,318✔
190

191
        // A peek can do at most one refill, otherwise we might lose data
192
        if n_bits > self.bits_in_buffer {
6,016,659✔
193
            self.refill()?;
3,873,766✔
194
        }
195

196
        debug_assert!(n_bits <= self.bits_in_buffer);
12,033,318✔
197

198
        // Move the n_bits highest bits of the buffer to the lowest
199
        Ok(self.buffer >> (Self::BUFFER_BITS - n_bits))
6,016,659✔
200
    }
201

202
    #[inline(always)]
203
    fn skip_bits_after_peek(&mut self, n_bits: usize) {
6,010,818✔
204
        self.bits_in_buffer -= n_bits;
6,010,818✔
205
        self.buffer <<= n_bits;
6,010,818✔
206
    }
207

208
    #[inline]
209
    fn read_bits(&mut self, mut num_bits: usize) -> Result<u64, Self::Error> {
110,502,699✔
210
        debug_assert!(num_bits <= 64);
221,005,398✔
211
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
221,005,398✔
212

213
        // most common path, we just read the buffer
214
        if num_bits <= self.bits_in_buffer {
110,502,699✔
215
            // Valid right shift of BB::<WR>::BITS - num_bits, even when num_bits is zero
216
            let result: u64 = (self.buffer >> (Self::BUFFER_BITS - num_bits - 1) >> 1_u32).as_();
382,923,380✔
217
            self.bits_in_buffer -= num_bits;
95,730,845✔
218
            self.buffer <<= num_bits;
95,730,845✔
219
            return Ok(result);
95,730,845✔
220
        }
221

222
        let mut result: u64 =
29,543,708✔
223
            (self.buffer >> (Self::BUFFER_BITS - 1 - self.bits_in_buffer) >> 1_u8).as_();
44,315,562✔
224
        num_bits -= self.bits_in_buffer;
14,771,854✔
225

226
        // Directly read to the result without updating the buffer
227
        while num_bits > Self::WORD_BITS {
22,287,340✔
228
            let new_word: u64 = self.backend.read_word()?.to_be().as_u64();
45,092,916✔
229
            result = (result << Self::WORD_BITS) | new_word;
7,515,486✔
230
            num_bits -= Self::WORD_BITS;
7,515,486✔
231
        }
232

233
        debug_assert!(num_bits > 0);
29,543,708✔
234
        debug_assert!(num_bits <= Self::WORD_BITS);
29,543,708✔
235

236
        // get the final word
237
        let new_word = self.backend.read_word()?.to_be();
59,087,416✔
238
        self.bits_in_buffer = Self::WORD_BITS - num_bits;
14,771,854✔
239
        // compose the remaining bits
240
        let upcast: u64 = new_word.as_u64();
59,087,416✔
241
        let final_bits: u64 = upcast >> self.bits_in_buffer;
44,315,562✔
242
        result = (result << (num_bits - 1) << 1) | final_bits;
14,771,854✔
243
        // and put the rest in the buffer
244
        self.buffer = (new_word.as_double() << (Self::BUFFER_BITS - self.bits_in_buffer - 1)) << 1;
29,543,708✔
245

246
        Ok(result)
14,771,854✔
247
    }
248

249
    #[inline]
250
    fn read_unary(&mut self) -> Result<u64, Self::Error> {
24,115,048✔
251
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
48,230,096✔
252

253
        // count the zeros from the left
254
        let zeros: usize = self.buffer.leading_zeros() as _;
96,460,192✔
255

256
        // if we encountered an 1 in the bits_in_buffer we can return
257
        if zeros < self.bits_in_buffer {
24,115,048✔
258
            self.buffer = self.buffer << zeros << 1;
11,666,367✔
259
            self.bits_in_buffer -= zeros + 1;
11,666,367✔
260
            return Ok(zeros as u64);
11,666,367✔
261
        }
262

263
        let mut result: u64 = self.bits_in_buffer as _;
37,346,043✔
264

265
        loop {
×
266
            let new_word = self.backend.read_word()?.to_be();
130,574,928✔
267

268
            if new_word != WR::Word::ZERO {
32,643,732✔
269
                let zeros: usize = new_word.leading_zeros() as _;
49,794,724✔
270
                self.buffer = new_word.as_double() << (Self::WORD_BITS + zeros) << 1;
24,897,362✔
271
                self.bits_in_buffer = Self::WORD_BITS - zeros - 1;
12,448,681✔
272
                return Ok(result + zeros as u64);
12,448,681✔
273
            }
274
            result += Self::WORD_BITS as u64;
20,195,051✔
275
        }
276
    }
277

278
    #[inline]
279
    fn skip_bits(&mut self, mut n_bits: usize) -> Result<(), Self::Error> {
118,440✔
280
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
236,880✔
281
        // happy case, just shift the buffer
282
        if n_bits <= self.bits_in_buffer {
118,440✔
283
            self.bits_in_buffer -= n_bits;
4,000✔
284
            self.buffer <<= n_bits;
4,000✔
285
            return Ok(());
4,000✔
286
        }
287

288
        n_bits -= self.bits_in_buffer;
114,440✔
289

290
        // skip words as needed
291
        while n_bits > Self::WORD_BITS {
114,440✔
292
            let _ = self.backend.read_word()?;
×
293
            n_bits -= Self::WORD_BITS;
×
294
        }
295

296
        // get the final word
297
        let new_word = self.backend.read_word()?.to_be();
457,760✔
298
        self.bits_in_buffer = Self::WORD_BITS - n_bits;
114,440✔
299

300
        self.buffer = new_word.as_double() << (Self::BUFFER_BITS - 1 - self.bits_in_buffer) << 1;
343,320✔
301

302
        Ok(())
114,440✔
303
    }
304

305
    #[cfg(not(feature = "no_copy_impls"))]
306
    fn copy_to<F: Endianness, W: BitWrite<F>>(
307
        &mut self,
308
        bit_write: &mut W,
309
        mut n: u64,
310
    ) -> Result<(), CopyError<Self::Error, W::Error>> {
311
        let from_buffer = Ord::min(n, self.bits_in_buffer as _);
×
312
        self.buffer = self.buffer.rotate_left(from_buffer as _);
×
313

314
        #[allow(unused_mut)]
315
        let mut self_buffer_u64: u64 = self.buffer.as_();
×
316

317
        #[cfg(feature = "checks")]
318
        {
319
            // Clean up in case checks are enabled
320
            if n < 64 {
×
321
                self_buffer_u64 &= (1_u64 << n) - 1;
×
322
            }
323
        }
324

325
        bit_write
×
326
            .write_bits(self_buffer_u64, from_buffer as usize)
×
327
            .map_err(CopyError::WriteError)?;
×
328
        n -= from_buffer;
×
329

330
        if n == 0 {
×
331
            self.bits_in_buffer -= from_buffer as usize;
×
332
            return Ok(());
×
333
        }
334

335
        while n > Self::WORD_BITS as u64 {
×
336
            bit_write
×
337
                .write_bits(
338
                    self.backend
×
339
                        .read_word()
×
340
                        .map_err(CopyError::ReadError)?
×
341
                        .to_be()
×
342
                        .as_u64(),
×
343
                    Self::WORD_BITS,
×
344
                )
345
                .map_err(CopyError::WriteError)?;
×
346
            n -= Self::WORD_BITS as u64;
×
347
        }
348

349
        debug_assert!(n > 0);
×
350
        let new_word = self
×
351
            .backend
×
352
            .read_word()
353
            .map_err(CopyError::ReadError)?
×
354
            .to_be();
355
        self.bits_in_buffer = Self::WORD_BITS - n as usize;
×
356
        bit_write
×
357
            .write_bits((new_word >> self.bits_in_buffer).as_u64(), n as usize)
×
358
            .map_err(CopyError::WriteError)?;
×
359
        self.buffer = new_word
×
360
            .as_double()
×
361
            .rotate_right(Self::WORD_BITS as u32 - n as u32);
×
362

363
        Ok(())
×
364
    }
365
}
366

367
impl<WR: WordRead + WordSeek<Error = <WR as WordRead>::Error>, RP: ReadParams> BitSeek
368
    for BufBitReader<BE, WR, RP>
369
where
370
    WR::Word: DoubleType,
371
{
372
    type Error = <WR as WordSeek>::Error;
373

374
    #[inline]
375
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
32,038✔
376
        Ok(self.backend.word_pos()? * Self::WORD_BITS as u64 - self.bits_in_buffer as u64)
128,152✔
377
    }
378

379
    #[inline]
380
    fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
×
381
        self.backend
×
382
            .set_word_pos(bit_index / Self::WORD_BITS as u64)?;
×
383
        let bit_offset = (bit_index % Self::WORD_BITS as u64) as usize;
×
384
        self.buffer = BB::<WR>::ZERO;
×
385
        self.bits_in_buffer = 0;
×
386
        if bit_offset != 0 {
×
387
            let new_word: BB<WR> = self.backend.read_word()?.to_be().as_double();
×
388
            self.bits_in_buffer = Self::WORD_BITS - bit_offset;
×
389
            self.buffer = new_word << (Self::BUFFER_BITS - self.bits_in_buffer);
×
390
        }
391
        Ok(())
×
392
    }
393
}
394

395
//
396
// Little-endian implementation
397
//
398

399
impl<WR: WordRead, RP: ReadParams> BufBitReader<LE, WR, RP>
400
where
401
    WR::Word: DoubleType,
402
{
403
    /// Ensures that in the buffer there are at least `Self::WORD_BITS` bits to read.
404
    /// This method can be called only if there are at least
405
    /// `Self::WORD_BITS` free bits in the buffer.
406
    #[inline(always)]
407
    fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
1,939,423✔
408
        debug_assert!(Self::BUFFER_BITS - self.bits_in_buffer >= Self::WORD_BITS);
3,878,846✔
409

410
        let new_word: BB<WR> = self.backend.read_word()?.to_le().as_double();
11,636,538✔
411
        self.buffer |= new_word << self.bits_in_buffer;
3,878,846✔
412
        self.bits_in_buffer += Self::WORD_BITS;
1,939,423✔
413
        Ok(())
1,939,423✔
414
    }
415
}
416

417
impl<WR: WordRead, RP: ReadParams> BitRead<LE> for BufBitReader<LE, WR, RP>
418
where
419
    WR::Word: DoubleType,
420
{
421
    type Error = <WR as WordRead>::Error;
422
    type PeekWord = BB<WR>;
423
    const PEEK_BITS: usize = <WR as WordRead>::Word::BITS as usize + 1;
424

425
    #[inline(always)]
426
    fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
6,016,779✔
427
        debug_assert!(n_bits > 0);
12,033,558✔
428
        debug_assert!(n_bits <= Self::PeekWord::BITS as usize);
12,033,558✔
429

430
        // A peek can do at most one refill, otherwise we might lose data
431
        if n_bits > self.bits_in_buffer {
6,016,779✔
432
            self.refill()?;
3,878,846✔
433
        }
434

435
        debug_assert!(n_bits <= self.bits_in_buffer);
12,033,558✔
436

437
        // Keep the n_bits lowest bits of the buffer
438
        let shamt = Self::BUFFER_BITS - n_bits;
12,033,558✔
439
        Ok((self.buffer << shamt) >> shamt)
6,016,779✔
440
    }
441

442
    #[inline(always)]
443
    fn skip_bits_after_peek(&mut self, n_bits: usize) {
6,010,937✔
444
        self.bits_in_buffer -= n_bits;
6,010,937✔
445
        self.buffer >>= n_bits;
6,010,937✔
446
    }
447

448
    #[inline]
449
    fn read_bits(&mut self, mut num_bits: usize) -> Result<u64, Self::Error> {
110,500,729✔
450
        debug_assert!(num_bits <= 64);
221,001,458✔
451
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
221,001,458✔
452

453
        // most common path, we just read the buffer
454
        if num_bits <= self.bits_in_buffer {
110,500,729✔
455
            let result: u64 = (self.buffer & ((BB::<WR>::ONE << num_bits) - BB::<WR>::ONE)).as_();
382,901,048✔
456
            self.bits_in_buffer -= num_bits;
95,725,262✔
457
            self.buffer >>= num_bits;
95,725,262✔
458
            return Ok(result);
95,725,262✔
459
        }
460

461
        let mut result: u64 = self.buffer.as_();
59,101,868✔
462
        let mut bits_in_res = self.bits_in_buffer;
29,550,934✔
463

464
        // Directly read to the result without updating the buffer
465
        while num_bits > Self::WORD_BITS + bits_in_res {
22,277,935✔
466
            let new_word: u64 = self.backend.read_word()?.to_le().as_u64();
45,014,808✔
467
            result |= new_word << bits_in_res;
7,502,468✔
468
            bits_in_res += Self::WORD_BITS;
7,502,468✔
469
        }
470

471
        num_bits -= bits_in_res;
14,775,467✔
472

473
        debug_assert!(num_bits > 0);
29,550,934✔
474
        debug_assert!(num_bits <= Self::WORD_BITS);
29,550,934✔
475

476
        // get the final word
477
        let new_word = self.backend.read_word()?.to_le();
59,101,868✔
478
        self.bits_in_buffer = Self::WORD_BITS - num_bits;
14,775,467✔
479
        // compose the remaining bits
480
        let shamt = 64 - num_bits;
29,550,934✔
481
        let upcast: u64 = new_word.as_u64();
59,101,868✔
482
        let final_bits: u64 = (upcast << shamt) >> shamt;
44,326,401✔
483
        result |= final_bits << bits_in_res;
14,775,467✔
484
        // and put the rest in the buffer
485
        self.buffer = new_word.as_double() >> num_bits;
29,550,934✔
486

487
        Ok(result)
14,775,467✔
488
    }
489

490
    #[inline]
491
    fn read_unary(&mut self) -> Result<u64, Self::Error> {
24,114,065✔
492
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
48,228,130✔
493

494
        // count the zeros from the right
495
        let zeros: usize = self.buffer.trailing_zeros() as usize;
72,342,195✔
496

497
        // if we encountered an 1 in the bits_in_buffer we can return
498
        if zeros < self.bits_in_buffer {
24,114,065✔
499
            self.buffer = self.buffer >> zeros >> 1;
11,665,319✔
500
            self.bits_in_buffer -= zeros + 1;
11,665,319✔
501
            return Ok(zeros as u64);
11,665,319✔
502
        }
503

504
        let mut result: u64 = self.bits_in_buffer as _;
37,346,238✔
505

506
        loop {
×
507
            let new_word = self.backend.read_word()?.to_le();
130,462,196✔
508

509
            if new_word != WR::Word::ZERO {
32,615,549✔
510
                let zeros: usize = new_word.trailing_zeros() as _;
49,794,984✔
511
                self.buffer = new_word.as_double() >> zeros >> 1;
24,897,492✔
512
                self.bits_in_buffer = Self::WORD_BITS - zeros - 1;
12,448,746✔
513
                return Ok(result + zeros as u64);
12,448,746✔
514
            }
515
            result += Self::WORD_BITS as u64;
20,166,803✔
516
        }
517
    }
518

519
    #[inline]
520
    fn skip_bits(&mut self, mut n_bits: usize) -> Result<(), Self::Error> {
118,441✔
521
        debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
236,882✔
522
        // happy case, just shift the buffer
523
        if n_bits <= self.bits_in_buffer {
118,441✔
524
            self.bits_in_buffer -= n_bits;
4,000✔
525
            self.buffer >>= n_bits;
4,000✔
526
            return Ok(());
4,000✔
527
        }
528

529
        n_bits -= self.bits_in_buffer;
114,441✔
530

531
        // skip words as needed
532
        while n_bits > Self::WORD_BITS {
114,441✔
533
            let _ = self.backend.read_word()?;
×
534
            n_bits -= Self::WORD_BITS;
×
535
        }
536

537
        // get the final word
538
        let new_word = self.backend.read_word()?.to_le();
457,764✔
539
        self.bits_in_buffer = Self::WORD_BITS - n_bits;
114,441✔
540
        self.buffer = new_word.as_double() >> n_bits;
228,882✔
541

542
        Ok(())
114,441✔
543
    }
544

545
    #[cfg(not(feature = "no_copy_impls"))]
546
    fn copy_to<F: Endianness, W: BitWrite<F>>(
547
        &mut self,
548
        bit_write: &mut W,
549
        mut n: u64,
550
    ) -> Result<(), CopyError<Self::Error, W::Error>> {
551
        let from_buffer = Ord::min(n, self.bits_in_buffer as _);
×
552

553
        #[allow(unused_mut)]
554
        let mut self_buffer_u64: u64 = self.buffer.as_();
×
555

556
        #[cfg(feature = "checks")]
557
        {
558
            // Clean up in case checks are enabled
559
            if n < 64 {
×
560
                self_buffer_u64 &= (1_u64 << n) - 1;
×
561
            }
562
        }
563

564
        bit_write
×
565
            .write_bits(self_buffer_u64, from_buffer as usize)
×
566
            .map_err(CopyError::WriteError)?;
×
567

568
        self.buffer >>= from_buffer;
×
569
        n -= from_buffer;
×
570

571
        if n == 0 {
×
572
            self.bits_in_buffer -= from_buffer as usize;
×
573
            return Ok(());
×
574
        }
575

576
        while n > Self::WORD_BITS as u64 {
×
577
            bit_write
×
578
                .write_bits(
579
                    self.backend
×
580
                        .read_word()
×
581
                        .map_err(CopyError::ReadError)?
×
582
                        .to_le()
×
583
                        .as_u64(),
×
584
                    Self::WORD_BITS,
×
585
                )
586
                .map_err(CopyError::WriteError)?;
×
587
            n -= Self::WORD_BITS as u64;
×
588
        }
589

590
        debug_assert!(n > 0);
×
591
        let new_word = self
×
592
            .backend
×
593
            .read_word()
594
            .map_err(CopyError::ReadError)?
×
595
            .to_le();
596
        self.bits_in_buffer = Self::WORD_BITS - n as usize;
×
597

598
        #[allow(unused_mut)]
599
        let mut new_word_u64: u64 = new_word.as_u64();
×
600

601
        #[cfg(feature = "checks")]
602
        {
603
            // Clean up in case checks are enabled
604
            if n < 64 {
×
605
                new_word_u64 &= (1_u64 << n) - 1;
×
606
            }
607
        }
608

609
        bit_write
×
610
            .write_bits(new_word_u64, n as usize)
×
611
            .map_err(CopyError::WriteError)?;
×
612
        self.buffer = new_word.as_double() >> n;
×
613
        Ok(())
×
614
    }
615
}
616

617
impl<WR: WordRead + WordSeek<Error = <WR as WordRead>::Error>, RP: ReadParams> BitSeek
618
    for BufBitReader<LE, WR, RP>
619
where
620
    WR::Word: DoubleType,
621
{
622
    type Error = <WR as WordSeek>::Error;
623

624
    #[inline]
625
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
32,138✔
626
        Ok(self.backend.word_pos()? * Self::WORD_BITS as u64 - self.bits_in_buffer as u64)
128,552✔
627
    }
628

629
    #[inline]
630
    fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
×
631
        self.backend
×
632
            .set_word_pos(bit_index / Self::WORD_BITS as u64)?;
×
633

634
        let bit_offset = (bit_index % Self::WORD_BITS as u64) as usize;
×
635
        self.buffer = BB::<WR>::ZERO;
×
636
        self.bits_in_buffer = 0;
×
637
        if bit_offset != 0 {
×
638
            let new_word: BB<WR> = self.backend.read_word()?.to_le().as_double();
×
639
            self.bits_in_buffer = Self::WORD_BITS - bit_offset;
×
640
            self.buffer = new_word >> bit_offset;
×
641
        }
642
        Ok(())
×
643
    }
644
}
645

646
#[cfg(feature = "std")]
647
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<LE, WR, RP>
648
where
649
    WR::Word: DoubleType,
650
{
651
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1,014✔
652
        let mut iter = buf.chunks_exact_mut(8);
3,042✔
653

654
        for chunk in &mut iter {
3,222✔
655
            let word = self
4,416✔
656
                .read_bits(64)
657
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
2,208✔
658
            chunk.copy_from_slice(&word.to_le_bytes());
6,624✔
659
        }
660

661
        let rem = iter.into_remainder();
3,042✔
662
        if !rem.is_empty() {
1,014✔
663
            let word = self
1,904✔
664
                .read_bits(rem.len() * 8)
1,904✔
665
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
952✔
666
            rem.copy_from_slice(&word.to_le_bytes()[..rem.len()]);
3,808✔
667
        }
668

669
        Ok(buf.len())
1,014✔
670
    }
671
}
672

673
#[cfg(feature = "std")]
674
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<BE, WR, RP>
675
where
676
    WR::Word: DoubleType,
677
{
678
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1,014✔
679
        let mut iter = buf.chunks_exact_mut(8);
3,042✔
680

681
        for chunk in &mut iter {
3,222✔
682
            let word = self
4,416✔
683
                .read_bits(64)
684
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
2,208✔
685
            chunk.copy_from_slice(&word.to_be_bytes());
6,624✔
686
        }
687

688
        let rem = iter.into_remainder();
3,042✔
689
        if !rem.is_empty() {
1,014✔
690
            let word = self
1,904✔
691
                .read_bits(rem.len() * 8)
1,904✔
692
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
952✔
693
            rem.copy_from_slice(&word.to_be_bytes()[8 - rem.len()..]);
3,808✔
694
        }
695

696
        Ok(buf.len())
1,014✔
697
    }
698
}
699

700
#[cfg(test)]
701
#[cfg(feature = "std")]
702
mod tests {
703
    use super::*;
704
    use crate::prelude::{MemWordReader, MemWordWriterVec};
705
    use core::error::Error;
706
    use std::io::Read;
707

708
    #[test]
709
    fn test_read() -> std::io::Result<()> {
710
        let data = [
711
            0x90, 0x2d, 0xd0, 0x26, 0xdf, 0x89, 0xbb, 0x7e, 0x3a, 0xd6, 0xc6, 0x96, 0x73, 0xe9,
712
            0x9d, 0xc9, 0x2a, 0x77, 0x82, 0xa9, 0xe6, 0x4b, 0x53, 0xcc, 0x83, 0x80, 0x4a, 0xf3,
713
            0xcd, 0xe3, 0x50, 0x4e, 0x45, 0x4a, 0x3a, 0x42, 0x00, 0x4b, 0x4d, 0xbe, 0x4c, 0x88,
714
            0x24, 0xf2, 0x4b, 0x6b, 0xbd, 0x79, 0xeb, 0x74, 0xbc, 0xe8, 0x7d, 0xff, 0x4b, 0x3d,
715
            0xa7, 0xd6, 0x0d, 0xef, 0x9c, 0x5b, 0xb3, 0xec, 0x94, 0x97, 0xcc, 0x8b, 0x41, 0xe1,
716
            0x9c, 0xcc, 0x1a, 0x03, 0x58, 0xc4, 0xfb, 0xd0, 0xc0, 0x10, 0xe2, 0xa0, 0xc9, 0xac,
717
            0xa7, 0xbb, 0x50, 0xf6, 0x5c, 0x87, 0x68, 0x0f, 0x42, 0x93, 0x3f, 0x2e, 0x28, 0x28,
718
            0x76, 0x83, 0x9b, 0xeb, 0x12, 0xe0, 0x4f, 0xc5, 0xb0, 0x8d, 0x14, 0xda, 0x3b, 0xdf,
719
            0xd3, 0x4b, 0x80, 0xd1, 0xfc, 0x87, 0x85, 0xae, 0x54, 0xc7, 0x45, 0xc9, 0x38, 0x43,
720
            0xa7, 0x9f, 0xdd, 0xa9, 0x71, 0xa7, 0x52, 0x36, 0x82, 0xff, 0x49, 0x55, 0xdb, 0x84,
721
            0xc2, 0x95, 0xad, 0x45, 0x80, 0xc6, 0x02, 0x80, 0xf8, 0xfc, 0x86, 0x79, 0xae, 0xb9,
722
            0x57, 0xe7, 0x3b, 0x33, 0x64, 0xa8,
723
        ];
724
        let data_u32 = unsafe { data.align_to::<u32>().1 };
725

726
        for i in 0..data.len() {
727
            let mut reader = BufBitReader::<LE, _>::new(MemWordReader::new_inf(&data_u32));
728
            let mut buffer = vec![0; i];
729
            assert_eq!(reader.read(&mut buffer)?, i);
730
            assert_eq!(&buffer, &data[..i]);
731

732
            let mut reader = BufBitReader::<BE, _>::new(MemWordReader::new_inf(&data_u32));
733
            let mut buffer = vec![0; i];
734
            assert_eq!(reader.read(&mut buffer)?, i);
735
            assert_eq!(&buffer, &data[..i]);
736
        }
737
        Ok(())
738
    }
739

740
    macro_rules! test_buf_bit_reader {
741
        ($f: ident, $word:ty) => {
742
            #[test]
743
            fn $f() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
744
                #[allow(unused_imports)]
745
                use crate::{
746
                    codes::{GammaRead, GammaWrite},
747
                    prelude::{
748
                        BufBitWriter, DeltaRead, DeltaWrite, MemWordReader, len_delta, len_gamma,
749
                    },
750
                };
751
                use rand::{RngExt, SeedableRng, rngs::SmallRng};
752

753
                let mut buffer_be: Vec<$word> = vec![];
754
                let mut buffer_le: Vec<$word> = vec![];
755
                let mut big = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(&mut buffer_be));
756
                let mut little = BufBitWriter::<LE, _>::new(MemWordWriterVec::new(&mut buffer_le));
757

758
                let mut r = SmallRng::seed_from_u64(0);
759
                const ITER: usize = 1_000_000;
760

761
                for _ in 0..ITER {
762
                    let value = r.random_range(0..128);
763
                    assert_eq!(big.write_gamma(value)?, len_gamma(value));
764
                    let value = r.random_range(0..128);
765
                    assert_eq!(little.write_gamma(value)?, len_gamma(value));
766
                    let value = r.random_range(0..128);
767
                    assert_eq!(big.write_gamma(value)?, len_gamma(value));
768
                    let value = r.random_range(0..128);
769
                    assert_eq!(little.write_gamma(value)?, len_gamma(value));
770
                    let value = r.random_range(0..128);
771
                    assert_eq!(big.write_delta(value)?, len_delta(value));
772
                    let value = r.random_range(0..128);
773
                    assert_eq!(little.write_delta(value)?, len_delta(value));
774
                    let value = r.random_range(0..128);
775
                    assert_eq!(big.write_delta(value)?, len_delta(value));
776
                    let value = r.random_range(0..128);
777
                    assert_eq!(little.write_delta(value)?, len_delta(value));
778
                    let n_bits = r.random_range(0..=64);
779
                    if n_bits == 0 {
780
                        big.write_bits(0, 0)?;
781
                    } else {
782
                        big.write_bits(1, n_bits)?;
783
                    }
784
                    let n_bits = r.random_range(0..=64);
785
                    if n_bits == 0 {
786
                        little.write_bits(0, 0)?;
787
                    } else {
788
                        little.write_bits(1, n_bits)?;
789
                    }
790
                    let value = r.random_range(0..128);
791
                    assert_eq!(big.write_unary(value)?, value as usize + 1);
792
                    let value = r.random_range(0..128);
793
                    assert_eq!(little.write_unary(value)?, value as usize + 1);
794
                }
795

796
                drop(big);
797
                drop(little);
798

799
                type ReadWord = $word;
800

801
                #[allow(clippy::size_of_in_element_count)] // false positive
802
                let be_trans: &[ReadWord] = unsafe {
803
                    core::slice::from_raw_parts(
804
                        buffer_be.as_ptr() as *const ReadWord,
805
                        buffer_be.len()
806
                            * (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
807
                    )
808
                };
809

810
                #[allow(clippy::size_of_in_element_count)] // false positive
811
                let le_trans: &[ReadWord] = unsafe {
812
                    core::slice::from_raw_parts(
813
                        buffer_le.as_ptr() as *const ReadWord,
814
                        buffer_le.len()
815
                            * (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
816
                    )
817
                };
818

819
                let mut big_buff = BufBitReader::<BE, _>::new(MemWordReader::new_inf(be_trans));
820
                let mut little_buff = BufBitReader::<LE, _>::new(MemWordReader::new_inf(le_trans));
821

822
                let mut r = SmallRng::seed_from_u64(0);
823

824
                for _ in 0..ITER {
825
                    assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
826
                    assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
827
                    assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
828
                    assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
829
                    assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
830
                    assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
831
                    assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
832
                    assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
833
                    let n_bits = r.random_range(0..=64);
834
                    if n_bits == 0 {
835
                        assert_eq!(big_buff.read_bits(0)?, 0);
836
                    } else {
837
                        assert_eq!(big_buff.read_bits(n_bits)?, 1);
838
                    }
839
                    let n_bits = r.random_range(0..=64);
840
                    if n_bits == 0 {
841
                        assert_eq!(little_buff.read_bits(0)?, 0);
842
                    } else {
843
                        assert_eq!(little_buff.read_bits(n_bits)?, 1);
844
                    }
845

846
                    assert_eq!(big_buff.read_unary()?, r.random_range(0..128));
847
                    assert_eq!(little_buff.read_unary()?, r.random_range(0..128));
848
                }
849

850
                Ok(())
851
            }
852
        };
853
    }
854

855
    test_buf_bit_reader!(test_u64, u64);
856
    test_buf_bit_reader!(test_u32, u32);
857

858
    test_buf_bit_reader!(test_u16, u16);
859
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc