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

vigna / sux-rs / 24216514866

09 Apr 2026 10:30PM UTC coverage: 71.86% (+0.7%) from 71.145%
24216514866

push

github

vigna
Fixed usage of VBuilder

4 of 7 new or added lines in 2 files covered. (57.14%)

408 existing lines in 7 files now uncovered.

7776 of 10821 relevant lines covered (71.86%)

15692247.57 hits per line

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

76.69
/src/bits/bit_vec.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
 *
5
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6
 */
7

8
//! Bit vector implementations.
9
//!
10
//! There are two flavors: [`BitVec`], a mutable bit vector, and
11
//! [`AtomicBitVec`], a mutable, thread-safe bit vector.
12
//!
13
//! Operations on these structures are provided by the extension traits
14
//! [`BitVecOps`], [`BitVecOpsMut`](crate::traits::BitVecOpsMut), and
15
//! [`AtomicBitVecOps`], which must be pulled in scope as needed. There are also
16
//! operations that are specific to certain implementations, such as
17
//! [`push`](BitVec::push).
18
//!
19
//! These flavors depend on a backend with a word type `W`, and presently we
20
//! provide:
21
//!
22
//! - `BitVec<Vec<W>>`: a mutable, growable and resizable bit vector;
23
//! - `BitVec<AsRef<[W]>>`: an immutable bit vector, useful for
24
//!   [ε-serde](https://crates.io/crates/epserde) support;
25
//! - `BitVec<AsRef<[W]> + AsMut<[W]>>`: a mutable (but
26
//!   not resizable) bit vector;
27
//! - `AtomicBitVec<AsRef<[Atomic<W>]>>`: a thread-safe, mutable (but
28
//!   not resizable) bit vector.
29
//!
30
//! Note that nothing is assumed about the content of the backend outside the
31
//! bits of the bit vector. Moreover, the content of the backend outside of
32
//! the bit vector is never modified by the methods of this structure.
33
//!
34
//! It is possible to juggle between all flavors using [`From`]/[`Into`], and
35
//! with [`TryFrom`]/[`TryInto`] when going [from a non-atomic to an atomic bit
36
//! vector](BitVec#impl-TryFrom%3CBitVec%3C%26%5BW%5D%3E%3E-for-AtomicBitVec%3C%26%5B%3CW+as+AtomicPrimitive%3E::Atomic%5D%3E).
37
//!
38
//! # Type annotations
39
//!
40
//! Both [`BitVec`] and [`AtomicBitVec`] have default type parameters for
41
//! their backends. However, Rust does not apply struct default type
42
//! parameters in expression position, so constructor calls like
43
//! `BitVec::new(n)` or `AtomicBitVec::new(n)` leave the backend type
44
//! unconstrained.
45
//!
46
//! The fix is to annotate the binding with the bare type alias, which
47
//! *does* apply defaults:
48
//!
49
//! ```rust
50
//! # use sux::prelude::*;
51
//! let mut b: BitVec = BitVec::new(10);     // OK: B = Vec<usize>
52
//! let a: AtomicBitVec = AtomicBitVec::new(10); // OK: B = Box<[Atomic<usize>]>
53
//! ```
54
//!
55
//! The [`bit_vec!`](macro@crate::bits::bit_vec) macro and
56
//! [`FromIterator`] / [`Extend`] do not need
57
//! annotations because the word type is determined by the output context.
58
//!
59
//! # Examples
60
//!
61
//! ```rust
62
//! use sux::prelude::*;
63
//! use sux::traits::bit_vec_ops::*;
64

65
//! use std::sync::atomic::Ordering;
66
//!
67
//! // Convenience macro
68
//! let b = bit_vec![0, 1, 0, 1, 1, 0, 1, 0];
69
//! assert_eq!(b.len(), 8);
70
//! // Not constant time
71
//! assert_eq!(b.count_ones(), 4);
72
//! assert_eq!(b[0], false);
73
//! assert_eq!(b[1], true);
74
//! assert_eq!(b[2], false);
75
//!
76
//! let b: AddNumBits<_> = b.into();
77
//! // Constant time, but now b is immutable
78
//! assert_eq!(b.num_ones(), 4);
79
//!
80
//! let mut b: BitVec = BitVec::new(0);
81
//! b.push(true);
82
//! b.push(false);
83
//! b.push(true);
84
//! assert_eq!(b.len(), 3);
85
//!
86
//! // Let's make it atomic
87
//! let mut a: AtomicBitVec = b.into();
88
//! a.set(1, true, Ordering::Relaxed);
89
//! assert!(a.get(0, Ordering::Relaxed));
90
//!
91
//! // Back to normal, but immutable size
92
//! let b: BitVec<Vec<usize>> = a.into();
93
//! let mut b: BitVec<Box<[usize]>> = b.into();
94
//! b.set(2, false);
95
//!
96
//! // If we create an artificially dirty bit vector, everything still works.
97
//! let ones = [usize::MAX; 2];
98
//! assert_eq!(unsafe { BitVec::from_raw_parts(ones.as_slice(), 1) }.count_ones(), 1);
99
//! ```
100

101
use crate::ambassador_impl_Index;
102
use crate::bits::{assert_unaligned, debug_assert_unaligned, test_unaligned};
103
use crate::traits::ambassador_impl_Backend;
104
use crate::traits::ambassador_impl_BitLength;
105
use crate::traits::{
106
    AtomicBitIter, AtomicBitVecOps, Backend, BitIter, BitVecOps, BitVecValueOps, Word,
107
};
108
use crate::utils::SelectInWord;
109
use crate::{
110
    traits::{bit_vec_ops::BitLength, rank_sel::*},
111
    utils::{
112
        CannotCastToAtomicError, transmute_boxed_slice_from_atomic,
113
        transmute_boxed_slice_into_atomic, transmute_vec_from_atomic, transmute_vec_into_atomic,
114
    },
115
};
116
use ambassador::Delegate;
117
use atomic_primitive::{Atomic, AtomicPrimitive, PrimitiveAtomic, PrimitiveAtomicUnsigned};
118
#[allow(unused_imports)] // this is in the std prelude but not in no_std!
119
use core::borrow::BorrowMut;
120
use core::fmt;
121
use mem_dbg::*;
122
use num_primitive::PrimitiveInteger;
123
use std::mem::size_of;
124
use std::{ops::Index, sync::atomic::Ordering};
125

