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

vigna / dsi-bitstream-rs / 22237719643

20 Feb 2026 07:16PM UTC coverage: 54.824% (-0.5%) from 55.302%
22237719643

push

github

vigna
Cosmetic changes

2108 of 3845 relevant lines covered (54.82%)

3125840.71 hits per line

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

62.86
/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 common_traits::*;
10

11
use crate::codes::params::{DefaultReadParams, ReadParams};
12
use crate::traits::*;
13
use core::convert::Infallible;
14
use core::error::Error;
15
use core::{mem, ptr};
16
#[cfg(feature = "mem_dbg")]
17
use mem_dbg::{MemDbg, MemSize};
18

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

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

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

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

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

102
impl<E: Endianness, WR: WordRead + Clone, RP: ReadParams> core::clone::Clone
103
    for BufBitReader<E, WR, RP>
104
where
105
    WR::Word: DoubleType,
106
{
107
    fn clone(&self) -> Self {
×
108
        Self {
109
            backend: self.backend.clone(),
×
110
            buffer: self.buffer,
×
111
            bits_in_buffer: self.bits_in_buffer,
×
112
            _marker: core::marker::PhantomData,
113
        }
114
    }
115
}
116

117
impl<E: Endianness, WR: WordRead, RP: ReadParams> BufBitReader<E, WR, RP>
118
where
119
    WR::Word: DoubleType,
120
{
121
    /// Creates a new [`BufBitReader`] around a [`WordRead`].
122
    ///
123
    /// # Example
124
    /// ```
125
    /// use dsi_bitstream::prelude::*;
126
    /// let words: [u32; 2] = [0x0043b59f, 0xccf16077];
127
    /// let word_reader = MemWordReader::new(&words);
128
    /// let mut buf_bit_reader = <BufBitReader<BE, _>>::new(word_reader);
129
    /// ```
130
    #[must_use]
131
    pub fn new(backend: WR) -> Self {
483,933✔
132
        Self {
133
            backend,
134
            buffer: BB::<WR>::ZERO,
135
            bits_in_buffer: 0,
136
            _marker: core::marker::PhantomData,
137
        }
138
    }
139

140
    ///  Return the backend, consuming this reader.
141
    pub fn into_inner(self) -> Result<WR, Infallible> {
×
142
        // SAFETY: forget(self) prevents double dropping backend
143
        let backend = unsafe { ptr::read(&self.backend) };
×
144
        mem::forget(self);
×
145
        Ok(backend)
×
146
    }
147
}
148

149
//
150
// Big-endian implementation
151
//
152

153
impl<WR: WordRead, RP: ReadParams> BufBitReader<BE, WR, RP>
154
where
155
    WR::Word: DoubleType,
156
{
157
    /// Ensure that in the buffer there are at least `WR::Word::BITS` bits to read.
158
    /// This method can be called only if there are at least
159
    /// `WR::Word::BITS` free bits in the buffer.
160
    #[inline(always)]
161
    fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
6,361,707✔
162
        debug_assert!(BB::<WR>::BITS - self.bits_in_buffer >= WR::Word::BITS);
12,723,414✔
163

164
        let new_word: BB<WR> = self.backend.read_word()?.to_be().upcast();
38,170,242✔
165
        self.bits_in_buffer += WR::Word::BITS;
6,361,707✔
166
        self.buffer |= new_word << (BB::<WR>::BITS - self.bits_in_buffer);
12,723,414✔
167
        Ok(())
6,361,707✔
168
    }
169
}
170

171
impl<WR: WordRead, RP: ReadParams> BitRead<BE> for BufBitReader<BE, WR, RP>
172
where
173
    WR::Word: DoubleType + UpcastableInto<u64>,
174
    BB<WR>: CastableInto<u64>,
