mod chunk_iterator;
mod chunks_exact_mut;
mod fmt;
mod iterator;
mod slice_iterator;
mod zip_validity;
use std::convert::TryInto;
pub(crate) use chunk_iterator::merge_reversed;
pub use chunk_iterator::{BitChunk, BitChunkIterExact, BitChunks, BitChunksExact};
pub use chunks_exact_mut::BitChunksExactMut;
pub use fmt::fmt;
pub use iterator::BitmapIter;
pub use slice_iterator::SlicesIterator;
pub use zip_validity::{ZipValidity, ZipValidityIter};
const BIT_MASK: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
const UNSET_BIT_MASK: [u8; 8] = [
255 - 1,
255 - 2,
255 - 4,
255 - 8,
255 - 16,
255 - 32,
255 - 64,
255 - 128,
];
#[inline]
pub fn is_set(byte: u8, i: usize) -> bool {
(byte & BIT_MASK[i]) != 0
}
#[inline]
pub fn set(byte: u8, i: usize, value: bool) -> u8 {
if value {
byte | BIT_MASK[i]
} else {
byte & UNSET_BIT_MASK[i]
}
}
#[inline]
pub fn set_bit(data: &mut [u8], i: usize, value: bool) {
data[i / 8] = set(data[i / 8], i % 8, value);
}
#[inline]
pub unsafe fn set_bit_unchecked(data: &mut [u8], i: usize, value: bool) {
let byte = data.get_unchecked_mut(i / 8);
*byte = set(*byte, i % 8, value);
}
#[inline]
pub fn get_bit(bytes: &[u8], i: usize) -> bool {
is_set(bytes[i / 8], i % 8)
}
#[inline]
pub unsafe fn get_bit_unchecked(data: &[u8], i: usize) -> bool {
(*data.as_ptr().add(i >> 3) & BIT_MASK[i & 7]) != 0
}
#[inline]
pub fn bytes_for(bits: usize) -> usize {
bits.saturating_add(7) / 8
}
pub fn count_zeros(slice: &[u8], offset: usize, len: usize) -> usize {
if len == 0 {
return 0;
};
let mut slice = &slice[offset / 8..(offset + len).saturating_add(7) / 8];
let offset = offset % 8;
if (offset + len) / 8 == 0 {
let byte = (slice[0] >> offset) << (8 - len);
return len - byte.count_ones() as usize;
}
let mut set_count = 0;
if offset != 0 {
set_count += (slice[0] >> offset).count_ones() as usize;
slice = &slice[1..];
}
if (offset + len) % 8 != 0 {
let end_offset = (offset + len) % 8; let last_index = slice.len() - 1;
set_count += (slice[last_index] << (8 - end_offset)).count_ones() as usize;
slice = &slice[..last_index];
}
let mut chunks = slice.chunks_exact(8);
set_count += chunks
.by_ref()
.map(|chunk| {
let a = u64::from_ne_bytes(chunk.try_into().unwrap());
a.count_ones() as usize
})
.sum::<usize>();
set_count += chunks
.remainder()
.iter()
.map(|byte| byte.count_ones() as usize)
.sum::<usize>();
len - set_count
}