126
/// A bit vector.
127
///
128
/// Instances can be created using [`new`](BitVec::new),
129
/// [`with_value`](BitVec::with_value), with the convenience macro
130
/// [`bit_vec!`](macro@crate::bits::bit_vec), or with a [`FromIterator`
131
/// implementation](#impl-FromIterator<bool>-for-BitVec).
132
///
133
/// See the [module documentation](mod@crate::bits::bit_vec) for more details.
134
#[derive(Debug, Clone, MemSize, MemDbg, Delegate)]
135
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
136
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
137
#[delegate(crate::traits::Backend, target = "bits")]
138
pub struct BitVec<B = Vec<usize>> {
139
    bits: B,
140
    len: usize,
141
}
142

143
/// Convenient, [`vec!`](vec!)-like macro to initialize bit vectors.
144
///
145
/// - `bit_vec![]` creates an empty bit vector.
146
///
147
/// - `bit_vec![false; n]` or `bit_vec![0; n]` creates a bit vector of length
148
///   `n` with all bits set to `false`.
149
///
150
/// - `bit_vec![true; n]` or `bit_vec![1; n]` creates a bit vector of length `n`
151
///   with all bits set to `true`.
152
///
153
/// - `bit_vec![b₀, b₁, b₂, …]` creates a bit vector with the specified bits,
154
///   where each `bᵢ` can be any expression that evaluates to a boolean or integer
155
///   (0 for `false`, non-zero for `true`).
156
///
157
/// # Examples
158
///
159
/// ```rust
160
/// # #[cfg(target_pointer_width = "64")]
161
/// # {
162
/// # use sux::prelude::*;
163
/// # use sux::traits::BitVecOps;
164
/// // Empty bit vector
165
/// let b = bit_vec![];
166
/// assert_eq!(b.len(), 0);
167
///
168
/// // 10 bits set to true
169
/// let b = bit_vec![true; 10];
170
/// assert_eq!(b.len(), 10);
171
/// assert_eq!(b.iter().all(|x| x), true);
172
/// let b = bit_vec![1; 10];
173
/// assert_eq!(b.len(), 10);
174
/// assert_eq!(b.iter().all(|x| x), true);
175
///
176
/// // 10 bits set to false
177
/// let b = bit_vec![false; 10];
178
/// assert_eq!(b.len(), 10);
179
/// assert_eq!(b.iter().any(|x| x), false);
180
/// let b = bit_vec![0; 10];
181
/// assert_eq!(b.len(), 10);
182
/// assert_eq!(b.iter().any(|x| x), false);
183
///
184
/// // Bit list
185
/// let b = bit_vec![0, 1, 0, 1, 0, 0];
186
/// assert_eq!(b.len(), 6);
187
/// assert_eq!(b[0], false);
188
/// assert_eq!(b[1], true);
189
/// assert_eq!(b[2], false);
190
/// assert_eq!(b[3], true);
191
/// assert_eq!(b[4], false);
192
/// assert_eq!(b[5], false);
193
///
194
/// // With explicit word type (useful for cross-platform code)
195
/// let b = bit_vec![0, 1, 0, 1];
196
/// assert_eq!(b.len(), 4);
197
/// let b = bit_vec![false; 10];
198
/// assert_eq!(b.len(), 10);
199
/// # }
200
/// ```
201
#[macro_export]
202
macro_rules! bit_vec {
203
    // Arms with explicit word type (colon separator)
204
    ($W:ty) => {
205
        $crate::bits::BitVec::<Vec<$W>>::new(0)
206
    };
207
    ($W:ty: false; $n:expr) => {
208
        $crate::bits::BitVec::<Vec<$W>>::new($n)
209
    };
210
    ($W:ty: 0; $n:expr) => {
211
        $crate::bits::BitVec::<Vec<$W>>::new($n)
212
    };
213
    ($W:ty: true; $n:expr) => {
214
        {
215
            $crate::bits::BitVec::<Vec<$W>>::with_value($n, true)
216
        }
217
    };
218
    ($W:ty: 1; $n:expr) => {
219
        {
220
            $crate::bits::BitVec::<Vec<$W>>::with_value($n, true)
221
        }
222
    };
223
    ($W:ty: $($x:expr),+ $(,)?) => {
224
        {
225
            let mut b = $crate::bits::BitVec::<Vec<$W>>::with_capacity([$($x),+].len());
226
            $( b.push($x != 0); )*
227
            b
228
        }
229
    };
230
    // Default arms (usize backing)
231
    () => {
232
        $crate::bits::BitVec::<Vec<usize>>::new(0)
233
    };
234
    (false; $n:expr) => {
235
        $crate::bits::BitVec::<Vec<usize>>::new($n)
236
    };
237
    (0; $n:expr) => {
238
        $crate::bits::BitVec::<Vec<usize>>::new($n)
239
    };
240
    (true; $n:expr) => {
241
        {
242
            $crate::bits::BitVec::<Vec<usize>>::with_value($n, true)
243
        }
244
    };
245
    (1; $n:expr) => {
246
        {
247
            $crate::bits::BitVec::<Vec<usize>>::with_value($n, true)
248
        }
249
    };
250
    ($($x:expr),+ $(,)?) => {
251
        {
252
            let mut b = $crate::bits::BitVec::<Vec<usize>>::with_capacity([$($x),+].len());
253
            $( b.push($x != 0); )*
254
            b
255
        }
256
    };
257
}
258

259
impl<B> BitVec<B> {
260
    /// Returns the number of bits in the bit vector.
261
    ///
262
    /// This method is equivalent to [`BitLength::len`], but it is provided to
263
    /// reduce ambiguity in method resolution.
264
    #[inline(always)]
265
    pub const fn len(&self) -> usize {
77,200✔
266
        self.len
77,200✔
267
    }
268

269
    /// # Safety
270
    /// `len` must be between 0 (included) and the number of
271
    /// bits in `bits` (included).
272
    #[inline(always)]
273
    pub const unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
96✔
274
        Self { bits, len }
275
    }
276

277
    /// Returns the backend and the length in bits, consuming this bit vector.
278
    #[inline(always)]
279
    pub fn into_raw_parts(self) -> (B, usize) {
2✔
280
        (self.bits, self.len)
2✔
281
    }
282

283
    /// Replaces the backend by applying a function, consuming this bit vector.
284
    ///
285
    /// # Safety
286
    /// The caller must ensure that the length is compatible with the new
287
    /// backend.
288
    #[inline(always)]
289
    pub unsafe fn map<B2>(self, f: impl FnOnce(B) -> B2) -> BitVec<B2> {
×
290
        BitVec {
291
            bits: f(self.bits),
×
292
            len: self.len,
×
293
        }
294
    }
295
}
296

