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

vigna / sux-rs / 18480907774

13 Oct 2025 11:33PM UTC coverage: 67.167% (+1.8%) from 65.37%
18480907774

push

github

vigna
Further methods moved to bit_vec_ops; added missing docs; iterators on atomic bit vector no longer take an exclusive reference

13 of 29 new or added lines in 2 files covered. (44.83%)

360 existing lines in 5 files now uncovered.

3852 of 5735 relevant lines covered (67.17%)

117331163.32 hits per line

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

77.99
/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 is provided by the extension traits
14
//! [`BitVecOps`], [`BitVecOpsMut`], and [`AtomicBitVecOps`],
15
//! 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 depends on a backend, and presently we provide:
20
//!
21
//! - `BitVec<Vec<usize>>`: a mutable, growable and resizable bit vector;
22
//! - `BitVec<AsRef<[usize]>>`: an immutable bit vector, useful for
23
//!   [ε-serde](https://crates.io/crates/epserde) support;
24
//! - `BitVec<AsRef<[usize]> + AsMut<[usize]>>`: a mutable (but not resizable)
25
//!   bit vector;
26
//! - `AtomicBitVec<AsRef<[AtomicUsize]>>`: a thread-safe, mutable (but not
27
//!   resizable) bit vector.
28
//!
29
//! Note that nothing is assumed about the content of the backend outside the
30
//! bits of the bit vector. Moreover, the content of the backend outside of
31
//! the bit vector is never modified by the methods of this structure.
32
//!
33
//! It is possible to juggle between the three flavors using [`From`]/[`Into`],
34
//! and with [`TryFrom`]/[`TryInto`] when going [from a non-atomic to an atomic
35
//! bit vector](BitVec#impl-TryFrom%3CBitVec%3C%26%5BW%5D%3E%3E-for-AtomicBitVec%3C%26%5B%3CW+as+IntoAtomic%3E::AtomicType%5D%3E).
36
//!
37
//! # Examples
38
//!
39
//! ```rust
40
//! use sux::bit_vec;
41
//! use sux::bits::bit_vec::{BitVec, AtomicBitVec, BitVecOps, BitVecOpsMut, AtomicBitVecOps};
42
//! use sux::traits::{BitCount, BitLength, NumBits, AddNumBits};
43
//! use core::sync::atomic::Ordering;
44
//!
45
//! // Convenience macro
46
//! let b = bit_vec![0, 1, 0, 1, 1, 0, 1, 0];
47
//! assert_eq!(b.len(), 8);
48
//! // Not constant time
49
//! assert_eq!(b.count_ones(), 4);
50
//! assert_eq!(b[0], false);
51
//! assert_eq!(b[1], true);
52
//! assert_eq!(b[2], false);
53
//!
54
//! let b: AddNumBits<_> = b.into();
55
//! // Constant time, but now b is immutable
56
//! assert_eq!(b.num_ones(), 4);
57
//!
58
//! let mut b = BitVec::new(0);
59
//! b.push(true);
60
//! b.push(false);
61
//! b.push(true);
62
//! assert_eq!(b.len(), 3);
63
//!
64
//! // Let's make it atomic
65
//! let mut a: AtomicBitVec = b.into();
66
//! a.set(1, true, Ordering::Relaxed);
67
//! assert!(a.get(0, Ordering::Relaxed));
68
//!
69
//! // Back to normal, but immutable size
70
//! let b: BitVec<Vec<usize>> = a.into();
71
//! let mut b: BitVec<Box<[usize]>> = b.into();
72
//! b.set(2, false);
73
//!
74
//! // If we create an artificially dirty bit vector, everything still works.
75
//! let ones = [usize::MAX; 2];
76
//! assert_eq!(unsafe { BitVec::from_raw_parts(ones, 1) }.count_ones(), 1);
77
//! ```
78

79
use crate::traits::{AtomicBitIterator, AtomicBitVecOps, BitIterator, BitVecOps, BitVecOpsMut};
80
use common_traits::{IntoAtomic, SelectInWord};
81
#[allow(unused_imports)] // this is in the std prelude but not in no_std!
82
use core::borrow::BorrowMut;
83
use core::fmt;
84
use mem_dbg::*;
85
use std::{
86
    ops::Index,
87
    sync::atomic::{AtomicUsize, Ordering},
88
};
89