175
{
176
    type Error = <WR as WordRead>::Error;
177
    type PeekWord = BB<WR>;
178
    const PEEK_BITS: usize = <WR as WordRead>::Word::BITS + 1;
179

180
    #[inline(always)]
181
    fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
14,018,256✔
182
        debug_assert!(n_bits > 0);
28,036,512✔
183
        debug_assert!(n_bits <= Self::PeekWord::BITS);
28,036,512✔
184

185
        // A peek can do at most one refill, otherwise we might lose data
186
        if n_bits > self.bits_in_buffer {
14,018,256✔
187
            self.refill()?;
12,723,414✔
188
        }
189

190
        debug_assert!(n_bits <= self.bits_in_buffer);
28,036,512✔
191

192
        // Move the n_bits highest bits of the buffer to the lowest
193
        Ok(self.buffer >> (BB::<WR>::BITS - n_bits))
14,018,256✔
194
    }
195

196
    #[inline(always)]
197
    fn skip_bits_after_peek(&mut self, n_bits: usize) {
14,011,766✔
198
        self.bits_in_buffer -= n_bits;
14,011,766✔
199
        self.buffer <<= n_bits;
14,011,766✔
200
    }
201

202
    #[inline]
203
    fn read_bits(&mut self, mut n_bits: usize) -> Result<u64, Self::Error> {
110,514,298✔
204
        debug_assert!(n_bits <= 64);
221,028,596✔
205
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
221,028,596✔
206

207
        // most common path, we just read the buffer
208
        if n_bits <= self.bits_in_buffer {
110,514,298✔
209
            // Valid right shift of BB::<WR>::BITS - n_bits, even when n_bits is zero
210
            let result: u64 = (self.buffer >> (BB::<WR>::BITS - n_bits - 1) >> 1_u32).cast();
382,963,312✔
211
            self.bits_in_buffer -= n_bits;
95,740,828✔
212
            self.buffer <<= n_bits;
95,740,828✔
213
            return Ok(result);
95,740,828✔
214
        }
215

216
        let mut result: u64 =
29,546,940✔
217
            (self.buffer >> (BB::<WR>::BITS - 1 - self.bits_in_buffer) >> 1_u8).cast();
44,320,410✔
218
        n_bits -= self.bits_in_buffer;
14,773,470✔
219

220
        // Directly read to the result without updating the buffer
221
        while n_bits > WR::Word::BITS {
22,289,969✔
222
            let new_word: u64 = self.backend.read_word()?.to_be().upcast();
45,098,994✔
223
            result = (result << WR::Word::BITS) | new_word;
7,516,499✔
224
            n_bits -= WR::Word::BITS;
7,516,499✔
225
        }
226

227
        debug_assert!(n_bits > 0);
29,546,940✔
228
        debug_assert!(n_bits <= WR::Word::BITS);
29,546,940✔
229

230
        // get the final word
231
        let new_word = self.backend.read_word()?.to_be();
59,093,880✔
232
        self.bits_in_buffer = WR::Word::BITS - n_bits;
14,773,470✔
233
        // compose the remaining bits
234
        let upcast: u64 = new_word.upcast();
59,093,880✔
235
        let final_bits: u64 = (upcast >> self.bits_in_buffer).downcast();
59,093,880✔
236
        result = (result << (n_bits - 1) << 1) | final_bits;
14,773,470✔
237
        // and put the rest in the buffer
238
        self.buffer = (UpcastableInto::<BB<WR>>::upcast(new_word)
29,546,940✔
239
            << (BB::<WR>::BITS - self.bits_in_buffer - 1))
14,773,470✔
240
            << 1;
14,773,470✔
241

242
        Ok(result)
14,773,470✔
243
    }
244

245
    #[inline]