297
impl<W: Word> BitVec<Vec<W>> {
298
    /// Creates a new bit vector of length `len` initialized to `false`.
299
    pub fn new(len: usize) -> Self {
128,470✔
300
        Self::with_value(len, false)
256,940✔
301
    }
302

303
    /// Creates a new bit vector of length `len` initialized to `value`.
304
    pub fn with_value(len: usize, value: bool) -> Self {
148,140✔
305
        let bits_per_word = W::BITS as usize;
296,280✔
306
        let n_of_words = len.div_ceil(bits_per_word);
592,560✔
307
        let extra_bits = (n_of_words * bits_per_word) - len;
296,280✔
308
        let word_value = if value { !W::ZERO } else { W::ZERO };
444,420✔
309
        let mut bits = vec![word_value; n_of_words];
592,560✔
310
        if extra_bits > 0 {
173,687✔
311
            let last_word_value = word_value >> extra_bits;
76,641✔
312
            bits[n_of_words - 1] = last_word_value;
25,547✔
313
        }
314
        Self { bits, len }
315
    }
316

317
    /// Creates a new zero-length bit vector of given capacity.
318
    ///
319
    /// Note that the capacity will be rounded up to a multiple of the word
320
    /// size.
321
    pub fn with_capacity(capacity: usize) -> Self {
45✔
322
        let bits_per_word = W::BITS as usize;
90✔
323
        let n_of_words = capacity.div_ceil(bits_per_word);
180✔
324
        Self {
325
            bits: Vec::with_capacity(n_of_words),
45✔
326
            len: 0,
327
        }
328
    }
329

330
    /// Returns the current capacity of this bit vector.
331
    pub fn capacity(&self) -> usize {
20✔
332
        self.bits.capacity() * W::BITS as usize
40✔
333
    }
334

335
    /// Appends a bit to the end of this bit vector.
336
    pub fn push(&mut self, b: bool) {
1,544,126,490✔
337
        let bits_per_word = W::BITS as usize;
2,147,483,647✔
338
        if self.bits.len() * bits_per_word == self.len {
2,147,483,647✔
339
            self.bits.push(W::ZERO);
26,356,634✔
340
        }
341
        let word_index = self.len / bits_per_word;
2,147,483,647✔
342
        let bit_index = self.len % bits_per_word;
2,147,483,647✔
343
        // Clear bit
344
        self.bits[word_index] &= !(W::ONE << bit_index);
1,544,126,490✔
345
        // Set bit
346
        if b {
2,147,483,647✔
347
            self.bits[word_index] |= W::ONE << bit_index;
730,764,628✔
348
        }
349
        self.len += 1;
1,544,126,490✔
350
    }
351

352
    /// Appends the lower `width` bits of `value` to the end of this bit
353
    /// vector.
354
    ///
355
    /// # Panics
356
    ///
357
    /// Panics if `width` > `W::BITS`.
358
    pub fn append_value(&mut self, value: W, width: usize) {
31,523✔
359
        assert!(
31,523✔
360
            width <= W::BITS as usize,
31,523✔
361
            "width {} must be at most W::BITS ({})",
×
362
            width,
×
363
            W::BITS
×
364
        );
365
        if width == 0 {
31,523✔
366
            return;
679✔
367
        }
368
        let bits_per_word = W::BITS as usize;
61,688✔
369
        let l = bits_per_word - width;
61,688✔
370
        let value = (value << l) >> l;
61,688✔
371
        let new_len = self.len + width;
61,688✔
372
        let needed_words = new_len.div_ceil(bits_per_word);
123,376✔
373
        // Grow the backing storage if necessary.
374
        self.bits.resize(needed_words, W::ZERO);
92,532✔
375

376
        let word_idx = self.len / bits_per_word;
61,688✔
377
        let bit_idx = self.len % bits_per_word;
61,688✔
378

379
        self.bits[word_idx] |= value << bit_idx;
61,688✔
380
        if bit_idx + width > bits_per_word {
42,638✔
381
            self.bits[word_idx + 1] = value.wrapping_shr(bit_idx.wrapping_neg() as u32);
47,176✔
382
        }
383
        self.len = new_len;
30,844✔
384
    }
385

386
    /// Removes the last bit from the bit vector and returns it, or `None` if it
387
    /// is empty.
388
    pub fn pop(&mut self) -> Option<bool> {
1,206✔
389
        if self.len == 0 {
1,206✔
390
            return None;
6✔
391
        }
392
        let last_pos = self.len - 1;
2,400✔
393
        let result = unsafe { BitVecOps::<W>::get_unchecked(self, last_pos) };
4,800✔
394
        self.len = last_pos;
1,200✔
395
        Some(result)
1,200✔
396
    }
397

398
    /// Reserves capacity for at least `additional` more bits to be appended.
399
    ///
400
    /// After calling `reserve`, capacity will be greater than or equal to
401
    /// `self.len() + additional`. The allocator may reserve more space to
402
    /// speculatively avoid frequent reallocations. Does nothing if the
403
    /// capacity is already sufficient.
404
    pub fn reserve(&mut self, additional: usize) {
117✔
405
        let needed_words = (self.len + additional).div_ceil(W::BITS as usize);
468✔
406
        self.bits
117✔
407
            .reserve(needed_words.saturating_sub(self.bits.len()));
585✔
408
    }
409

410
    /// Reserves the minimum capacity for at least `additional` more bits to
411
    /// be appended.
412
    ///
413
    /// After calling `reserve_exact`, capacity will be greater than or equal
414
    /// to `self.len() + additional`. Does nothing if the capacity is already
415
    /// sufficient.
416
    ///
417
    /// Note that the allocator may give the collection more space than it
418
    /// requests. Therefore, capacity cannot be relied upon to be precisely
419
    /// minimal.
420
    pub fn reserve_exact(&mut self, additional: usize) {
2✔
421
        let needed_words = (self.len + additional).div_ceil(W::BITS as usize);
8✔
422
        self.bits
2✔
423
            .reserve_exact(needed_words.saturating_sub(self.bits.len()));
10✔
424
    }
425

426
    /// Appends the bits of `other` to the end of this bit vector.
427
    ///
428
    /// Unlike [`Vec::append`], `other` is not drained: its contents are
429
    /// copied into `self`.
430
    pub fn append<B2: AsRef<[W]>>(&mut self, other: &BitVec<B2>) {
4,526✔
431
        let other_len = other.len;
9,052✔
432
        if other_len == 0 {
4,526✔
433
            return;
1,527✔
434
        }
435

436
        let bpw = W::BITS as usize;
5,998✔
437
        let offset = self.len % bpw;
5,998✔
438
        let src: &[W] = other.bits.as_ref();
8,997✔
439
        let src_words = other_len.div_ceil(bpw);
11,996✔
440
        let new_total = self.len + other_len;
5,998✔
441
        let new_word_count = new_total.div_ceil(bpw);
11,996✔
442

443
        if offset == 0 {
3,359✔
444
            self.bits.extend_from_slice(&src[..src_words]);
1,080✔
445
        } else {
446
            self.bits.reserve(new_word_count - self.bits.len());
10,556✔
447

448
            let last_idx = self.bits.len() - 1;
5,278✔
449
            self.bits[last_idx] |= src[0] << offset;
5,278✔
450

451
            let shift_right = bpw - offset;
5,278✔
452
            for i in 1..src_words {
4,797✔
453
                self.bits
2,158✔
454
                    .push((src[i - 1] >> shift_right) | (src[i] << offset));
3,237✔
455
            }
456

457
            if new_word_count > self.bits.len() {
5,718✔
458
                self.bits.push(src[src_words - 1] >> shift_right);
1,320✔
459
            }
460
        }
461

462
        self.len = new_total;
2,999✔
463
    }
464

465
    /// Resizes the bit vector in place, extending it with `value` if it is
466
    /// necessary.
467
    pub fn resize(&mut self, new_len: usize, value: bool) {
12✔
468
        let bits_per_word = W::BITS as usize;
24✔
469
        if new_len > self.len {
12✔
470
            let old_len = self.len;
12✔
471
            let old_word = old_len / bits_per_word;
12✔
472
            let old_bit = old_len % bits_per_word;
12✔
473
            let word_value = if value { !W::ZERO } else { W::ZERO };
18✔
474

475
            self.bits
6✔
476
                .resize(new_len.div_ceil(bits_per_word), word_value);
30✔
477

478
            // Handle the partial word at old_len, then fill all
479
            // remaining words (which may contain stale data from
480
            // previous truncations).
481
            if old_bit != 0 {
6✔
482
                let mask = !W::ZERO << old_bit;
×
483
                self.bits[old_word] = (self.bits[old_word] & !mask) | (word_value & mask);
×
484
                self.bits[old_word + 1..].fill(word_value);
×
485
            } else {
486
                self.bits[old_word..].fill(word_value);
12✔
487
            }
488
        }
489
        self.len = new_len;
12✔
490
    }
491

492
    /// Ensures a padding word is present at the end and converts the
493
    /// backend to `Box<[W]>`.
494
    ///
495
    /// The extra word ensures that unaligned reads of `size_of::<W>()`
496
    /// bytes starting at any byte offset within the data never exceed the
497
    /// allocation. If the allocation already has more words than needed
498
    /// for the data, no word is added.
499
    pub fn into_padded(mut self) -> BitVec<Box<[W]>> {
115✔
500
        let needed = self.len.div_ceil(W::BITS as usize);
460✔
501
        if self.bits.len() <= needed {
345✔
502
            self.bits.push(W::ZERO);
115✔
503
        }
504
        unsafe { BitVec::from_raw_parts(self.bits.into_boxed_slice(), self.len) }
460✔
505
    }
506

507
    /// Creates a new bit vector of length `len` initialized to `false`,
508
    /// with a padding word at the end for safe unaligned reads.
509
    ///
510
    /// This constructor is useful for structures implementing
511
    /// [`TryIntoUnaligned`](crate::traits::TryIntoUnaligned) that want to avoid
512
    /// reallocations.
513
    pub fn new_padded(len: usize) -> BitVec<Box<[W]>> {
×
514
        let n_of_words = len.div_ceil(W::BITS as usize);
×
515
        unsafe { BitVec::from_raw_parts(vec![W::ZERO; n_of_words + 1].into_boxed_slice(), len) }
×
516
    }
517
}
518