90
use crate::{
91
    traits::{BITS, rank_sel::*},
92
    utils::{
93
        CannotCastToAtomicError, transmute_boxed_slice_from_atomic,
94
        transmute_boxed_slice_into_atomic, transmute_vec_from_atomic, transmute_vec_into_atomic,
95
    },
96
};
97

98
/// Convenient, [`vec!`](vec!)-like macro to initialize bit vectors.
99
///
100
/// - `bit_vec![]` creates an empty bit vector.
101
///
102
/// - `bit_vec![false; n]` or `bit_vec![0; n]` creates a bit vector of length
103
///   `n` with all bits set to `false`.
104
///
105
/// - `bit_vec![true; n]` or `bit_vec![1; n]` creates a bit vector of length `n`
106
///    with all bits set to `true`.
107
///
108
/// - `bit_vec![b₀, b₁, b₂, …]` creates a bit vector with the specified bits,
109
///    where each `bᵢ` can be any expression that evaluates to a boolean or integer
110
///    (0 for `false`, non-zero for `true`).
111
///
112
///
113
/// # Examples
114
///
115
/// ```rust
116
/// use sux::bit_vec;
117
/// use sux::bits::bit_vec::{BitVecOps, BitVecOpsMut};
118
/// use sux::traits::BitLength;
119
///
120
/// // Empty bit vector
121
/// let b = bit_vec![];
122
/// assert_eq!(b.len(), 0);
123
///
124
/// // 10 bits set to true
125
/// let b = bit_vec![true; 10];
126
/// assert_eq!(b.len(), 10);
127
/// assert_eq!(b.iter().all(|x| x), true);
128
/// let b = bit_vec![1; 10];
129
/// assert_eq!(b.len(), 10);
130
/// assert_eq!(b.iter().all(|x| x), true);
131
///
132
/// // 10 bits set to false
133
/// let b = bit_vec![false; 10];
134
/// assert_eq!(b.len(), 10);
135
/// assert_eq!(b.iter().any(|x| x), false);
136
/// let b = bit_vec![0; 10];
137
/// assert_eq!(b.len(), 10);
138
/// assert_eq!(b.iter().any(|x| x), false);
139
///
140
/// // Bit list
141
/// let b = bit_vec![0, 1, 0, 1, 0, 0];
142
/// assert_eq!(b.len(), 6);
143
/// assert_eq!(b[0], false);
144
/// assert_eq!(b[1], true);
145
/// assert_eq!(b[2], false);
146
/// assert_eq!(b[3], true);
147
/// assert_eq!(b[4], false);
148
/// assert_eq!(b[5], false);
149
/// ```
150
#[macro_export]
151
macro_rules! bit_vec {
152
    () => {
153
        $crate::bits::BitVec::new(0)
154
    };
155
    (false; $n:expr) => {
156
        $crate::bits::BitVec::new($n)
157
    };
158
    (0; $n:expr) => {
159
        $crate::bits::BitVec::new($n)
160
    };
161
    (true; $n:expr) => {
162
        {
163
            $crate::bits::BitVec::with_value($n, true)
164
        }
165
    };
166
    (1; $n:expr) => {
167
        {
168
            $crate::bits::BitVec::with_value($n, true)
169
        }
170
    };
171
    ($($x:expr),+ $(,)?) => {
172
        {
173
            let mut b = $crate::bits::BitVec::with_capacity([$($x),+].len());
174
            $( b.push($x != 0); )*
175
            b
176
        }
177
    };
178
}
179

180
#[derive(Debug, Clone, Copy, MemDbg, MemSize)]
181
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
182
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
183
/// A bit vector.
184
///
185
/// Instances can be created using [`new`](BitVec::new),
186
/// [`with_value`](BitVec::with_value), with the convenience macro
187
/// [`bit_vec!`](macro@crate::bits::bit_vec), or with a [`FromIterator`
188
/// implementation](#impl-FromIterator<bool>-for-BitVec).
189
///
190
/// See the [module documentation](mod@crate::bits::bit_vec) for more details.
191
pub struct BitVec<B = Vec<usize>> {
192
    bits: B,
193
    len: usize,
194
}
195

196
impl<B> BitLength for BitVec<B> {
197
    #[inline(always)]
198
    fn len(&self) -> usize {
2,147,483,647✔
199
        self.len
2,147,483,647✔
200
    }
201
}
202

