use crate::Bitmap64;
use core::marker::PhantomData;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ptr::NonNull;
impl FromIterator<u64> for Bitmap64 {
fn from_iter<I: IntoIterator<Item = u64>>(iter: I) -> Self {
let mut bitmap = Bitmap64::new();
bitmap.extend(iter);
bitmap
}
}
impl Extend<u64> for Bitmap64 {
#[doc(alias = "roaring64_bitmap_add_bulk")]
fn extend<T: IntoIterator<Item = u64>>(&mut self, iter: T) {
let mut ctx = MaybeUninit::<ffi::roaring64_bulk_context_t>::zeroed();
iter.into_iter().for_each(|value| unsafe {
ffi::roaring64_bitmap_add_bulk(self.raw.as_ptr(), ctx.as_mut_ptr(), value);
});
}
}
#[derive(Debug)]
pub struct Bitmap64Cursor<'a> {
raw: NonNull<ffi::roaring64_iterator_t>,
has_value: bool,
_bitmap: PhantomData<&'a Bitmap64>,
}
unsafe impl Send for Bitmap64Cursor<'_> {}
unsafe impl Sync for Bitmap64Cursor<'_> {}
impl Drop for Bitmap64Cursor<'_> {
fn drop(&mut self) {
unsafe {
ffi::roaring64_iterator_free(self.raw.as_ptr());
}
}
}
impl<'a> Bitmap64Cursor<'a> {
fn from_raw(raw: *mut ffi::roaring64_iterator_t) -> Self {
let raw = NonNull::new(raw).expect("Failed to allocate roaring64_iterator_t");
let has_value = unsafe { ffi::roaring64_iterator_has_value(raw.as_ptr()) };
Self {
raw,
has_value,
_bitmap: PhantomData,
}
}
fn at_first(bitmap: &'a Bitmap64) -> Self {
let raw = unsafe { ffi::roaring64_iterator_create(bitmap.raw.as_ptr()) };
Self::from_raw(raw)
}
fn at_last(bitmap: &'a Bitmap64) -> Self {
let raw = unsafe { ffi::roaring64_iterator_create_last(bitmap.raw.as_ptr()) };
Self::from_raw(raw)
}
#[inline]
pub fn has_value(&self) -> bool {
self.has_value
}
#[inline]
pub fn current(&self) -> Option<u64> {
if self.has_value() {
Some(unsafe { self.current_unchecked() })
} else {
None
}
}
unsafe fn current_unchecked(&self) -> u64 {
ffi::roaring64_iterator_value(self.raw.as_ptr())
}
#[inline]
pub fn move_next(&mut self) {
self.has_value = unsafe { ffi::roaring64_iterator_advance(self.raw.as_ptr()) };
}
#[inline]
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<u64> {
self.move_next();
self.current()
}
#[inline]
pub fn move_prev(&mut self) {
self.has_value = unsafe { ffi::roaring64_iterator_previous(self.raw.as_ptr()) };
}
#[inline]
pub fn prev(&mut self) -> Option<u64> {
self.move_prev();
self.current()
}
#[must_use]
pub fn reset_to_first(self, bitmap: &Bitmap64) -> Bitmap64Cursor<'_> {
let this = ManuallyDrop::new(self);
unsafe { ffi::roaring64_iterator_reinit(bitmap.raw.as_ptr(), this.raw.as_ptr()) };
Bitmap64Cursor::from_raw(this.raw.as_ptr())
}
#[must_use]
pub fn reset_to_last(self, bitmap: &Bitmap64) -> Bitmap64Cursor<'_> {
let this = ManuallyDrop::new(self);
unsafe { ffi::roaring64_iterator_reinit_last(bitmap.raw.as_ptr(), this.raw.as_ptr()) };
Bitmap64Cursor::from_raw(this.raw.as_ptr())
}
#[inline]
#[doc(alias = "roaring64_iterator_read")]
pub fn read_many(&mut self, dst: &mut [u64]) -> usize {
let count = u64::try_from(dst.len()).unwrap_or(u64::MAX);
let result =
unsafe { ffi::roaring64_iterator_read(self.raw.as_ptr(), dst.as_mut_ptr(), count) };
debug_assert!(result <= count);
self.has_value = unsafe { ffi::roaring64_iterator_has_value(self.raw.as_ptr()) };
result as usize
}
#[inline]
#[doc(alias = "roaring64_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u64) {
self.has_value =
unsafe { ffi::roaring64_iterator_move_equalorlarger(self.raw.as_ptr(), val) };
}
}
impl<'a> From<Bitmap64Iterator<'a>> for Bitmap64Cursor<'a> {
fn from(iter: Bitmap64Iterator<'a>) -> Self {
iter.cursor
}
}
impl<'a> From<Bitmap64Cursor<'a>> for Bitmap64Iterator<'a> {
fn from(cursor: Bitmap64Cursor<'a>) -> Self {
Bitmap64Iterator { cursor }
}
}
impl<'a> Clone for Bitmap64Cursor<'a> {
fn clone(&self) -> Self {
let raw = unsafe { ffi::roaring64_iterator_copy(self.raw.as_ptr()) };
Self::from_raw(raw)
}
}
#[derive(Debug, Clone)]
pub struct Bitmap64Iterator<'a> {
cursor: Bitmap64Cursor<'a>,
}
impl<'a> Bitmap64Iterator<'a> {
fn new(bitmap: &'a Bitmap64) -> Self {
Self {
cursor: bitmap.cursor(),
}
}
#[inline]
fn advance(&mut self) {
self.cursor.move_next();
}
#[inline]
#[must_use]
#[doc(alias = "roaring64_iterator_read")]
pub fn next_many(&mut self, dst: &mut [u64]) -> usize {
self.cursor.read_many(dst)
}
#[inline]
#[doc(alias = "roaring64_iterator_move_equalorlarger")]
pub fn reset_at_or_after(&mut self, val: u64) {
self.cursor.reset_at_or_after(val);
}
#[inline]
#[must_use]
pub fn peek(&self) -> Option<u64> {
self.cursor.current()
}
}
impl<'a> Iterator for Bitmap64Iterator<'a> {
type Item = u64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.peek() {
Some(value) => {
self.advance();
Some(value)
}
None => None,
}
}
}
impl Bitmap64 {
#[inline]
#[must_use]
pub fn iter(&self) -> Bitmap64Iterator<'_> {
Bitmap64Iterator::new(self)
}
#[inline]
#[must_use]
pub fn cursor(&self) -> Bitmap64Cursor<'_> {
Bitmap64Cursor::at_first(self)
}
#[inline]
#[must_use]
pub fn cursor_to_last(&self) -> Bitmap64Cursor<'_> {
Bitmap64Cursor::at_last(self)
}
}