246
    fn read_unary(&mut self) -> Result<u64, Self::Error> {
24,115,410✔
247
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
48,230,820✔
248

249
        // count the zeros from the left
250
        let zeros: usize = self.buffer.leading_zeros() as _;
96,461,640✔
251

252
        // if we encountered an 1 in the bits_in_buffer we can return
253
        if zeros < self.bits_in_buffer {
24,115,410✔
254
            self.buffer = self.buffer << zeros << 1;
11,666,668✔
255
            self.bits_in_buffer -= zeros + 1;
11,666,668✔
256
            return Ok(zeros as u64);
11,666,668✔
257
        }
258

259
        let mut result: u64 = self.bits_in_buffer as _;
37,346,226✔
260

261
        loop {
×
262
            let new_word = self.backend.read_word()?.to_be();
130,598,008✔
263

264
            if new_word != WR::Word::ZERO {
32,649,502✔
265
                let zeros: usize = new_word.leading_zeros() as _;
49,794,968✔
266
                self.buffer =
12,448,742✔
267
                    UpcastableInto::<BB<WR>>::upcast(new_word) << (WR::Word::BITS + zeros) << 1;
24,897,484✔
268
                self.bits_in_buffer = WR::Word::BITS - zeros - 1;
12,448,742✔
269
                return Ok(result + zeros as u64);
12,448,742✔
270
            }
271
            result += WR::Word::BITS as u64;
20,200,760✔
272
        }
273
    }
274

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

285
        n_bits -= self.bits_in_buffer;
114,440✔
286

287
        // skip words as needed
288
        while n_bits > WR::Word::BITS {
114,440✔
289
            let _ = self.backend.read_word()?;
×
290
            n_bits -= WR::Word::BITS;
×
291
        }
292

293
        // get the final word
294
        let new_word = self.backend.read_word()?.to_be();
457,760✔
295
        self.bits_in_buffer = WR::Word::BITS - n_bits;
114,440✔
296

297
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word)
343,320✔
298
            << (BB::<WR>::BITS - 1 - self.bits_in_buffer)
114,440✔
299
            << 1;
114,440✔
300

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

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

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

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

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

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

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

348
        assert!(n > 0);
×
349
        let new_word = self
×
350
            .backend
×
351
            .read_word()
352
            .map_err(CopyError::ReadError)?
×
353
            .to_be();
354
        self.bits_in_buffer = WR::Word::BITS - n as usize;
×
355
        bit_write
×
356
            .write_bits((new_word >> self.bits_in_buffer).upcast(), n as usize)
×
357
            .map_err(CopyError::WriteError)?;
×
358
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word)
×
359
            .rotate_right(WR::Word::BITS as u32 - n as u32);
×
360

361
        Ok(())
×
362
    }
363
}
364

365
impl<
366
    E: Error + Send + Sync + 'static,
367
    WR: WordRead<Error = E> + WordSeek<Error = E>,
368
    RP: ReadParams,
369
> BitSeek for BufBitReader<BE, WR, RP>
370
where
371
    WR::Word: DoubleType,
372
{
373
    type Error = <WR as WordSeek>::Error;
374

375
    #[inline]
376
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
36,143✔
377
        Ok(self.backend.word_pos()? * WR::Word::BITS as u64 - self.bits_in_buffer as u64)
144,572✔
378
    }
379

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

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

400
impl<WR: WordRead, RP: ReadParams> BufBitReader<LE, WR, RP>
401
where
402
    WR::Word: DoubleType,
403
{
404
    /// Ensure that in the buffer there are at least `WR::Word::BITS` bits to read.
405
    /// This method can be called only if there are at least
406
    /// `WR::Word::BITS` free bits in the buffer.
407
    #[inline(always)]
408
    fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
6,357,086✔
409
        debug_assert!(BB::<WR>::BITS - self.bits_in_buffer >= WR::Word::BITS);
12,714,172✔
410

411
        let new_word: BB<WR> = self.backend.read_word()?.to_le().upcast();
38,142,516✔
412
        self.buffer |= new_word << self.bits_in_buffer;
12,714,172✔
413
        self.bits_in_buffer += WR::Word::BITS;
6,357,086✔
414
        Ok(())
6,357,086✔
415
    }