203
impl<B: AsRef<[usize]>> BitVec<B> {
204
    /// Returns an owned copy of the bit vector.
NEW
205
    pub fn to_owned(&self) -> BitVec {
×
206
        BitVec {
NEW
207
            bits: self.bits.as_ref().to_owned(),
×
NEW
208
            len: self.len,
×
209
        }
210
    }
211
}
212

213
impl<B> BitVec<B> {
214
    /// Returns the number of bits in the bit vector.
215
    ///
216
    /// This method is equivalent to [`BitLength::len`], but it is provided to
217
    /// reduce ambiguity in method resolution.
218
    #[inline(always)]
219
    pub fn len(&self) -> usize {
216,667✔
220
        BitLength::len(self)
433,334✔
221
    }
222

223
    /// # Safety
224
    /// `len` must be between 0 (included) the number of
225
    /// bits in `bits` (included).
226
    #[inline(always)]
227
    pub unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
24✔
228
        Self { bits, len }
229
    }
230

231
    #[inline(always)]
232
    pub fn into_raw_parts(self) -> (B, usize) {
2✔
233
        (self.bits, self.len)
2✔
234
    }
235

236
    #[inline(always)]
237
    /// Modify the bit vector in place.
238
    ///
239
    ///
240
    /// # Safety
241
    /// This is unsafe because it's the caller's responsibility to ensure that
242
    /// that the length is compatible with the modified bits.
UNCOV
243
    pub unsafe fn map<B2>(self, f: impl FnOnce(B) -> B2) -> BitVec<B2> {
×
244
        BitVec {
UNCOV
245
            bits: f(self.bits),
×
UNCOV
246
            len: self.len,
×
247
        }
248
    }
249
}
250

251
impl BitVec<Vec<usize>> {
252
    /// Creates a new bit vector of length `len` initialized to `false`.
253
    pub fn new(len: usize) -> Self {
104,592✔
254
        Self::with_value(len, false)
209,184✔
255
    }
256

257
    /// Creates a new bit vector of length `len` initialized to `value`.
258
    pub fn with_value(len: usize, value: bool) -> Self {
105,262✔
259
        let n_of_words = len.div_ceil(BITS);
315,786✔
260
        let extra_bits = (n_of_words * BITS) - len;
210,524✔
261
        let word_value = if value { !0 } else { 0 };
315,786✔
262
        let mut bits = vec![word_value; n_of_words];
421,048✔
263
        if extra_bits > 0 {
106,702✔
264
            let last_word_value = word_value >> extra_bits;
4,320✔
265
            bits[n_of_words - 1] = last_word_value;
1,440✔
266
        }
267
        Self { bits, len }
268
    }
269

270
    /// Creates a new zero-length bit vector of given capacity.
271
    ///
272
    /// Note that the capacity will be rounded up to a multiple of the word
273
    /// size.
274
    pub fn with_capacity(capacity: usize) -> Self {
50✔
275
        let n_of_words = capacity.div_ceil(BITS);
150✔
276
        Self {
277
            bits: Vec::with_capacity(n_of_words),
50✔
278
            len: 0,
279
        }
280
    }
281

282
    /// Returns the currency capacity of this bit vector.
283
    pub fn capacity(&self) -> usize {
80✔
284
        self.bits.capacity() * BITS
80✔
285
    }
286

287
    /// Appends a bit to the end of this bit vector.
288
    pub fn push(&mut self, b: bool) {
2,147,483,647✔
289
        if self.bits.len() * BITS == self.len {
2,147,483,647✔
290
            self.bits.push(0);
40,495,570✔
291
        }
292
        let word_index = self.len / BITS;
2,147,483,647✔
293
        let bit_index = self.len % BITS;
2,147,483,647✔
294
        // Clear bit
295
        self.bits[word_index] &= !(1 << bit_index);
2,147,483,647✔
296
        // Set bit
297
        self.bits[word_index] |= (b as usize) << bit_index;
2,147,483,647✔
298
        self.len += 1;
2,147,483,647✔
299
    }
300

301
    /// Removes the last bit from the bit vector and returns it, or `None` if it
302
    /// is empty.
303
    pub fn pop(&mut self) -> Option<bool> {
1,005✔
304
        if self.len == 0 {
1,005✔
305
            return None;
5✔
306
        }
NEW
307
        let last_pos = self.len - 1;
×
NEW
308
        let result = unsafe { self.get_unchecked(last_pos) };
×
NEW
309
        self.len = last_pos;
×
NEW
310
        Some(result)
×
311
    }
312

313
    /// Resizes the bit vector in place, extending it with `value` if it is
314
    /// necessary.
315
    pub fn resize(&mut self, new_len: usize, value: bool) {
10✔
316
        // TODO: rewrite by word
317
        if new_len > self.len {
10✔
318
            if new_len > self.bits.len() * BITS {
15✔
319
                self.bits.resize(new_len.div_ceil(BITS), 0);
15✔
320
            }
321
            for i in self.len..new_len {
510✔
322
                unsafe {
UNCOV
323
                    self.set_unchecked(i, value);
×
324
                }
325
            }
326
        }
327
        self.len = new_len;
10✔
328
    }
329
}
330

