Skip to content

Commit cdfdb99

Browse files
committed
Add element iterator for ChunkedBitSet
1 parent 76d4862 commit cdfdb99

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

compiler/rustc_index/src/bit_set.rs

+48
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,11 @@ impl<T: Idx> ChunkedBitSet<T> {
479479
}
480480
}
481481

482+
#[inline]
483+
pub fn iter(&self) -> ChunkedBitIter<'_, T> {
484+
ChunkedBitIter::new(self)
485+
}
486+
482487
/// Insert `elem`. Returns whether the set has changed.
483488
pub fn insert(&mut self, elem: T) -> bool {
484489
assert!(elem.index() < self.domain_size);
@@ -697,6 +702,49 @@ impl<T> Clone for ChunkedBitSet<T> {
697702
}
698703
}
699704

705+
pub struct ChunkedBitIter<'a, T: Idx> {
706+
index: usize,
707+
bitset: &'a ChunkedBitSet<T>,
708+
}
709+
710+
impl<'a, T: Idx> ChunkedBitIter<'a, T> {
711+
#[inline]
712+
fn new(bitset: &'a ChunkedBitSet<T>) -> ChunkedBitIter<'a, T> {
713+
ChunkedBitIter { index: 0, bitset }
714+
}
715+
}
716+
717+
impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> {
718+
type Item = T;
719+
fn next(&mut self) -> Option<T> {
720+
while self.index < self.bitset.domain_size() {
721+
let elem = T::new(self.index);
722+
let chunk = &self.bitset.chunks[chunk_index(elem)];
723+
match &chunk {
724+
Zeros(chunk_domain_size) => {
725+
self.index += *chunk_domain_size as usize;
726+
}
727+
Ones(_chunk_domain_size) => {
728+
self.index += 1;
729+
return Some(elem);
730+
}
731+
Mixed(_chunk_domain_size, _, words) => loop {
732+
let elem = T::new(self.index);
733+
self.index += 1;
734+
let (word_index, mask) = chunk_word_index_and_mask(elem);
735+
if (words[word_index] & mask) != 0 {
736+
return Some(elem);
737+
}
738+
if self.index % CHUNK_BITS == 0 {
739+
break;
740+
}
741+
},
742+
}
743+
}
744+
None
745+
}
746+
}
747+
700748
impl Chunk {
701749
#[cfg(test)]
702750
fn assert_valid(&self) {

compiler/rustc_index/src/bit_set/tests.rs

+34
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,40 @@ fn chunked_bitset() {
342342
b10000b.assert_valid();
343343
}
344344

345+
#[test]
346+
fn chunked_bitset_iter() {
347+
fn with_elements(elements: &[usize], domain_size: usize) -> ChunkedBitSet<usize> {
348+
let mut s = ChunkedBitSet::new_empty(domain_size);
349+
for &e in elements {
350+
s.insert(e);
351+
}
352+
s
353+
}
354+
355+
// Empty
356+
let vec: Vec<usize> = Vec::new();
357+
let bit = with_elements(&vec, 9000);
358+
assert_eq!(vec, bit.iter().collect::<Vec<_>>());
359+
360+
// Filled
361+
let n = 10000;
362+
let vec: Vec<usize> = (0..n).collect();
363+
let bit = with_elements(&vec, n);
364+
assert_eq!(vec, bit.iter().collect::<Vec<_>>());
365+
366+
// Filled with trailing zeros
367+
let n = 10000;
368+
let vec: Vec<usize> = (0..n).collect();
369+
let bit = with_elements(&vec, 2 * n);
370+
assert_eq!(vec, bit.iter().collect::<Vec<_>>());
371+
372+
// Mixed
373+
let n = 12345;
374+
let vec: Vec<usize> = vec![0, 1, 2, 2010, 2047, 2099, 6000, 6002, 6004];
375+
let bit = with_elements(&vec, n);
376+
assert_eq!(vec, bit.iter().collect::<Vec<_>>());
377+
}
378+
345379
#[test]
346380
fn grow() {
347381
let mut set: GrowableBitSet<usize> = GrowableBitSet::with_capacity(65);

0 commit comments

Comments
 (0)