416
}
417

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

427
    #[inline(always)]
428
    fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
14,018,375✔
429
        debug_assert!(n_bits > 0);
28,036,750✔
430
        debug_assert!(n_bits <= Self::PeekWord::BITS);
28,036,750✔
431

432
        // A peek can do at most one refill, otherwise we might lose data
433
        if n_bits > self.bits_in_buffer {
14,018,375✔
434
            self.refill()?;
12,714,172✔
435
        }
436

437
        debug_assert!(n_bits <= self.bits_in_buffer);
28,036,750✔
438

439
        // Keep the n_bits lowest bits of the buffer
440
        let sham = BB::<WR>::BITS - n_bits;
28,036,750✔
441
        Ok((self.buffer << sham) >> sham)
14,018,375✔
442
    }
443

444
    #[inline(always)]
445
    fn skip_bits_after_peek(&mut self, n_bits: usize) {
14,011,884✔
446
        self.bits_in_buffer -= n_bits;
14,011,884✔
447
        self.buffer >>= n_bits;
14,011,884✔
448
    }
449

450
    #[inline]
451
    fn read_bits(&mut self, mut n_bits: usize) -> Result<u64, Self::Error> {
110,512,324✔
452
        debug_assert!(n_bits <= 64);
221,024,648✔
453
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
221,024,648✔
454

455
        // most common path, we just read the buffer
456
        if n_bits <= self.bits_in_buffer {
110,512,324✔
457
            let result: u64 = (self.buffer & ((BB::<WR>::ONE << n_bits) - BB::<WR>::ONE)).cast();
382,940,964✔
458
            self.bits_in_buffer -= n_bits;
95,735,241✔
459
            self.buffer >>= n_bits;
95,735,241✔
460
            return Ok(result);
95,735,241✔
461
        }
462

463
        let mut result: u64 = self.buffer.cast();
59,108,332✔
464
        let mut bits_in_res = self.bits_in_buffer;
29,554,166✔
465

466
        // Directly read to the result without updating the buffer
467
        while n_bits > WR::Word::BITS + bits_in_res {
22,280,564✔
468
            let new_word: u64 = self.backend.read_word()?.to_le().upcast();
45,020,886✔
469
            result |= new_word << bits_in_res;
7,503,481✔
470
            bits_in_res += WR::Word::BITS;
7,503,481✔
471
        }
472

473
        n_bits -= bits_in_res;
14,777,083✔
474

475
        debug_assert!(n_bits > 0);
29,554,166✔
476
        debug_assert!(n_bits <= WR::Word::BITS);
29,554,166✔
477

478
        // get the final word
479
        let new_word = self.backend.read_word()?.to_le();
59,108,332✔
480
        self.bits_in_buffer = WR::Word::BITS - n_bits;
14,777,083✔
481
        // compose the remaining bits
482
        let sham = 64 - n_bits;
29,554,166✔
483
        let upcast: u64 = new_word.upcast();
59,108,332✔
484
        let final_bits: u64 = ((upcast << sham) >> sham).downcast();
59,108,332✔
485
        result |= final_bits << bits_in_res;
14,777,083✔
486
        // and put the rest in the buffer
487
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> n_bits;
29,554,166✔
488

489
        Ok(result)
14,777,083✔
490
    }
491

492
    #[inline]
493
    fn read_unary(&mut self) -> Result<u64, Self::Error> {
24,114,425✔
494
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
48,228,850✔
495

496
        // count the zeros from the right
497
        let zeros: usize = self.buffer.trailing_zeros() as usize;
72,343,275✔
498

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

506
        let mut result: u64 = self.bits_in_buffer as _;
37,346,421✔
507

508
        loop {
×
509
            let new_word = self.backend.read_word()?.to_le();
130,485,276✔
510

511
            if new_word != WR::Word::ZERO {
32,621,319✔
512
                let zeros: usize = new_word.trailing_zeros() as _;
49,795,228✔
513
                self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> zeros >> 1;
24,897,614✔
514
                self.bits_in_buffer = WR::Word::BITS - zeros - 1;
12,448,807✔
515
                return Ok(result + zeros as u64);
12,448,807✔
516
            }
517
            result += WR::Word::BITS as u64;
20,172,512✔
518
        }
519
    }
