use super::Bitmap;
use core::marker::PhantomData;
use core::mem::MaybeUninit;
#[derive(Debug, Clone)]
pub struct BitmapCursor<'a> {
raw: ffi::roaring_uint32_iterator_t,
_bitmap: PhantomData<&'a Bitmap>,
}
unsafe impl Send for BitmapCursor<'_> {}
unsafe impl Sync for BitmapCursor<'_> {}
impl<'a> BitmapCursor<'a> {
#[inline]
fn from_raw(raw: ffi::roaring_uint32_iterator_t) -> Self {
BitmapCursor {
raw,
_bitmap: PhantomData,
}
}
fn at_first(bitmap: &'a Bitmap) -> Self {
let mut raw = MaybeUninit::<ffi::roaring_uint32_iterator_s>::uninit();
unsafe { ffi::roaring_iterator_init(&bitmap.bitmap, raw.as_mut_ptr()) };
Self::from_raw(unsafe { raw.assume_init() })
}
fn at_last(bitmap: &'a Bitmap) -> Self {
let mut raw = MaybeUninit::<ffi::roaring_uint32_iterator_s>::uninit();
unsafe { ffi::roaring_iterator_init_last(&bitmap.bitmap, raw.as_mut_ptr()) };
Self::from_raw(unsafe { raw.assume_init() })
}
#[inline]
#[must_use]
pub fn has_value(&self) -> bool {
self.raw.has_value
}
#[inline]
#[must_use]
pub fn current(&self) -> Option<u32> {
if self.has_value() {
Some(self.raw.current_value)
} else {
None
}
}
#[inline]
pub fn move_next(&mut self) {
unsafe { ffi::roaring_uint32_iterator_advance(&mut self.raw) };
}
#[inline]
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<u32> {
self.move_next();
self.current()
}
#[inline]
pub fn move_prev(&mut self) {
unsafe { ffi::roaring_uint32_iterator_previous(&mut self.raw) };
}
#[inline]
pub fn prev(&mut self) -> Option<u32> {
self.move_prev();
self.current()
}
#[must_use]
pub fn reset_to_first(self, bitmap: &Bitmap) -> BitmapCursor<'_> {
BitmapCursor::at_first(bitmap)
}
#[must_use]
pub fn reset_to_last(self, bitmap: &Bitmap) -> BitmapCursor<'_> {
BitmapCursor::at_last(bitmap)
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_read")]
#[must_use]
pub fn read_many(&mut self, dst: &mut [u32]) -> usize {
let count = u32::try_from(dst.len()).unwrap_or(u32::MAX);
let result =
unsafe { ffi::roaring_uint32_iterator_read(&mut self.raw, dst.as_mut_ptr(), count) };
debug_assert!(result <= count);
result as usize
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u32) {
unsafe { ffi::roaring_uint32_iterator_move_equalorlarger(&mut self.raw, val) };
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_skip")]
pub fn skip(&mut self, n: u32) -> u32 {
unsafe { ffi::roaring_uint32_iterator_skip(&mut self.raw, n) }
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_skip_backward")]
pub fn skip_backward(&mut self, n: u32) -> u32 {
unsafe { ffi::roaring_uint32_iterator_skip_backward(&mut self.raw, n) }
}
}
#[derive(Clone)]
pub struct BitmapIterator<'a> {
cursor: BitmapCursor<'a>,
}
impl<'a> BitmapIterator<'a> {
fn new(bitmap: &'a Bitmap) -> Self {
Self {
cursor: BitmapCursor::at_first(bitmap),
}
}
#[inline]
fn current_value(&self) -> Option<u32> {
self.cursor.current()
}
#[inline]
fn advance(&mut self) {
self.cursor.move_next();
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_read")]
#[must_use]
pub fn next_many(&mut self, dst: &mut [u32]) -> usize {
self.cursor.read_many(dst)
}
#[inline]
#[doc(alias = "roaring_uint32_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u32) {
self.cursor.reset_at_or_after(val);
}
#[inline]
#[must_use]
pub fn peek(&self) -> Option<u32> {
self.cursor.current()
}
}
impl<'a> Iterator for BitmapIterator<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
match self.current_value() {
Some(value) => {
self.advance();
Some(value)
}
None => None,
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if n > 0 {
self.cursor.skip(u32::try_from(n).unwrap_or(u32::MAX));
}
self.next()
}
}
impl Bitmap {
#[inline]
#[doc(alias = "roaring_init_iterator")]
#[must_use]
pub fn iter(&self) -> BitmapIterator<'_> {
BitmapIterator::new(self)
}
#[inline]
#[must_use]
pub fn cursor(&self) -> BitmapCursor<'_> {
BitmapCursor::at_first(self)
}
#[inline]
#[must_use]
pub fn cursor_to_last(&self) -> BitmapCursor<'_> {
BitmapCursor::at_last(self)
}
}
impl<'a> From<BitmapIterator<'a>> for BitmapCursor<'a> {
fn from(iterator: BitmapIterator<'a>) -> Self {
iterator.cursor
}
}
impl<'a> From<BitmapCursor<'a>> for BitmapIterator<'a> {
fn from(cursor: BitmapCursor<'a>) -> Self {
BitmapIterator { cursor }
}
}
impl FromIterator<u32> for Bitmap {
fn from_iter<I: IntoIterator<Item = u32>>(iter: I) -> Self {
let mut bitmap = Bitmap::new();
bitmap.extend(iter);
bitmap
}
}
impl Extend<u32> for Bitmap {
fn extend<T: IntoIterator<Item = u32>>(&mut self, iter: T) {
let mut ctx = MaybeUninit::<ffi::roaring_bulk_context_t>::zeroed();
iter.into_iter().for_each(|item| unsafe {
ffi::roaring_bitmap_add_bulk(&mut self.bitmap, ctx.as_mut_ptr(), item);
});
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iter_nth() {
let bitmap = Bitmap::of(&[1, 2, 3, 4, 5]);
let mut iter = bitmap.iter();
assert_eq!(iter.nth(0), Some(1));
assert_eq!(iter.nth(1), Some(3));
assert_eq!(iter.nth(10), None);
}
}