331
impl<B: AsRef<[usize]>> BitCount for BitVec<B> {
332
    fn count_ones(&self) -> usize {
102,270✔
333
        let full_words = self.len() / BITS;
204,540✔
334
        let residual = self.len() % BITS;
204,540✔
335
        let bits = self.as_ref();
306,810✔
336
        let mut num_ones = bits[..full_words]
204,540✔
337
            .iter()
338
            .map(|x| x.count_ones() as usize)
706,963,010✔
339
            .sum();
340
        if residual != 0 {
102,270✔
341
            num_ones += (self.as_ref()[full_words] << (BITS - residual)).count_ones() as usize
183,216✔
342
        }
343
        num_ones
102,270✔
344
    }
345
}
346

347
impl<B: AsRef<[usize]>> Index<usize> for BitVec<B> {
348
    type Output = bool;
349

350
    fn index(&self, index: usize) -> &Self::Output {
325,878,760✔
351
        match self.get(index) {
651,757,520✔
352
            false => &false,
172,741,020✔
353
            true => &true,
153,137,740✔
354
        }
355
    }
356
}
357

358
impl Extend<bool> for BitVec<Vec<usize>> {
359
    fn extend<T>(&mut self, i: T)
20,582✔
360
    where
361
        T: IntoIterator<Item = bool>,
362
    {
363
        for b in i {
1,035,509,862✔
UNCOV
364
            self.push(b);
×
365
        }
366
    }
367
}
368

369
impl FromIterator<bool> for BitVec<Vec<usize>> {
370
    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
20,582✔
371
        let mut res = Self::new(0);
41,164✔
372
        res.extend(iter);
61,746✔
373
        res
20,582✔
374
    }
375
}
376

377
impl<'a, B: AsRef<[usize]>> IntoIterator for &'a BitVec<B> {
378
    type IntoIter = BitIterator<'a, B>;
379
    type Item = bool;
380

381
    fn into_iter(self) -> Self::IntoIter {
6,794✔
382
        BitIterator::new(&self.bits, self.len())
27,176✔
383
    }
384
}
385

386
impl Eq for BitVec<Vec<usize>> {}
387

388
impl<B: AsRef<[usize]>> fmt::Display for BitVec<B> {
UNCOV
389
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
×
UNCOV
390
        write!(f, "[")?;
×
UNCOV
391
        for b in self {
×
UNCOV
392
            write!(f, "{:b}", b as usize)?;
×
393
        }
UNCOV
394
        write!(f, "]")?;
×
UNCOV
395
        Ok(())
×
396
    }
397
}
398

399
#[derive(Debug, Clone, MemDbg, MemSize)]
400
/// A thread-safe bit vector.
401
///
402
/// See the [module documentation](mod@crate::bits::bit_vec) for details.
403
pub struct AtomicBitVec<B = Vec<AtomicUsize>> {
404
    bits: B,
405
    len: usize,
406
}
407

408
impl<B> AtomicBitVec<B> {
409
    /// Returns the number of bits in the bit vector.
410
    ///
411
    /// This method is equivalent to [`BitLength::len`], but it is provided to
412
    /// reduce ambiguity in method resolution.
413
    #[inline(always)]
414
    pub fn len(&self) -> usize {
77✔
415
        BitLength::len(self)
154✔
416
    }
417

418
    /// # Safety
419
    /// `len` must be between 0 (included) the number of
420
    /// bits in `bits` (included).
421
    #[inline(always)]
422
    pub unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
3✔
423
        Self { bits, len }
424
    }
425
    #[inline(always)]
426
    pub fn into_raw_parts(self) -> (B, usize) {
1✔
427
        (self.bits, self.len)
1✔
428
    }
429
}
430