520

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

531
        n_bits -= self.bits_in_buffer;
114,441✔
532

533
        // skip words as needed
534
        while n_bits > WR::Word::BITS {
114,441✔
535
            let _ = self.backend.read_word()?;
×
536
            n_bits -= WR::Word::BITS;
×
537
        }
538

539
        // get the final word
540
        let new_word = self.backend.read_word()?.to_le();
457,764✔
541
        self.bits_in_buffer = WR::Word::BITS - n_bits;
114,441✔
542
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> n_bits;
228,882✔
543

544
        Ok(())
114,441✔
545
    }
546

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

555
        #[allow(unused_mut)]
556
        let mut self_buffer_u64: u64 = self.buffer.cast();
×
557

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

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

570
        self.buffer >>= from_buffer;
×
571
        n -= from_buffer;
×
572

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

578
        while n > WR::Word::BITS as u64 {
×
579
            bit_write
×
580
                .write_bits(
581
                    self.backend
×
582
                        .read_word()
×
583
                        .map_err(CopyError::ReadError)?
×
584
                        .to_le()
×
585
                        .upcast(),
×
586
                    WR::Word::BITS,
×
587
                )
588
                .map_err(CopyError::WriteError)?;
×
589
            n -= WR::Word::BITS as u64;
×
590
        }
591

592
        assert!(n > 0);
×
593
        let new_word = self
×
594
            .backend
×
595
            .read_word()
596
            .map_err(CopyError::ReadError)?
×
597
            .to_le();
598
        self.bits_in_buffer = WR::Word::BITS - n as usize;
×
599

600
        #[allow(unused_mut)]
601
        let mut new_word_u64: u64 = new_word.upcast();
×
602

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

611
        bit_write
×
612
            .write_bits(new_word_u64, n as usize)
×
613
            .map_err(CopyError::WriteError)?;
×
614
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> n;
×
615
        Ok(())
×
616
    }
617
}
618

619
impl<
620
    E: Error + Send + Sync + 'static,
621
    WR: WordRead<Error = E> + WordSeek<Error = E>,
622
    RP: ReadParams,
623
> BitSeek for BufBitReader<LE, WR, RP>
624
where
625
    WR::Word: DoubleType,
626
{
627
    type Error = <WR as WordSeek>::Error;
628

629
    #[inline]
630
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
36,243✔
631
        Ok(self.backend.word_pos()? * WR::Word::BITS as u64 - self.bits_in_buffer as u64)
144,972✔
632
    }
633

634
    #[inline]
635
    fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
×
636
        self.backend
×
637
            .set_word_pos(bit_index / WR::Word::BITS as u64)?;
×
638

639
        let bit_offset = (bit_index % WR::Word::BITS as u64) as usize;
×
640
        self.buffer = BB::<WR>::ZERO;
×
641
        self.bits_in_buffer = 0;
×
642
        if bit_offset != 0 {
×
643
            let new_word: BB<WR> = self.backend.read_word()?.to_le().upcast();
×
644
            self.bits_in_buffer = WR::Word::BITS - bit_offset;
×
645
            self.buffer = new_word >> bit_offset;
×
646
        }
647
        Ok(())
×
648
    }
649
}
650

651
#[cfg(feature = "std")]
652
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<LE, WR, RP>
653
where
654
    WR::Word: DoubleType + UpcastableInto<u64>,
655
    BB<WR>: CastableInto<u64>,