519
impl<W: Word> Extend<bool> for BitVec<Vec<W>> {
520
    fn extend<T: IntoIterator<Item = bool>>(&mut self, i: T) {
35,930✔
521
        for b in i {
1,347,985,432✔
522
            self.push(b);
1,347,949,502✔
523
        }
524
    }
525
}
526

527
impl<W: Word> FromIterator<bool> for BitVec<Vec<W>> {
528
    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
35,930✔
529
        let mut res = Self::new(0);
71,860✔
530
        res.extend(iter);
107,790✔
531
        res
35,930✔
532
    }
533
}
534

535
impl<B: ToOwned> BitVec<B> {
536
    /// Returns a copy of this bit vector with an owned backend.
537
    pub fn to_owned(&self) -> BitVec<<B as ToOwned>::Owned> {
×
538
        BitVec {
539
            bits: self.bits.to_owned(),
×
540
            len: self.len,
×
541
        }
542
    }
543
}
544

545
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> BitVecValueOps<B::Word> for BitVec<B> {
546
    fn get_value(&self, pos: usize, width: usize) -> B::Word {
19,540✔
547
        assert!(
19,540✔
548
            width <= B::Word::BITS as usize,
19,540✔
549
            "width {} must be at most W::BITS ({})",
×
550
            width,
×
551
            B::Word::BITS
×
552
        );
553
        assert!(
19,540✔
554
            pos + width <= self.len,
19,540✔
555
            "bit range {}..{} out of bounds for length {}",
×
556
            pos,
×
557
            pos + width,
×
558
            self.len
×
559
        );
560
        unsafe { self.get_value_unchecked(pos, width) }
78,160✔
561
    }
562

563
    #[inline]
564
    unsafe fn get_value_unchecked(&self, pos: usize, width: usize) -> B::Word {
79,716✔
565
        let bits = B::Word::BITS as usize;
159,432✔
566
        let word_index = pos / bits;
159,432✔
567
        let bit_index = pos % bits;
159,432✔
568
        let l = bits - width;
159,432✔
569
        let data = self.bits.as_ref();
239,148✔
570

571
        if width == 0 {
79,716✔
572
            return B::Word::ZERO;
1,345✔
573
        }
574

575
        unsafe {
576
            if bit_index <= l {
78,371✔
577
                (*data.get_unchecked(word_index) << (l - bit_index)) >> l
180,165✔
578
            } else {
579
                (*data.get_unchecked(word_index) >> bit_index)
54,948✔
580
                    | ((*data.get_unchecked(word_index + 1))
54,948✔
581
                        .wrapping_shl(l.wrapping_sub(bit_index) as u32)
54,948✔
582
                        >> l)
18,316✔
583
            }
584
        }
585
    }
586
}
587

