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

vigna / dsi-bitstream-rs / 19987290132

06 Dec 2025 10:36AM UTC coverage: 52.821% (+8.3%) from 44.521%
19987290132

push

github

vigna
Fixed compilation errors without std

2 of 2 new or added lines in 2 files covered. (100.0%)

133 existing lines in 3 files now uncovered.

1910 of 3616 relevant lines covered (52.82%)

3105897.12 hits per line

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

62.99
/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
{
UNCOV
107
    fn clone(&self) -> Self {
×
108
        Self {
109
            backend: self.backend.clone(),
×
UNCOV
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 {
476,369✔
132
        #[cfg(feature = "std")]
133
        check_tables(WR::Word::BITS + 1);
952,738✔
134
        Self {
135
            backend,
136
            buffer: BB::<WR>::ZERO,
137
            bits_in_buffer: 0,
138
            _marker: core::marker::PhantomData,
139
        }
140
    }
141

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

151
//
152
// Big-endian implementation
153
//
154

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

166
        let new_word: BB<WR> = self.backend.read_word()?.to_be().upcast();
38,155,770✔
167
        self.bits_in_buffer += WR::Word::BITS;
6,359,295✔
168
        self.buffer |= new_word << (BB::<WR>::BITS - self.bits_in_buffer);
12,718,590✔
169
        Ok(())
6,359,295✔
170
    }
171
}
172

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

181
    #[inline(always)]
182
    fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
14,010,902✔
183
        debug_assert!(n_bits > 0);
28,021,804✔
184
        debug_assert!(n_bits <= Self::PeekWord::BITS);
28,021,804✔
185

186
        // A peek can do at most one refill, otherwise we might lose data
187
        if n_bits > self.bits_in_buffer {
14,010,902✔
188
            self.refill()?;
12,718,590✔
189
        }
190

191
        debug_assert!(n_bits <= self.bits_in_buffer);
28,021,804✔
192

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

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

203
    #[inline]
204
    fn read_bits(&mut self, mut n_bits: usize) -> Result<u64, Self::Error> {
110,481,688✔
205
        debug_assert!(n_bits <= 64);
220,963,376✔
206
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
220,963,376✔
207

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

217
        let mut result: u64 =
29,524,064✔
218
            (self.buffer >> (BB::<WR>::BITS - 1 - self.bits_in_buffer) >> 1_u8).cast();
44,286,096✔
219
        n_bits -= self.bits_in_buffer;
14,762,032✔
220

221
        // Directly read to the result without updating the buffer
222
        while n_bits > WR::Word::BITS {
22,273,948✔
223
            let new_word: u64 = self.backend.read_word()?.to_be().upcast();
45,071,496✔
224
            result = (result << WR::Word::BITS) | new_word;
7,511,916✔
225
            n_bits -= WR::Word::BITS;
7,511,916✔
226
        }
227

228
        debug_assert!(n_bits > 0);
29,524,064✔
229
        debug_assert!(n_bits <= WR::Word::BITS);
29,524,064✔
230

231
        // get the final word
232
        let new_word = self.backend.read_word()?.to_be();
59,048,128✔
233
        self.bits_in_buffer = WR::Word::BITS - n_bits;
14,762,032✔
234
        // compose the remaining bits
235
        let upcasted: u64 = new_word.upcast();
59,048,128✔
236
        let final_bits: u64 = (upcasted >> self.bits_in_buffer).downcast();
59,048,128✔
237
        result = (result << (n_bits - 1) << 1) | final_bits;
14,762,032✔
238
        // and put the rest in the buffer
239
        self.buffer = (UpcastableInto::<BB<WR>>::upcast(new_word)
29,524,064✔
240
            << (BB::<WR>::BITS - self.bits_in_buffer - 1))
14,762,032✔
241
            << 1;
14,762,032✔
242

243
        Ok(result)
14,762,032✔
244
    }
245

246
    #[inline]
247
    fn read_unary(&mut self) -> Result<u64, Self::Error> {
24,107,311✔
248
        debug_assert!(self.bits_in_buffer < BB::<WR>::BITS);
48,214,622✔
249

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

253
        // if we encountered an 1 in the bits_in_buffer we can return
254
        if zeros < self.bits_in_buffer {
24,107,311✔
255
            self.buffer = self.buffer << zeros << 1;
11,663,563✔
256
            self.bits_in_buffer -= zeros + 1;
11,663,563✔
257
            return Ok(zeros as u64);
11,663,563✔
258
        }
259

260
        let mut result: u64 = self.bits_in_buffer as _;
37,331,244✔
261

262
        loop {
×
263
            let new_word = self.backend.read_word()?.to_be();
130,159,408✔
264

265
            if new_word != WR::Word::ZERO {
32,539,852✔
266
                let zeros: usize = new_word.leading_zeros() as _;
49,774,992✔
267
                self.buffer =
12,443,748✔
268
                    UpcastableInto::<BB<WR>>::upcast(new_word) << (WR::Word::BITS + zeros) << 1;
24,887,496✔
269
                self.bits_in_buffer = WR::Word::BITS - zeros - 1;
12,443,748✔
270
                return Ok(result + zeros as u64);
12,443,748✔
271
            }
272
            result += WR::Word::BITS as u64;
20,096,104✔
273
        }
274
    }
275

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

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

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

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

298
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word)
343,320✔
299
            << (BB::<WR>::BITS - 1 - self.bits_in_buffer)
114,440✔
300
            << 1;
114,440✔
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.cast();
×
316

317
        #[cfg(feature = "checks")]
318
        {
319
            // Clean up in case checks are enabled
UNCOV
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)
×
UNCOV
327
            .map_err(CopyError::WriteError)?;
×
328
        n -= from_buffer;