656
{
657
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1,305✔
658
        let mut iter = buf.chunks_exact_mut(8);
3,915✔
659

660
        for chunk in &mut iter {
3,878✔
661
            let word = self
5,146✔
662
                .read_bits(64)
663
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
2,573✔
664
            chunk.copy_from_slice(&word.to_le_bytes());
7,719✔
665
        }
666

667
        let rem = iter.into_remainder();
3,915✔
668
        if !rem.is_empty() {
1,305✔
669
            let word = self
2,452✔
670
                .read_bits(rem.len() * 8)
2,452✔
671
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
1,226✔
672
            rem.copy_from_slice(&word.to_le_bytes()[..rem.len()]);
4,904✔
673
        }
674

675
        Ok(buf.len())
1,305✔
676
    }
677
}
678

679
#[cfg(feature = "std")]
680
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<BE, WR, RP>
681
where
682
    WR::Word: DoubleType + UpcastableInto<u64>,
683
    BB<WR>: CastableInto<u64>,
684
{
685
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1,305✔
686
        let mut iter = buf.chunks_exact_mut(8);
3,915✔
687

688
        for chunk in &mut iter {
3,878✔
689
            let word = self
5,146✔
690
                .read_bits(64)
691
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
2,573✔
692
            chunk.copy_from_slice(&word.to_be_bytes());
7,719✔
693
        }
694

695
        let rem = iter.into_remainder();
3,915✔
696
        if !rem.is_empty() {
1,305✔
697
            let word = self
2,452✔
698
                .read_bits(rem.len() * 8)
2,452✔
699
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
1,226✔
700
            rem.copy_from_slice(&word.to_be_bytes()[8 - rem.len()..]);
4,904✔
701
        }
702

703
        Ok(buf.len())
1,305✔
704
    }
705
}
706

707
#[cfg(test)]
708
#[cfg(feature = "std")]
709
mod test {
710
    use super::*;
711
    use crate::prelude::{MemWordReader, MemWordWriterVec};
712
    use std::io::Read;
713

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

732
        for i in 0..data.len() {
733
            let mut reader = BufBitReader::<LE, _>::new(MemWordReader::new(&data_u32));
734
            let mut buffer = vec![0; i];
735
            assert_eq!(reader.read(&mut buffer).unwrap(), i);
736
            assert_eq!(&buffer, &data[..i]);
737

738
            let mut reader = BufBitReader::<BE, _>::new(MemWordReader::new(&data_u32));
739
            let mut buffer = vec![0; i];
740
            assert_eq!(reader.read(&mut buffer).unwrap(), i);
741
            assert_eq!(&buffer, &data[..i]);
742
        }
743
    }
744

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

758
                let mut buffer_be: Vec<$word> = vec![];
759
                let mut buffer_le: Vec<$word> = vec![];
760
                let mut big = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(&mut buffer_be));
761
                let mut little = BufBitWriter::<LE, _>::new(MemWordWriterVec::new(&mut buffer_le));
762

763
                let mut r = SmallRng::seed_from_u64(0);
764
                const ITER: usize = 1_000_000;
765

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

801
                drop(big);
802
                drop(little);
803

804
                type ReadWord = $word;
805

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

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

824
                let mut big_buff = BufBitReader::<BE, _>::new(MemWordReader::new(be_trans));
825
                let mut little_buff = BufBitReader::<LE, _>::new(MemWordReader::new(le_trans));
826

827
                let mut r = SmallRng::seed_from_u64(0);
828

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

851
                    assert_eq!(big_buff.read_unary()?, r.random_range(0..128));
852
                    assert_eq!(little_buff.read_unary()?, r.random_range(0..128));
853
                }
854

855
                Ok(())
856
            }
857
        };
858
    }
859

860
    test_buf_bit_reader!(test_u64, u64);
861
    test_buf_bit_reader!(test_u32, u32);
862

863
    test_buf_bit_reader!(test_u16, u16);
864
}
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