588
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> BitVec<B> {
589
    /// Like [`BitVecValueOps::get_value`], but using unaligned reads.
590
    ///
591
    /// This avoids a branch at the cost of requiring the bit width to satisfy
592
    /// the constraints of
593
    /// [`BitFieldVec::get_unaligned`](crate::bits::BitFieldVec::get_unaligned):
594
    /// `width` must be at most `W::BITS - 6`, or exactly `W::BITS - 4`, or
595
    /// exactly `W::BITS` (where `W` is the word type of the backend).
596
    ///
597
    /// Additionally, a padding word must be present at the end of the
598
    /// underlying storage.
599
    ///
600
    /// # Panics
601
    ///
602
    /// Panics if `pos + width` exceeds the bit length, if `width` does not
603
    /// satisfy the unaligned constraints, or if the read would exceed the
604
    /// allocation.
605
    pub fn get_value_unaligned(&self, pos: usize, width: usize) -> B::Word {
×
606
        assert_unaligned!(B::Word, width);
×
607
        assert!(
×
608
            pos + width <= self.len,
×
609
            "bit range {}..{} out of bounds for length {}",
×
610
            pos,
×
611
            pos + width,
×
612
            self.len
×
613
        );
614
        assert!(
×
615
            pos / 8 + size_of::<B::Word>() <= std::mem::size_of_val(self.bits.as_ref()),
×
616
            "unaligned read at bit position {} would exceed allocation",
×
617
            pos,
×
618
        );
619
        unsafe { self.get_value_unaligned_unchecked(pos, width) }
×
620
    }
621

622
    /// Like [`BitVecValueOps::get_value_unchecked`], but using unaligned
623
    /// reads.
624
    ///
625
    /// # Safety
626
    ///
627
    /// - `width` must satisfy the unaligned constraints: at most `W::BITS -
628
    ///   6`, or exactly `W::BITS - 4`, or exactly `W::BITS`.
629
    /// - `pos + width` must not exceed the bit length.
630
    /// - A padding word must be present at the end of the underlying storage so
631
    ///   that reading `size_of::<W>()` bytes starting at byte offset `pos / 8`
632
    ///   does not exceed the allocation.
633
    #[inline]
634
    pub unsafe fn get_value_unaligned_unchecked(&self, pos: usize, width: usize) -> B::Word {
×
635
        debug_assert_unaligned!(B::Word, width);
×
636
        if width == 0 {
×
637
            return B::Word::ZERO;
×
638
        }
639
        let base_ptr = self.bits.as_ref().as_ptr() as *const u8;
×
640
        debug_assert!(
×
641
            pos / 8 + size_of::<B::Word>() <= std::mem::size_of_val(self.bits.as_ref()),
×
642
            "unaligned read at bit position {} would exceed allocation",
×
643
            pos,
×
644
        );
645
        let ptr = unsafe { base_ptr.add(pos / 8) } as *const B::Word;
×
646
        let word = unsafe { core::ptr::read_unaligned(ptr) };
×
647
        let l = B::Word::BITS as usize - width;
×
648
        ((word >> (pos % 8)) << l) >> l
×
649
    }
650
}
651

652
impl<B> BitLength for BitVec<B> {
653
    #[inline(always)]
654
    fn len(&self) -> usize {
560,095,540✔
655
        self.len
560,095,540✔
656
    }
657
}
658

659
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> BitCount for BitVec<B> {
660
    fn count_ones(&self) -> usize {
44,015✔
661
        let bits_per_word = B::Word::BITS as usize;
88,030✔
662
        let full_words = self.len() / bits_per_word;
132,045✔
663
        let residual = self.len() % bits_per_word;
132,045✔
664
        let bits: &[B::Word] = self.as_ref();
132,045✔
665
        let mut num_ones: usize = bits[..full_words]
132,045✔
666
            .iter()
667
            .map(|x| x.count_ones() as usize)
678,198,033✔
668
            .sum();
669
        if residual != 0 {
44,015✔
670
            num_ones += (bits[full_words] << (bits_per_word - residual)).count_ones() as usize
68,382✔
671
        }
672
        num_ones
44,015✔
673
    }
674
}
675

676
impl<B: Backend<Word: Word> + AsRef<[B::Word]>, C: Backend<Word = B::Word> + AsRef<[B::Word]>>
677
    PartialEq<BitVec<C>> for BitVec<B>
678
{
679
    fn eq(&self, other: &BitVec<C>) -> bool {
812✔
680
        let len = self.len();
2,436✔
681
        if len != other.len() {
1,624✔
682
            return false;
1✔
683
        }
684

685
        let word_bits = B::Word::BITS as usize;
1,622✔
686
        let full_words = len / word_bits;
1,622✔
687
        if self.as_ref()[..full_words] != other.as_ref()[..full_words] {
1,622✔
688
            return false;
×
689
        }
690

691
        let residual = len % word_bits;
1,622✔
692
        residual == 0
811✔
693
            || (self.as_ref()[full_words] ^ other.as_ref()[full_words]) << (word_bits - residual)
3,355✔
694
                == B::Word::ZERO
671✔
695
    }
696
}
697

698
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> Eq for BitVec<B> {}
699

700
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> std::hash::Hash for BitVec<B> {
UNCOV
701
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
×
UNCOV
702
        let len = self.len();
×
UNCOV
703
        len.hash(state);
×
UNCOV
704
        let word_bits = B::Word::BITS as usize;
×
UNCOV
705
        let full_words = len / word_bits;
×
UNCOV
706
        self.as_ref()[..full_words].hash(state);
×
UNCOV
707
        let residual = len % word_bits;
×
UNCOV
708
        if residual != 0 {
×
709
            // Mask off the padding bits before hashing the last partial word.
UNCOV
710
            (self.as_ref()[full_words] << (word_bits - residual)).hash(state);
×
711
        }
712
    }
713
}
714

715
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> Index<usize> for BitVec<B> {
716
    type Output = bool;
717

718
    fn index(&self, index: usize) -> &Self::Output {
336,487,989✔
719
        match BitVecOps::<B::Word>::get(self, index) {
672,975,978✔
720
            false => &false,
178,148,664✔
721
            true => &true,
158,339,325✔
722
        }
723
    }
724
}
725

726
impl<'a, B: Backend<Word: Word> + AsRef<[B::Word]>> IntoIterator for &'a BitVec<B> {
727
    type IntoIter = BitIter<'a, B::Word, B>;
728
    type Item = bool;
729

730
    fn into_iter(self) -> Self::IntoIter {
1,314✔
731
        BitIter::new(&self.bits, self.len())
5,256✔
732
    }
733
}
734