×
329

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

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

349
        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 = WR::Word::BITS - n as usize;
×
356
        bit_write
×
357
            .write_bits((new_word >> self.bits_in_buffer).upcast(), n as usize)
×
UNCOV
358
            .map_err(CopyError::WriteError)?;
×
359
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word)
×
UNCOV
360
            .rotate_right(WR::Word::BITS as u32 - n as u32);
×
361

UNCOV
362
        Ok(())
×
363
    }
364
}
365

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

376
    #[inline]
377
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
3,225✔
378
        Ok(self.backend.word_pos()? * WR::Word::BITS as u64 - self.bits_in_buffer as u64)
12,900✔
379
    }
380

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

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

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

412
        let new_word: BB<WR> = self.backend.read_word()?.to_le().upcast();
38,128,044✔
413
        self.buffer |= new_word << self.bits_in_buffer;
12,709,348✔
414
        self.bits_in_buffer += WR::Word::BITS;
6,354,674✔
415
        Ok(())
6,354,674✔
416
    }
417
}
418

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

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

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

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

439
        // Keep the n_bits lowest bits of the buffer
440
        let shamt = BB::<WR>::BITS - n_bits;
28,022,042✔
441
        Ok((self.buffer << shamt) >> shamt)
14,011,021✔
442
    }
443

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

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

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

463
        let mut result: u64 = self.buffer.cast();
59,062,580✔
464
        let mut bits_in_res = self.bits_in_buffer;
29,531,290✔
465

466
        // Directly read to the result without updating the buffer
467
        while n_bits > WR::Word::BITS + bits_in_res {
22,264,543✔
468
            let new_word: u64 = self.backend.read_word()?.to_le().upcast();
44,993,388✔
469
            result |= new_word << bits_in_res;
7,498,898✔
470
            bits_in_res += WR::Word::BITS;
7,498,898✔
471
        }
472

473
        n_bits -= bits_in_res;
14,765,645✔
474

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

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

489
        Ok(result)
14,765,645✔
490
    }
491

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

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

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

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

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

511
            if new_word != WR::Word::ZERO {
32,511,669✔
512
                let zeros: usize = new_word.trailing_zeros() as _;
49,775,252✔
513
                self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> zeros >> 1;
24,887,626✔
514
                self.bits_in_buffer = WR::Word::BITS - zeros - 1;
12,443,813✔
515
                return Ok(result + zeros as u64);
12,443,813✔
516
            }
517
            result += WR::Word::BITS as u64;
20,067,856✔
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✔
UNCOV
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>> {
UNCOV
553
        let from_buffer = Ord::min(n, self.bits_in_buffer as _);
×
554

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

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

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

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

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

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

UNCOV
592
        assert!(n > 0);
×
UNCOV
593
        let new_word = self
×
UNCOV
594
            .backend
×
595
            .read_word()
UNCOV
596
            .map_err(CopyError::ReadError)?
×
597
            .to_le();
UNCOV
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
×
UNCOV
612
            .write_bits(new_word_u64, n as usize)
×
613
            .map_err(CopyError::WriteError)?;
×
UNCOV
614
        self.buffer = UpcastableInto::<BB<WR>>::upcast(new_word) >> n;
×
UNCOV
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> {
3,325✔
631
        Ok(self.backend.word_pos()? * WR::Word::BITS as u64 - self.bits_in_buffer as u64)
13,300✔
632
    }
633

634
    #[inline]
UNCOV
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

UNCOV
639
        let bit_offset = (bit_index % WR::Word::BITS as u64) as usize;
×
UNCOV
640
        self.buffer = BB::<WR>::ZERO;
×
UNCOV
641
        self.bits_in_buffer = 0;
×
UNCOV
642
        if bit_offset != 0 {
×
UNCOV
643
            let new_word: BB<WR> = self.backend.read_word()?.to_le().upcast();
×
UNCOV
644
            self.bits_in_buffer = WR::Word::BITS - bit_offset;
×
UNCOV
645
            self.buffer = new_word >> bit_offset;
×
646
        }
UNCOV
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> {
167✔
658
        let mut iter = buf.chunks_exact_mut(8);
501✔
659

660
        for chunk in &mut iter {
1,700✔
661
            let word = self
3,066✔
662
                .read_bits(64)
663
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
1,533✔
664
            chunk.copy_from_slice(&word.to_le_bytes());
4,599✔
665
        }
666

667
        let rem = iter.into_remainder();
501✔
668
        if !rem.is_empty() {
167✔
669
            let word = self
292✔
670
                .read_bits(rem.len() * 8)
292✔
671
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
146✔
672
            rem.copy_from_slice(&word.to_le_bytes()[..rem.len()]);
584✔
673
        }
674

675
        Ok(buf.len())
167✔
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> {
167✔
686
        let mut iter = buf.chunks_exact_mut(8);
501✔
687

688
        for chunk in &mut iter {
1,700✔
689
            let word = self
3,066✔
690
                .read_bits(64)
691
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
1,533✔
692
            chunk.copy_from_slice(&word.to_be_bytes());
4,599✔
693
        }
694

695
        let rem = iter.into_remainder();
501✔
696
        if !rem.is_empty() {
167✔
697
            let word = self
292✔
698
                .read_bits(rem.len() * 8)
292✔
699
                .map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
146✔
700
            rem.copy_from_slice(&word.to_be_bytes()[8 - rem.len()..]);
584✔
701
        }
702

703
        Ok(buf.len())
167✔
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::Rng;
757
                use rand::{SeedableRng, rngs::SmallRng};
758

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

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

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

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

805
                type ReadWord = $word;
806

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

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

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

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

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

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

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

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

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

© 2025 Coveralls, Inc