431
impl AtomicBitVec<Vec<AtomicUsize>> {
432
    /// Creates a new atomic bit vector of length `len` initialized to `false`.
433
    pub fn new(len: usize) -> Self {
115✔
434
        Self::with_value(len, false)
230✔
435
    }
436

437
    /// Creates a new atomic bit vector of length `len` initialized to `value`.
438
    pub fn with_value(len: usize, value: bool) -> Self {
120✔
439
        let n_of_words = len.div_ceil(BITS);
360✔
440
        let extra_bits = (n_of_words * BITS) - len;
240✔
441
        let word_value = if value { !0 } else { 0 };
360✔
442
        let mut bits = (0..n_of_words)
240✔
443
            .map(|_| AtomicUsize::new(word_value))
1,260✔
444
            .collect::<Vec<_>>();
445
        if extra_bits > 0 {
210✔
446
            let last_word_value = word_value >> extra_bits;
270✔
447
            bits[n_of_words - 1] = AtomicUsize::new(last_word_value);
180✔
448
        }
449
        Self { bits, len }
450
    }
451
}
452

453
impl<B> BitLength for AtomicBitVec<B> {
454
    #[inline(always)]
455
    fn len(&self) -> usize {
21,628✔
456
        self.len
21,628✔
457
    }
458
}
459

460
impl<B: AsRef<[AtomicUsize]>> Index<usize> for AtomicBitVec<B> {
461
    type Output = bool;
462

463
    /// Shorthand for `get` using [`Ordering::Relaxed`].
464
    fn index(&self, index: usize) -> &Self::Output {
10,000✔
465
        match self.get(index, Ordering::Relaxed) {
30,000✔
466
            false => &false,
9,500✔
467
            true => &true,
500✔
468
        }
469
    }
470
}
471

472
impl<B: AsRef<[AtomicUsize]>> BitCount for AtomicBitVec<B> {
473
    fn count_ones(&self) -> usize {
3✔
474
        let full_words = self.len() / BITS;
6✔
475
        let residual = self.len() % BITS;
6✔
476
        let bits = self.as_ref();
9✔
UNCOV
477
        let mut num_ones;
×
478
        // Just to be sure, add a fence to ensure that we will see all the final
479
        // values
480
        core::sync::atomic::fence(Ordering::SeqCst);
6✔
481
        num_ones = bits[..full_words]
3✔
482
            .iter()
3✔
483
            .map(|x| x.load(Ordering::Relaxed).count_ones() as usize)
63✔
484
            .sum();
3✔
485
        if residual != 0 {
3✔
486
            num_ones += (bits[full_words].load(Ordering::Relaxed) << (BITS - residual)).count_ones()
6✔
487
                as usize
2✔
488
        }
489
        num_ones
3✔
490
    }
491
}
492

493
// Conversions
494

495
impl<W: IntoAtomic> From<BitVec<Vec<W>>> for AtomicBitVec<Vec<W::AtomicType>> {
496
    fn from(value: BitVec<Vec<W>>) -> Self {
2✔
497
        AtomicBitVec {
498
            bits: transmute_vec_into_atomic(value.bits),
4✔
499
            len: value.len,
2✔
500
        }
501
    }
502
}
503

504
/// This conversion may fail if the alignment of `W` is not the same as
505
/// that of `W::AtomicType`.
506
impl<'a, W: IntoAtomic> TryFrom<BitVec<&'a [W]>> for AtomicBitVec<&'a [W::AtomicType]> {
507
    type Error = CannotCastToAtomicError<W>;
508
    fn try_from(value: BitVec<&'a [W]>) -> Result<Self, Self::Error> {
1✔
509
        if core::mem::align_of::<W>() != core::mem::align_of::<W::AtomicType>() {
1✔
UNCOV
510
            return Err(CannotCastToAtomicError::default());
×
511
        }
UNCOV
512
        Ok(AtomicBitVec {
×
UNCOV
513
            bits: unsafe { core::mem::transmute::<&'a [W], &'a [W::AtomicType]>(value.bits) },
×
UNCOV
514
            len: value.len,
×
515
        })
516
    }
517
}
518

519
/// This conversion may fail if the alignment of `W` is not the same as
520
/// that of `W::AtomicType`.
521
impl<'a, W: IntoAtomic> TryFrom<BitVec<&'a mut [W]>> for AtomicBitVec<&'a mut [W::AtomicType]> {
522
    type Error = CannotCastToAtomicError<W>;