735
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> fmt::Display for BitVec<B> {
736
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5✔
737
        write!(f, "[")?;
10✔
738
        for b in self {
20✔
739
            write!(f, "{:b}", b as usize)?;
45✔
740
        }
741
        write!(f, "]")?;
10✔
742
        Ok(())
5✔
743
    }
744
}
745

746
#[derive(Debug, Clone, MemSize, MemDbg, Delegate)]
747
/// A thread-safe bit vector.
748
///
749
/// See the [module documentation](mod@crate::bits::bit_vec) for details.
750
#[delegate(crate::traits::Backend, target = "bits")]
751
pub struct AtomicBitVec<B = Box<[Atomic<usize>]>> {
752
    bits: B,
753
    len: usize,
754
}
755

756
impl<B> AtomicBitVec<B> {
757
    /// Returns the number of bits in the bit vector.
758
    ///
759
    /// This method is equivalent to [`BitLength::len`], but it is provided to
760
    /// reduce ambiguity in method resolution.
761
    #[inline(always)]
762
    pub const fn len(&self) -> usize {
77✔
763
        self.len
77✔
764
    }
765

766
    /// # Safety
767
    /// `len` must be between 0 (included) and the number of
768
    /// bits in `bits` (included).
769
    #[inline(always)]
770
    pub const unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
3✔
771
        Self { bits, len }
772
    }
773
    /// Returns the backend and the length in bits, consuming this bit vector.
774
    #[inline(always)]
775
    pub fn into_raw_parts(self) -> (B, usize) {
1✔
776
        (self.bits, self.len)
1✔
777
    }
778
}
779

780
impl<B: Backend<Word: PrimitiveAtomicUnsigned<Value: Word>> + From<Vec<B::Word>>> AtomicBitVec<B> {
781
    /// Creates a new atomic bit vector of length `len` initialized to `false`.
782
    pub fn new(len: usize) -> Self {
23✔
783
        Self::with_value(len, false)
46✔
784
    }
785

786
    /// Creates a new atomic bit vector of length `len` initialized to `value`.
787
    pub fn with_value(len: usize, value: bool) -> Self {
24✔
788
        let bits_per_word = <B::Word as PrimitiveAtomic>::Value::BITS as usize;
48✔
789
        let n_of_words = len.div_ceil(bits_per_word);
96✔
790
        let extra_bits = (n_of_words * bits_per_word) - len;
48✔
791
        let word_value = if value {
48✔
792
            !<B::Word as PrimitiveAtomic>::Value::ZERO
1✔
793
        } else {
794
            <B::Word as PrimitiveAtomic>::Value::ZERO
23✔
795
        };
796
        let mut bits: Vec<B::Word> = (0..n_of_words).map(|_| B::Word::new(word_value)).collect();
348✔
797
        if extra_bits > 0 {
42✔
798
            let last_word_value = word_value >> extra_bits;
54✔
799
            bits[n_of_words - 1] = B::Word::new(last_word_value);
36✔
800
        }
801
        Self {
802
            bits: B::from(bits),
48✔
803
            len,
804
        }
805
    }
806
}
807

808
impl<B> BitLength for AtomicBitVec<B> {
809
    #[inline(always)]
810
    fn len(&self) -> usize {
2,211✔
811
        self.len
2,211✔
812
    }
813
}
814

815
impl<B: Backend<Word: PrimitiveAtomicUnsigned<Value: Word>> + AsRef<[B::Word]>> BitCount
816
    for AtomicBitVec<B>
817
{
818
    fn count_ones(&self) -> usize {
3✔
819
        let bits_per_word = <B::Word as PrimitiveAtomic>::Value::BITS as usize;
6✔
820
        let full_words = self.len() / bits_per_word;
9✔
821
        let residual = self.len() % bits_per_word;
9✔
822
        let bits: &[B::Word] = self.as_ref();
9✔
UNCOV
823
        let mut num_ones;
×
824
        // Just to be sure, add a fence to ensure that we will see all the final
825
        // values
826
        core::sync::atomic::fence(Ordering::SeqCst);
6✔
827
        num_ones = bits[..full_words]
3✔
828
            .iter()
3✔
829
            .map(|x| x.load(Ordering::Relaxed).count_ones() as usize)
63✔
830
            .sum();
3✔
831
        if residual != 0 {
3✔
832
            num_ones += (bits[full_words].load(Ordering::Relaxed) << (bits_per_word - residual))
8✔
833
                .count_ones() as usize
2✔
834
        }
835
        num_ones
3✔
836
    }
837
}
838

839
impl<B: Backend<Word: PrimitiveAtomicUnsigned<Value: Word>> + AsRef<[B::Word]>> Index<usize>
840
    for AtomicBitVec<B>
841
{
842
    type Output = bool;
843

844
    /// Shorthand for `get` using [`Ordering::Relaxed`].
845
    fn index(&self, index: usize) -> &Self::Output {
10,000✔
846
        match AtomicBitVecOps::<B::Word>::get(self, index, Ordering::Relaxed) {
30,000✔
847
            false => &false,
9,500✔
848
            true => &true,
500✔
849
        }
850
    }
851
}
852

853
impl<'a, B: Backend<Word: PrimitiveAtomicUnsigned<Value: Word>> + AsRef<[B::Word]>> IntoIterator
854
    for &'a AtomicBitVec<B>
855
{
856
    type IntoIter = AtomicBitIter<'a, B::Word, B>;
857
    type Item = bool;
858

UNCOV
859
    fn into_iter(self) -> Self::IntoIter {
×
UNCOV
860
        AtomicBitIter::new(&self.bits, self.len())
×
861
    }
862
}
863

864
// Conversions
865

866
/// This conversion may fail if the alignment of `W` is not the same as
867
/// that of `W::Atomic`.
868
impl<'a, W: AtomicPrimitive> TryFrom<BitVec<&'a [W]>> for AtomicBitVec<&'a [W::Atomic]> {
869
    type Error = CannotCastToAtomicError<W>;
870
    fn try_from(value: BitVec<&'a [W]>) -> Result<Self, Self::Error> {
1✔
871
        if core::mem::align_of::<W>() != core::mem::align_of::<W::Atomic>() {
1✔
872
            return Err(CannotCastToAtomicError::default());
×
873
        }
874
        Ok(AtomicBitVec {
1✔
875
            bits: unsafe { core::mem::transmute::<&'a [W], &'a [W::Atomic]>(value.bits) },
1✔
876
            len: value.len,
1✔
877
        })
878
    }
