Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions roaring/src/bitmap/store/array_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,10 @@ impl ArrayStore {

let mut vec = Vec::with_capacity(bits_set as usize);

let chunks = bytes.chunks_exact(size_of::<Word>());
let remainder = chunks.remainder();
for (index, chunk) in chunks.enumerate() {
let (chunks, remainder) = bytes.as_chunks::<{ size_of::<Word>() }>();
for (index, chunk) in chunks.iter().enumerate() {
let bit_index = (byte_offset + index * size_of::<Word>()) * 8;
let mut word = Word::from_le_bytes(chunk.try_into().unwrap());
let mut word = Word::from_le_bytes(*chunk);

while word != 0 {
vec.push((word.trailing_zeros() + bit_index as u32) as u16);
Expand Down
5 changes: 2 additions & 3 deletions roaring/src/bitmap/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ impl Store {
// using u64s than for each byte
let bits_set = {
let mut bits_set = 0;
let chunks = bytes.chunks_exact(mem::size_of::<u64>());
let remainder = chunks.remainder();
let (chunks, remainder) = bytes.as_chunks::<{ mem::size_of::<u64>() }>();
for chunk in chunks {
let chunk = u64::from_ne_bytes(chunk.try_into().unwrap());
let chunk = u64::from_ne_bytes(*chunk);
bits_set += u64::from(chunk.count_ones());
}
for byte in remainder {
Expand Down
3 changes: 3 additions & 0 deletions roaring/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ impl fmt::Display for IntegerTooSmall {
}
}

#[cfg(feature = "std")]
impl std::error::Error for IntegerTooSmall {}

/// An error type that is returned when an iterator isn't sorted.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NonSortedIntegers {
Expand Down
79 changes: 55 additions & 24 deletions roaring/src/treemap/iter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloc::collections::{btree_map, BTreeMap};
use core::cmp::Ordering;
use core::iter;
use core::ops::Add;

Expand Down Expand Up @@ -147,24 +148,39 @@ impl Iter<'_> {
pub fn advance_to(&mut self, n: u64) {
let (key, index) = util::split(n);

if let Some(ref mut front) = self.front {
match front.hi.cmp(&key) {
Ordering::Less => {}
Ordering::Equal => {
front.advance_to(index);
return;
}
Ordering::Greater => return,
}
self.front = None;
}

self.outer.advance_to(key);

if self.front.is_none() {
let Some(next) = self.outer.next() else {
// if the current front iterator is empty or not yet initialized,
// but the outer bitmap iterator is empty, then consume the back
// iterator from the front if it is not also exhausted
if let Some(ref mut back) = self.back {
back.advance_to(index);
let Some(next) = self.outer.next() else {
// if the current front iterator is empty or not yet initialized,
// but the outer bitmap iterator is empty, then consume the back
// iterator from the front if it is not also exhausted
if let Some(ref mut back) = self.back {
match back.hi.cmp(&key) {
Ordering::Less => self.back = None,
Ordering::Equal => back.advance_to(index),
Ordering::Greater => {}
}
return;
};
self.front = Some(to64iter(next));
}
}
return;
};

if let Some(ref mut front) = self.front {
let mut front = to64iter(next);
if front.hi == key {
front.advance_to(index);
}
self.front = Some(front);
}

/// Advance the back of the iterator to the first position where the item has a value <= `n`
Expand All @@ -185,24 +201,39 @@ impl Iter<'_> {
pub fn advance_back_to(&mut self, n: u64) {
let (key, index) = util::split(n);

if let Some(ref mut back) = self.back {
match back.hi.cmp(&key) {
Ordering::Less => return,
Ordering::Equal => {
back.advance_back_to(index);
return;
}
Ordering::Greater => {}
}
self.back = None;
}

self.outer.advance_back_to(key);

if self.back.is_none() {
let Some(next_back) = self.outer.next_back() else {
// if the current back iterator is empty or not yet initialized,
// but the outer bitmap iterator is empty, then consume the front
// iterator from the back if it is not also exhausted
if let Some(ref mut front) = self.front {
front.advance_back_to(index);
let Some(next_back) = self.outer.next_back() else {
// if the current back iterator is empty or not yet initialized,
// but the outer bitmap iterator is empty, then consume the front
// iterator from the back if it is not also exhausted
if let Some(ref mut front) = self.front {
match front.hi.cmp(&key) {
Ordering::Less => {}
Ordering::Equal => front.advance_back_to(index),
Ordering::Greater => self.front = None,
}
return;
};
self.back = Some(to64iter(next_back));
}
}
return;
};

if let Some(ref mut back) = self.back {
let mut back = to64iter(next_back);
if back.hi == key {
back.advance_back_to(index);
}
self.back = Some(back);
}
}

Expand Down
50 changes: 50 additions & 0 deletions roaring/tests/treemap_iter_advance_to.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ fn to_next_bitmap() {
assert_eq!(i.next(), None);
}

#[test]
fn advance_to_later_bitmap_after_iteration_started() {
let later_bitmap = 1u64 << 32;
let bm = RoaringTreemap::from([1, 3, later_bitmap]);
let mut i = bm.iter();

assert_eq!(i.next(), Some(1));
i.advance_to(later_bitmap);

assert_eq!(i.next(), Some(later_bitmap));
assert_eq!(i.next(), None);
}

#[test]
fn advance_to_missing_bitmap() {
let later_bitmap = 1u64 << 32;
let bm = RoaringTreemap::from([later_bitmap]);
let mut i = bm.iter();

i.advance_to(3);

assert_eq!(i.next(), Some(later_bitmap));
assert_eq!(i.next(), None);
}

#[test]
fn iter_back_basic() {
let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]);
Expand All @@ -47,6 +72,31 @@ fn iter_back_basic() {
assert_eq!(i.next_back(), None);
}

#[test]
fn advance_back_to_earlier_bitmap_after_iteration_started() {
let later_bitmap = 1u64 << 32;
let bm = RoaringTreemap::from([1, later_bitmap, later_bitmap + 2]);
let mut i = bm.iter();

assert_eq!(i.next_back(), Some(later_bitmap + 2));
i.advance_back_to(1);

assert_eq!(i.next_back(), Some(1));
assert_eq!(i.next_back(), None);
}

#[test]
fn advance_back_to_missing_bitmap() {
let later_bitmap = 1u64 << 32;
let bm = RoaringTreemap::from([3]);
let mut i = bm.iter();

i.advance_back_to(later_bitmap);

assert_eq!(i.next_back(), Some(3));
assert_eq!(i.next_back(), None);
}

#[test]
fn iter_advance_past_end() {
let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]);
Expand Down
Loading