Skip to content

Commit

Permalink
Misc changes to match parity with bitmap/64
Browse files Browse the repository at this point in the history
  • Loading branch information
Dr-Emann committed Mar 22, 2024
1 parent 2a40561 commit eb25648
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 21 deletions.
2 changes: 1 addition & 1 deletion croaring/benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ fn random_iter(c: &mut Criterion) {
// Super simple LCG iterator
let mut z = 20170705; // seed
std::iter::from_fn(move || {
z = (MULTIPLIER * z) % MODULUS;
z = (MULTIPLIER.wrapping_mul(z)) % MODULUS;
Some(z % MAX)
})
};
Expand Down
56 changes: 53 additions & 3 deletions croaring/src/bitmap/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::Bitmap;
///
/// A cursor points at a single value in the bitmap, or at a "ghost" position,
/// either one before the beginning of the bitmap, or one after the end of the bitmap.
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct BitmapCursor<'a> {
raw: ffi::roaring_uint32_iterator_t,
_bitmap: PhantomData<&'a Bitmap>,
Expand Down Expand Up @@ -403,7 +403,7 @@ impl<'a> BitmapIterator<'a> {
/// # print_by_chunks(&Bitmap::of(&[1, 2, 8, 20, 1000]));
/// ```
#[inline]
#[doc(alias = "roaring_read_uint32_iterator")]
#[doc(alias = "roaring_uint32_iterator_read")]
pub fn next_many(&mut self, dst: &mut [u32]) -> usize {
self.cursor.read_many(dst)
}
Expand Down Expand Up @@ -432,10 +432,26 @@ impl<'a> BitmapIterator<'a> {
/// assert_eq!(iter.next(), None);
/// ```
#[inline]
#[doc(alias = "roaring_move_uint32_iterator_equalorlarger")]
#[doc(alias = "roaring_uint32_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u32) {
self.cursor.reset_at_or_after(val);
}

/// Peek at the next value to be returned by the iterator (if any), without consuming it
///
/// # Examples
///
/// ```
/// use croaring::Bitmap;
/// let mut bitmap = Bitmap::of(&[1, 2, 3]);
/// let mut iter = bitmap.iter();
/// assert_eq!(iter.peek(), Some(1));
/// assert_eq!(iter.next(), Some(1));
/// ```
#[inline]
pub fn peek(&self) -> Option<u32> {
self.cursor.current()
}
}

impl<'a> Iterator for BitmapIterator<'a> {
Expand Down Expand Up @@ -499,12 +515,46 @@ impl Bitmap {
}
}

/// Converts this iterator into a cursor
///
/// The cursor's current value will be the the item which would have been returned by the next call to `next()`
/// or one past the end of the bitmap if the iterator is exhausted.
///
/// # Examples
///
/// ```
/// use croaring::bitmap::{Bitmap, BitmapCursor};
/// let mut bitmap = Bitmap::of(&[1, 2, 3]);
/// let mut iter = bitmap.iter();
/// assert_eq!(iter.peek(), Some(1));
/// assert_eq!(iter.next(), Some(1));
///
/// assert_eq!(iter.peek(), Some(2));
/// let mut cursor: BitmapCursor = iter.into();
/// assert_eq!(cursor.current(), Some(2));
/// ```
impl<'a> From<BitmapIterator<'a>> for BitmapCursor<'a> {
fn from(iterator: BitmapIterator<'a>) -> Self {
iterator.cursor
}
}

/// Converts this cursor into an iterator
///
/// The next value returned by the iterator will be the current value of the cursor (if any).
///
/// # Examples
///
/// ```
/// use croaring::bitmap::{Bitmap, BitmapIterator};
///
/// let mut bitmap = Bitmap::of(&[1, 2, 3]);
/// let mut cursor = bitmap.cursor();
/// assert_eq!(cursor.current(), Some(1));
///
/// let mut iter = BitmapIterator::from(cursor);
/// assert_eq!(iter.next(), Some(1));
/// ```
impl<'a> From<BitmapCursor<'a>> for BitmapIterator<'a> {
fn from(cursor: BitmapCursor<'a>) -> Self {
BitmapIterator { cursor }
Expand Down
129 changes: 113 additions & 16 deletions croaring/src/bitmap64/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,12 +381,46 @@ impl<'a> Bitmap64Cursor<'a> {
}
}

/// Converts this iterator into a cursor
///
/// The cursor's current value will be the the item which would have been returned by the next call to `next()`
/// or one past the end of the bitmap if the iterator is exhausted.
///
/// # Examples
///
/// ```
/// use croaring::bitmap64::{Bitmap64, Bitmap64Cursor};
/// let mut bitmap = Bitmap64::of(&[1, 2, 3]);
/// let mut iter = bitmap.iter();
/// assert_eq!(iter.peek(), Some(1));
/// assert_eq!(iter.next(), Some(1));
///
/// assert_eq!(iter.peek(), Some(2));
/// let mut cursor: Bitmap64Cursor = iter.into();
/// assert_eq!(cursor.current(), Some(2));
/// ```
impl<'a> From<Bitmap64Iterator<'a>> for Bitmap64Cursor<'a> {
fn from(iter: Bitmap64Iterator<'a>) -> Self {
iter.into_cursor()
iter.cursor
}
}