879
}
880

881
/// This conversion may fail if the alignment of `W` is not the same as
882
/// that of `W::Atomic`.
883
impl<'a, W: AtomicPrimitive> TryFrom<BitVec<&'a mut [W]>> for AtomicBitVec<&'a mut [W::Atomic]> {
884
    type Error = CannotCastToAtomicError<W>;
885
    fn try_from(value: BitVec<&'a mut [W]>) -> Result<Self, Self::Error> {
1✔
886
        if core::mem::align_of::<W>() != core::mem::align_of::<W::Atomic>() {
1✔
UNCOV
887
            return Err(CannotCastToAtomicError::default());
×
888
        }
889
        Ok(AtomicBitVec {
1✔
890
            bits: unsafe { core::mem::transmute::<&'a mut [W], &'a mut [W::Atomic]>(value.bits) },
1✔
891
            len: value.len,
1✔
892
        })
893
    }
894
}
895

896
impl<W: AtomicPrimitive> From<AtomicBitVec<Box<[W::Atomic]>>> for BitVec<Vec<W>> {
897
    fn from(value: AtomicBitVec<Box<[W::Atomic]>>) -> Self {
1✔
898
        BitVec {
899
            bits: transmute_vec_from_atomic::<W::Atomic>(value.bits.into_vec()),
3✔
900
            len: value.len,
1✔
901
        }
902
    }
903
}
904

905
impl<W: AtomicPrimitive> From<BitVec<Vec<W>>> for AtomicBitVec<Box<[W::Atomic]>> {
906
    fn from(value: BitVec<Vec<W>>) -> Self {
2✔
907
        AtomicBitVec {
908
            bits: transmute_vec_into_atomic(value.bits).into_boxed_slice(),
6✔
909
            len: value.len,
2✔
910
        }
911
    }
912
}
913

914
impl<W: AtomicPrimitive> From<AtomicBitVec<Box<[W::Atomic]>>> for BitVec<Box<[W]>> {
915
    fn from(value: AtomicBitVec<Box<[W::Atomic]>>) -> Self {
6✔
916
        BitVec {
917
            bits: transmute_boxed_slice_from_atomic::<W::Atomic>(value.bits),
12✔
918
            len: value.len,
6✔
919
        }
920
    }
921
}
922

923
impl<W: AtomicPrimitive + Copy> From<BitVec<Box<[W]>>> for AtomicBitVec<Box<[W::Atomic]>> {
924
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
925
        AtomicBitVec {
926
            bits: transmute_boxed_slice_into_atomic::<W>(value.bits),
2✔
927
            len: value.len,
1✔
928
        }
929
    }
930
}
931

932
impl<'a, W: AtomicPrimitive> From<AtomicBitVec<&'a [W::Atomic]>> for BitVec<&'a [W]> {
933
    fn from(value: AtomicBitVec<&'a [W::Atomic]>) -> Self {
1✔
934
        BitVec {
935
            bits: unsafe { core::mem::transmute::<&'a [W::Atomic], &'a [W]>(value.bits) },
1✔
936
            len: value.len,
1✔
937
        }
938
    }
939
}
940

941
impl<'a, W: AtomicPrimitive> From<AtomicBitVec<&'a mut [W::Atomic]>> for BitVec<&'a mut [W]> {
942
    fn from(value: AtomicBitVec<&'a mut [W::Atomic]>) -> Self {
1✔
943
        BitVec {
944
            bits: unsafe { core::mem::transmute::<&'a mut [W::Atomic], &'a mut [W]>(value.bits) },
1✔
945
            len: value.len,
1✔
946
        }
947
    }
948
}
949

950
impl<W> From<BitVec<Vec<W>>> for BitVec<Box<[W]>> {
951
    fn from(value: BitVec<Vec<W>>) -> Self {
1,702✔
952
        BitVec {
953
            bits: value.bits.into_boxed_slice(),
3,404✔
954
            len: value.len,
1,702✔
955
        }
956
    }
957
}
958

959
impl<W> From<BitVec<Box<[W]>>> for BitVec<Vec<W>> {
960
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
961
        BitVec {
962
            bits: value.bits.into_vec(),
2✔
963
            len: value.len,
1✔
964
        }
965
    }
966
}
967

968
impl<W: Word, B: AsRef<[W]>> AsRef<[W]> for BitVec<B> {
969
    #[inline(always)]
970
    fn as_ref(&self) -> &[W] {
2,147,483,647✔
971
        self.bits.as_ref()
2,147,483,647✔
972
    }
973
}
974

975
impl<W: Word, B: AsMut<[W]>> AsMut<[W]> for BitVec<B> {
976
    #[inline(always)]
977
    fn as_mut(&mut self) -> &mut [W] {
50,443,007✔
978
        self.bits.as_mut()
50,443,007✔
979
    }
980
}
981

982
impl<B: Backend + AsRef<[B::Word]>> AsRef<[B::Word]> for AtomicBitVec<B> {
983
    #[inline(always)]
984
    fn as_ref(&self) -> &[B::Word] {
2,223✔
985
        self.bits.as_ref()
2,223✔
986
    }
987
}
988

989
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> RankHinted for BitVec<B> {
990
    #[inline(always)]
991
    unsafe fn rank_hinted(&self, pos: usize, hint_pos: usize, hint_rank: usize) -> usize {
9,904,509✔
992
        let bits_per_word = B::Word::BITS as usize;
19,809,018✔
993
        let bits: &[B::Word] = self.as_ref();
29,713,527✔
994
        let mut rank = hint_rank;
19,809,018✔
995
        let mut hint_pos = hint_pos;
19,809,018✔
996

997
        debug_assert!(
9,904,509✔
998
            hint_pos < bits.len(),
19,809,018✔
UNCOV
999
            "hint_pos: {}, len: {}",
×
UNCOV
1000
            hint_pos,
×
UNCOV
1001
            bits.len()
×
1002
        );
1003

1004
        while (hint_pos + 1) * bits_per_word <= pos {
19,791,333✔
1005
            rank += unsafe { bits.get_unchecked(hint_pos) }.count_ones() as usize;
9,886,824✔
1006
            hint_pos += 1;
4,943,412✔
1007
        }
1008

1009
        rank + (unsafe { *bits.get_unchecked(hint_pos) }
39,618,036✔
1010
            & (B::Word::ONE << (pos % bits_per_word)).wrapping_sub(B::Word::ONE))
9,904,509✔
1011
        .count_ones() as usize
9,904,509✔
1012
    }
1013
}
1014