523
    fn try_from(value: BitVec<&'a mut [W]>) -> Result<Self, Self::Error> {
1✔
524
        if core::mem::align_of::<W>() != core::mem::align_of::<W::AtomicType>() {
1✔
UNCOV
525
            return Err(CannotCastToAtomicError::default());
×
526
        }
UNCOV
527
        Ok(AtomicBitVec {
×
UNCOV
528
            bits: unsafe {
×
UNCOV
529
                core::mem::transmute::<&'a mut [W], &'a mut [W::AtomicType]>(value.bits)
×
530
            },
UNCOV
531
            len: value.len,
×
532
        })
533
    }
534
}
535

536
impl<W: IntoAtomic> From<AtomicBitVec<Vec<W::AtomicType>>> for BitVec<Vec<W>> {
537
    fn from(value: AtomicBitVec<Vec<W::AtomicType>>) -> Self {
30✔
538
        BitVec {
539
            bits: transmute_vec_from_atomic::<W::AtomicType>(value.bits),
60✔
540
            len: value.len,
30✔
541
        }
542
    }
543
}
544

545
impl<W: IntoAtomic> From<AtomicBitVec<Box<[W::AtomicType]>>> for BitVec<Box<[W]>> {
546
    fn from(value: AtomicBitVec<Box<[W::AtomicType]>>) -> Self {
1✔
547
        BitVec {
548
            bits: transmute_boxed_slice_from_atomic::<W::AtomicType>(value.bits),
2✔
549
            len: value.len,
1✔
550
        }
551
    }
552
}
553

554
impl<W: IntoAtomic + Copy> From<BitVec<Box<[W]>>> for AtomicBitVec<Box<[W::AtomicType]>> {
555
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
556
        AtomicBitVec {
557
            bits: transmute_boxed_slice_into_atomic::<W>(value.bits),
2✔
558
            len: value.len,
1✔
559
        }
560
    }
561
}
562

563
impl<'a, W: IntoAtomic> From<AtomicBitVec<&'a [W::AtomicType]>> for BitVec<&'a [W]> {
564
    fn from(value: AtomicBitVec<&'a [W::AtomicType]>) -> Self {
1✔
565
        BitVec {
566
            bits: unsafe { core::mem::transmute::<&'a [W::AtomicType], &'a [W]>(value.bits) },
1✔
567
            len: value.len,
1✔
568
        }
569
    }
570
}
571

572
impl<'a, W: IntoAtomic> From<AtomicBitVec<&'a mut [W::AtomicType]>> for BitVec<&'a mut [W]> {
573
    fn from(value: AtomicBitVec<&'a mut [W::AtomicType]>) -> Self {
1✔
574
        BitVec {
575
            bits: unsafe {
1✔
576
                core::mem::transmute::<&'a mut [W::AtomicType], &'a mut [W]>(value.bits)
577
            },
578
            len: value.len,
1✔
579
        }
580
    }
581
}
582

583
impl<W> From<BitVec<Vec<W>>> for BitVec<Box<[W]>> {
584
    fn from(value: BitVec<Vec<W>>) -> Self {
156✔
585
        BitVec {
586
            bits: value.bits.into_boxed_slice(),
312✔
587
            len: value.len,
156✔
588
        }
589
    }
590
}
591

592
impl<W> From<BitVec<Box<[W]>>> for BitVec<Vec<W>> {
593
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
594
        BitVec {
595
            bits: value.bits.into_vec(),
2✔
596
            len: value.len,
1✔
597
        }
598
    }
599
}
600

601
impl<W, B: AsRef<[W]>> AsRef<[W]> for BitVec<B> {
602
    #[inline(always)]
603
    fn as_ref(&self) -> &[W] {
2,147,483,647✔
604
        self.bits.as_ref()
2,147,483,647✔
605
    }
606
}
607

608
impl<W, B: AsMut<[W]>> AsMut<[W]> for BitVec<B> {
609
    #[inline(always)]
610
    fn as_mut(&mut self) -> &mut [W] {
2,147,483,647✔
611
        self.bits.as_mut()
2,147,483,647✔
612
    }
613
}
614

615
impl<W, B: AsRef<[W]>> AsRef<[W]> for AtomicBitVec<B> {
616
    #[inline(always)]
617
    fn as_ref(&self) -> &[W] {
21,563✔
618
        self.bits.as_ref()
21,563✔
619
    }
620
}
621