/// Converts this cursor into an iterator
///
/// The next value returned by the iterator will be the current value of the cursor (if any).
///
/// # Examples
///
/// ```
/// use croaring::bitmap64::{Bitmap64, Bitmap64Iterator};
///
/// let mut bitmap = Bitmap64::of(&[1, 2, 3]);
/// let mut cursor = bitmap.cursor();
/// assert_eq!(cursor.current(), Some(1));
///
/// let mut iter = Bitmap64Iterator::from(cursor);
/// assert_eq!(iter.next(), Some(1));
/// ```
impl<'a> From<Bitmap64Cursor<'a>> for Bitmap64Iterator<'a> {
fn from(cursor: Bitmap64Cursor<'a>) -> Self {
Bitmap64Iterator { cursor }
Expand Down Expand Up @@ -418,26 +452,92 @@ impl<'a> Bitmap64Iterator<'a> {
self.cursor.move_next();
}

/// Peek at the next value to be returned by the iterator (if any), without consuming it
/// Attempt to read many values from the iterator into `dst`
///
/// Returns the number of items read from the iterator, may be `< dst.len()` iff
/// the iterator is exhausted or `dst.len() > u64::MAX`.
///
/// This can be much more efficient than repeated iteration.
///
/// # Examples
///
/// ```
/// use croaring::Bitmap64;
/// let mut bitmap = Bitmap64::of(&[1, 2, 3]);
///
/// let mut bitmap: Bitmap64 = Bitmap64::new();
/// bitmap.add_range(0..100);
/// bitmap.add(222);
/// bitmap.add(555);
///
/// let mut buf = [0; 100];
/// let mut iter = bitmap.iter();
/// assert_eq!(iter.peek(), Some(1));
/// assert_eq!(iter.next(), Some(1));
/// assert_eq!(iter.next_many(&mut buf), 100);
/// // Get the first 100 items, from the original range added
/// for (i, item) in buf.iter().enumerate() {
/// assert_eq!(*item, i as u64);
/// }
/// // Calls to next_many() can be interleaved with calls to next()
/// assert_eq!(iter.next(), Some(222));
/// assert_eq!(iter.next_many(&mut buf), 1);
/// assert_eq!(buf[0], 555);
///
/// assert_eq!(iter.next(), None);
/// assert_eq!(iter.next_many(&mut buf), 0);
/// ```
///
/// ```
/// use croaring::Bitmap64;
///
/// fn print_by_chunks(bitmap: &Bitmap64) {
/// let mut buf = [0; 1024];
/// let mut iter = bitmap.iter();
/// loop {
/// let n = iter.next_many(&mut buf);
/// if n == 0 {
/// break;
/// }
/// println!("{:?}", &buf[..n]);
/// }
/// }
///
/// # print_by_chunks(&Bitmap64::of(&[1, 2, 8, 20, 1000]));
/// ```
#[inline]
pub fn peek(&self) -> Option<u64> {
self.cursor.current()
#[doc(alias = "roaring64_iterator_read")]
pub fn next_many(&mut self, dst: &mut [u64]) -> usize {
self.cursor.read_many(dst)
}

/// Converts this iterator into a cursor
/// Reset the iterator to the first value `>= val`
///
/// The cursor's current value will be the the item which would have been returned by the next call to `next()`
/// or one past the end of the bitmap if the iterator is exhausted.
/// This can move the iterator forwards or backwards.
///
/// # Examples
/// ```
/// use croaring::Bitmap64;
///
/// let mut bitmap = Bitmap64::of(&[0, 1, 100, 1000, u64::MAX]);
/// let mut iter = bitmap.iter();
/// iter.reset_at_or_after(0);
/// assert_eq!(iter.next(), Some(0));
/// iter.reset_at_or_after(0);
/// assert_eq!(iter.next(), Some(0));
///
/// iter.reset_at_or_after(101);
/// assert_eq!(iter.next(), Some(1000));
/// assert_eq!(iter.next(), Some(u64::MAX));
/// assert_eq!(iter.next(), None);
/// iter.reset_at_or_after(u64::MAX);
/// assert_eq!(iter.next(), Some(u64::MAX));
/// assert_eq!(iter.next(), None);
/// ```
#[inline]
#[doc(alias = "roaring64_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u64) {
self.cursor.reset_at_or_after(val);
}

/// Peek at the next value to be returned by the iterator (if any), without consuming it
///
/// # Examples
///
Expand All @@ -447,13 +547,10 @@ impl<'a> Bitmap64Iterator<'a> {
/// let mut iter = bitmap.iter();
/// assert_eq!(iter.peek(), Some(1));
/// assert_eq!(iter.next(), Some(1));
///
/// assert_eq!(iter.peek(), Some(2));
/// let mut cursor = iter.into_cursor();
/// assert_eq!(cursor.current(), Some(2));
/// ```
pub fn into_cursor(self) -> Bitmap64Cursor<'a> {
self.cursor
#[inline]
pub fn peek(&self) -> Option<u64> {
self.cursor.current()
}
}

Expand Down
2 changes: 1 addition & 1 deletion croaring/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ fn empty_cursor() {

#[test]
fn cursor_return_from_the_edge() {
let mut bitmap = Bitmap::from([1, 2, u32::MAX]);
let bitmap = Bitmap::from([1, 2, u32::MAX]);
let mut cursor = bitmap.cursor_to_last();
assert_eq!(cursor.current(), Some(u32::MAX));
assert_eq!(cursor.next(), None);
Expand Down

0 comments on commit eb25648

Please sign in to comment.