1015
// SelectHinted and SelectZeroHinted for BitVec.
1016

1017
impl<B: Backend<Word: Word + SelectInWord> + AsRef<[B::Word]>> SelectHinted for BitVec<B> {
1018
    unsafe fn select_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
216,939,549✔
1019
        let bits_per_word = B::Word::BITS as usize;
433,879,098✔
1020
        let mut word_index = hint_pos / bits_per_word;
433,879,098✔
1021
        let bit_index = hint_pos % bits_per_word;
433,879,098✔
1022
        let mut residual = rank - hint_rank;
433,879,098✔
1023
        let mut word =
216,939,549✔
1024
            (unsafe { *self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
433,879,098✔
UNCOV
1025
        loop {
×
1026
            let bit_count = word.count_ones() as usize;
2,107,342,358✔
1027
            if residual < bit_count {
1,053,671,179✔
1028
                return word_index * bits_per_word + word.select_in_word(residual);
650,818,647✔
1029
            }
1030
            word_index += 1;
836,731,630✔
1031
            word = *unsafe { self.as_ref().get_unchecked(word_index) };
1,673,463,260✔
1032
            residual -= bit_count;
836,731,630✔
1033
        }
1034
    }
1035
}
1036

1037
impl<B: Backend<Word: Word + SelectInWord> + AsRef<[B::Word]>> SelectZeroHinted for BitVec<B> {
1038
    unsafe fn select_zero_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
59,710,935✔
1039
        let bits_per_word = B::Word::BITS as usize;
119,421,870✔
1040
        let mut word_index = hint_pos / bits_per_word;
119,421,870✔
1041
        let bit_index = hint_pos % bits_per_word;
119,421,870✔
1042
        let mut residual = rank - hint_rank;
119,421,870✔
1043
        let mut word =
59,710,935✔
1044
            (!*unsafe { self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
119,421,870✔
UNCOV
1045
        loop {
×
1046
            let bit_count = word.count_ones() as usize;
1,017,590,788✔
1047
            if residual < bit_count {
508,795,394✔
1048
                return word_index * bits_per_word + word.select_in_word(residual);
179,132,805✔
1049
            }
1050
            word_index += 1;
449,084,459✔
1051
            word = unsafe { !*self.as_ref().get_unchecked(word_index) };
898,168,918✔
1052
            residual -= bit_count;
449,084,459✔
1053
        }
1054
    }
1055
}
1056

1057
/// A wrapper around [`BitVec`] that implements [`BitVecValueOps`] using
1058
/// unaligned reads.
1059
///
1060
/// Obtain an instance via [`TryIntoUnaligned`](crate::traits::TryIntoUnaligned)
1061
/// on a `BitVec<Box<[W]>>`, which adds a padding word if one is not already
1062
/// present. You can recover the original [`BitVec`] using a [`From`
1063
/// implementation](#impl-From<BitVecU<Box<%5BW%5D>>>-for-BitVec<Box<%5BW%5D>>)
1064
///
1065
/// Note that unaligned reads give correct results only when the bit width
1066
/// satisfies the unaligned constraints (at most `W::BITS - 6`, or exactly
1067
/// `W::BITS - 4`, or exactly `W::BITS`). Using other widths will not
1068
/// cause undefined behavior, but may return incorrect values.
1069
///
1070
/// We delegate [`Backend`], [`BitLength`], and
1071
/// [`AsRef<[Backend::Word]>`](AsRef) to make [`BitVecOps`] methods available,
1072
/// and [`Index`] to make slice-like read-only access available.
1073
#[derive(Debug, Clone, MemSize, MemDbg, Delegate)]
1074
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
1075
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1076
#[delegate(Index<usize>, target = "0")]
1077
#[delegate(crate::traits::Backend, target = "0")]
1078
#[delegate(crate::traits::bit_vec_ops::BitLength, target = "0")]
1079
pub struct BitVecU<B>(BitVec<B>);
1080

1081
impl<W: Word> From<BitVecU<Box<[W]>>> for BitVec<Box<[W]>> {
1082
    /// Converts a [`BitVecU`] back into a [`BitVec`].
1083
    ///
1084
    /// The padding word is kept in the backing storage so that a subsequent
1085
    /// [`try_into_unaligned`](crate::traits::TryIntoUnaligned::try_into_unaligned)
1086
    /// does not need to reallocate.
1087
    fn from(unaligned: BitVecU<Box<[W]>>) -> Self {
×
1088
        unaligned.0
×
1089
    }
1090
}
1091

1092
impl<W: Word> crate::traits::TryIntoUnaligned for BitVec<Box<[W]>> {
1093
    type Unaligned = BitVecU<Box<[W]>>;
1094

UNCOV
1095
    fn try_into_unaligned(
×
1096
        self,
1097
    ) -> Result<Self::Unaligned, crate::traits::UnalignedConversionError> {
UNCOV
1098
        let needed = self.len().div_ceil(W::BITS as usize);
×
UNCOV
1099
        if self.as_ref().len() > needed {
×
1100
            Ok(BitVecU(self))
×
1101
        } else {
UNCOV
1102
            let (raw, len) = self.into_raw_parts();
×
UNCOV
1103
            let mut v = raw.into_vec();
×
UNCOV
1104
            v.reserve_exact(1);
×
1105
            v.push(W::ZERO);
×
1106
            Ok(BitVecU(unsafe {
×
UNCOV
1107
                BitVec::from_raw_parts(v.into_boxed_slice(), len)
×
1108
            }))
1109
        }
1110
    }
1111
}
1112

1113
impl<B: Backend<Word: Word> + AsRef<[B::Word]>> BitVecValueOps<B::Word> for BitVecU<B> {
1114
    #[inline(always)]
UNCOV
1115
    fn get_value(&self, pos: usize, width: usize) -> B::Word {
×
UNCOV
1116
        self.0.get_value_unaligned(pos, width)
×
1117
    }
1118

1119
    #[inline(always)]
UNCOV
1120
    unsafe fn get_value_unchecked(&self, pos: usize, width: usize) -> B::Word {
×
UNCOV
1121
        unsafe { self.0.get_value_unaligned_unchecked(pos, width) }
×
1122
    }
1123
}
1124

1125
impl<B: Backend + AsRef<[B::Word]>> AsRef<[B::Word]> for BitVecU<B> {
1126
    #[inline(always)]
UNCOV
1127
    fn as_ref(&self) -> &[B::Word] {
×
UNCOV
1128
        self.0.bits.as_ref()
×
1129
    }
1130
}
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