polars_arrow/bitmap/
aligned.rsuse std::iter::Copied;
use std::slice::Iter;
use crate::bitmap::utils::BitChunk;
fn load_chunk_le<T: BitChunk>(src: &[u8]) -> T {
if let Ok(chunk) = src.try_into() {
return T::from_le_bytes(chunk);
}
let mut chunk = T::Bytes::default();
let len = src.len().min(chunk.as_ref().len());
chunk.as_mut()[..len].copy_from_slice(&src[..len]);
T::from_le_bytes(chunk)
}
#[derive(Default, Clone, Debug)]
pub struct AlignedBitmapSlice<'a, T: BitChunk> {
prefix: T,
prefix_len: u32,
bulk: &'a [T],
suffix: T,
suffix_len: u32,
}
impl<'a, T: BitChunk> AlignedBitmapSlice<'a, T> {
#[inline(always)]
pub fn prefix(&self) -> T {
self.prefix
}
#[inline(always)]
pub fn bulk_iter(&self) -> Copied<Iter<'a, T>> {
self.bulk.iter().copied()
}
#[inline(always)]
pub fn bulk(&self) -> &'a [T] {
self.bulk
}
#[inline(always)]
pub fn suffix(&self) -> T {
self.suffix
}
#[inline(always)]
pub fn prefix_bitlen(&self) -> usize {
self.prefix_len as usize
}
#[inline(always)]
pub fn bulk_bitlen(&self) -> usize {
8 * size_of::<T>() * self.bulk.len()
}
#[inline(always)]
pub fn suffix_bitlen(&self) -> usize {
self.suffix_len as usize
}
pub fn new(mut bytes: &'a [u8], mut offset: usize, len: usize) -> Self {
if len == 0 {
return Self::default();
}
assert!(bytes.len() * 8 >= offset + len);
let start_byte_idx = offset / 8;
bytes = &bytes[start_byte_idx..];
offset %= 8;
let chunk_len = size_of::<T>();
let chunk_len_bits = 8 * chunk_len;
if offset + len <= chunk_len_bits {
let mut prefix = load_chunk_le::<T>(bytes) >> offset;
if len < chunk_len_bits {
prefix &= (T::one() << len) - T::one();
}
return Self {
prefix,
prefix_len: len as u32,
..Self::default()
};
}
let mut align_offset = bytes.as_ptr().align_offset(chunk_len);
let mut align_offset_bits = 8 * align_offset;
if offset > align_offset_bits {
align_offset_bits += chunk_len_bits;
align_offset += chunk_len;
}
let prefix_len = (align_offset_bits - offset).min(len);
let rest_len = len - prefix_len;
let suffix_len = rest_len % chunk_len_bits;
let bulk_len = rest_len - suffix_len;
debug_assert!(prefix_len < chunk_len_bits);
debug_assert!(bulk_len % chunk_len_bits == 0);
debug_assert!(suffix_len < chunk_len_bits);
let (prefix_bytes, rest_bytes) = bytes.split_at(align_offset);
let (bulk_bytes, suffix_bytes) = rest_bytes.split_at(bulk_len / 8);
let mut prefix = load_chunk_le::<T>(prefix_bytes) >> offset;
let mut suffix = load_chunk_le::<T>(suffix_bytes);
prefix &= (T::one() << prefix_len) - T::one();
suffix &= (T::one() << suffix_len) - T::one();
Self {
prefix,
bulk: bytemuck::cast_slice(bulk_bytes),
suffix,
prefix_len: prefix_len as u32,
suffix_len: suffix_len as u32,
}
}
}