use std::iter::FromIterator;
use std::sync::Arc;
use crate::{buffer::bytes::Bytes, buffer::MutableBuffer, trusted_len::TrustedLen};
use super::{
utils::{count_zeros, fmt, get_bit, get_bit_unchecked, BitChunk, BitChunks, BitmapIter},
MutableBitmap,
};
#[derive(Clone)]
pub struct Bitmap {
bytes: Arc<Bytes<u8>>,
offset: usize,
length: usize,
null_count: usize,
}
impl std::fmt::Debug for Bitmap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (bytes, offset, len) = self.as_slice();
fmt(bytes, offset, len, f)
}
}
impl Default for Bitmap {
fn default() -> Self {
MutableBitmap::new().into()
}
}
impl Bitmap {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn new_zeroed(length: usize) -> Self {
MutableBitmap::from_len_zeroed(length).into()
}
#[inline]
pub fn len(&self) -> usize {
self.length
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub(crate) fn from_bytes(bytes: Bytes<u8>, length: usize) -> Self {
assert!(length <= bytes.len() * 8);
let null_count = count_zeros(&bytes, 0, length);
Self {
length,
offset: 0,
bytes: Arc::new(bytes),
null_count,
}
}
#[inline]
pub fn from_u8_buffer(buffer: MutableBuffer<u8>, length: usize) -> Self {
Bitmap::from_bytes(buffer.into(), length)
}
#[inline]
pub fn from_u8_slice<T: AsRef<[u8]>>(buffer: T, length: usize) -> Self {
let buffer = MutableBuffer::<u8>::from(buffer.as_ref());
Bitmap::from_u8_buffer(buffer, length)
}
#[inline]
pub fn null_count_range(&self, offset: usize, length: usize) -> usize {
count_zeros(&self.bytes, self.offset + offset, length)
}
#[inline]
pub fn null_count(&self) -> usize {
self.null_count
}
#[inline]
pub fn slice(self, offset: usize, length: usize) -> Self {
assert!(offset + length <= self.length);
unsafe { self.slice_unchecked(offset, length) }
}
#[inline]
pub unsafe fn slice_unchecked(mut self, offset: usize, length: usize) -> Self {
if length < self.length / 2 {
self.null_count = count_zeros(&self.bytes, offset, length);
} else {
let start_end = self.offset + offset + length;
let head_count = count_zeros(&self.bytes, self.offset, offset);
let tail_count = count_zeros(&self.bytes, start_end, self.length - length - offset);
self.null_count -= head_count + tail_count;
}
self.offset += offset;
self.length = length;
self
}
#[inline]
pub fn get_bit(&self, i: usize) -> bool {
get_bit(&self.bytes, self.offset + i)
}
#[inline]
pub fn get(&self, i: usize) -> Option<bool> {
if i < self.len() {
Some(unsafe { self.get_bit_unchecked(i) })
} else {
None
}
}
#[inline]
pub unsafe fn get_bit_unchecked(&self, i: usize) -> bool {
get_bit_unchecked(&self.bytes, self.offset + i)
}
pub(crate) fn as_ptr(&self) -> std::ptr::NonNull<u8> {
self.bytes.ptr()
}
}
impl<P: AsRef<[bool]>> From<P> for Bitmap {
fn from(slice: P) -> Self {
Self::from_trusted_len_iter(slice.as_ref().iter().copied())
}
}
impl FromIterator<bool> for Bitmap {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = bool>,
{
MutableBitmap::from_iter(iter).into()
}
}
impl Bitmap {
pub fn chunks<T: BitChunk>(&self) -> BitChunks<T> {
BitChunks::new(&self.bytes, self.offset, self.length)
}
}
impl Bitmap {
#[inline]
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = bool>>(iterator: I) -> Self {
MutableBitmap::from_trusted_len_iter_unchecked(iterator).into()
}
#[inline]
pub fn from_trusted_len_iter<I: TrustedLen<Item = bool>>(iterator: I) -> Self {
MutableBitmap::from_trusted_len_iter(iterator).into()
}
#[inline]
pub fn try_from_trusted_len_iter<E, I: TrustedLen<Item = std::result::Result<bool, E>>>(
iterator: I,
) -> std::result::Result<Self, E> {
Ok(MutableBitmap::try_from_trusted_len_iter(iterator)?.into())
}
#[inline]
pub unsafe fn try_from_trusted_len_iter_unchecked<
E,
I: Iterator<Item = std::result::Result<bool, E>>,
>(
iterator: I,
) -> std::result::Result<Self, E> {
Ok(MutableBitmap::try_from_trusted_len_iter_unchecked(iterator)?.into())
}
}
impl Bitmap {
#[inline]
pub fn as_slice(&self) -> (&[u8], usize, usize) {
let start = self.offset / 8;
let len = (self.offset % 8 + self.length).saturating_add(7) / 8;
(
&self.bytes[start..start + len],
self.offset % 8,
self.length,
)
}
}
impl<'a> IntoIterator for &'a Bitmap {
type Item = bool;
type IntoIter = BitmapIter<'a>;
fn into_iter(self) -> Self::IntoIter {
BitmapIter::<'a>::new(&self.bytes, self.offset, self.length)
}
}
impl<'a> Bitmap {
pub fn iter(&'a self) -> BitmapIter<'a> {
BitmapIter::<'a>::new(&self.bytes, self.offset, self.length)
}
}