622
// We implement [`IntoIterator`] for a mutable reference so no
623
// outstanding references are allowed while iterating.
624
impl<'a, B: AsRef<[AtomicUsize]>> IntoIterator for &'a AtomicBitVec<B> {
625
    type IntoIter = AtomicBitIterator<'a, B>;
626
    type Item = bool;
627

UNCOV
628
    fn into_iter(self) -> Self::IntoIter {
×
NEW
629
        AtomicBitIterator::new(&self.bits, self.len())
×
630
    }
631
}
632

633
impl<B: AsRef<[usize]>, C: AsRef<[usize]>> PartialEq<BitVec<C>> for BitVec<B> {
634
    fn eq(&self, other: &BitVec<C>) -> bool {
70✔
635
        let len = self.len();
210✔
636
        if len != other.len() {
140✔
637
            return false;
1✔
638
        }
639

640
        let full_words = len / BITS;
×
641
        if self.as_ref()[..full_words] != other.as_ref()[..full_words] {
×
642
            return false;
×
643
        }
644

UNCOV
645
        let residual = len % BITS;
×
646

UNCOV
647
        residual == 0
×
648
            || (self.as_ref()[full_words] ^ other.as_ref()[full_words]) << (BITS - residual) == 0
67✔
649
    }
650
}
651

652
impl<B: AsRef<[usize]>> RankHinted<64> for BitVec<B> {
653
    #[inline(always)]
654
    unsafe fn rank_hinted(&self, pos: usize, hint_pos: usize, hint_rank: usize) -> usize {
39,618,006✔
655
        let bits = self.as_ref();
118,854,018✔
656
        let mut rank = hint_rank;
79,236,012✔
657
        let mut hint_pos = hint_pos;
79,236,012✔
658

659
        debug_assert!(
39,618,006✔
660
            hint_pos < bits.len(),
79,236,012✔
UNCOV
661
            "hint_pos: {}, len: {}",
×
UNCOV
662
            hint_pos,
×
UNCOV
663
            bits.len()
×
664
        );
665

666
        while (hint_pos + 1) * 64 <= pos {
293,114,022✔
667
            rank += unsafe { bits.get_unchecked(hint_pos).count_ones() } as usize;
126,748,008✔
668
            hint_pos += 1;
126,748,008✔
669
        }
670

671
        rank + (unsafe { bits.get_unchecked(hint_pos) } & ((1 << (pos % 64)) - 1)).count_ones()
158,472,024✔
672
            as usize
39,618,006✔
673
    }
674
}
675

676
impl<B: AsRef<[usize]>> SelectHinted for BitVec<B> {
677
    unsafe fn select_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
2,147,483,647✔
678
        let mut word_index = hint_pos / BITS;
2,147,483,647✔
679
        let bit_index = hint_pos % BITS;
2,147,483,647✔
680
        let mut residual = rank - hint_rank;
2,147,483,647✔
681
        let mut word =
2,147,483,647✔
682
            (unsafe { self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
2,147,483,647✔
UNCOV
683
        loop {
×
684
            let bit_count = word.count_ones() as usize;
2,147,483,647✔
685
            if residual < bit_count {
2,147,483,647✔
686
                return word_index * BITS + word.select_in_word(residual);
2,147,483,647✔
687
            }
688
            word_index += 1;
×
UNCOV
689
            word = *unsafe { self.as_ref().get_unchecked(word_index) };
×
UNCOV
690
            residual -= bit_count;
×
691
        }
692
    }
693
}
694

695
impl<B: AsRef<[usize]>> SelectZeroHinted for BitVec<B> {
696
    unsafe fn select_zero_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
2,147,483,647✔
697
        let mut word_index = hint_pos / BITS;
2,147,483,647✔
698
        let bit_index = hint_pos % BITS;
2,147,483,647✔
699
        let mut residual = rank - hint_rank;
2,147,483,647✔
700
        let mut word =
2,147,483,647✔
701
            (!*unsafe { self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
2,147,483,647✔
UNCOV
702
        loop {
×
703
            let bit_count = word.count_ones() as usize;
2,147,483,647✔
704
            if residual < bit_count {
2,147,483,647✔
705
                return word_index * BITS + word.select_in_word(residual);
2,147,483,647✔
706
            }
UNCOV
707
            word_index += 1;
×
UNCOV
708
            word = unsafe { !self.as_ref().get_unchecked(word_index) };
×
UNCOV
709
            residual -= bit_count;
×
710
        }
711
    }
712
}
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