use std::ops::Bound;
use std::ops::RangeBounds;
use vortex_error::VortexExpect;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BitBufferMeta {
offset: usize,
len: usize,
}
impl BitBufferMeta {
pub fn new(offset: usize, len: usize) -> Self {
assert!(offset < 8, "BitBufferMeta offset must be < 8, got {offset}");
Self { offset, len }
}
pub fn from_raw_offset(offset: usize, len: usize) -> (usize, Self) {
(
offset / 8,
Self {
offset: offset % 8,
len,
},
)
}
pub fn slice(&self, range: impl RangeBounds<usize>) -> (usize, Self) {
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(&start) => start
.checked_add(1)
.vortex_expect("excluded slice start must not overflow"),
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&end) => end
.checked_add(1)
.vortex_expect("included slice end must not overflow"),
Bound::Excluded(&end) => end,
Bound::Unbounded => self.len,
};
assert!(start <= end);
assert!(start <= self.len);
assert!(end <= self.len);
Self::from_raw_offset(self.offset + start, end - start)
}
#[inline(always)]
pub fn offset(&self) -> usize {
self.offset
}
#[inline(always)]
pub fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn byte_len(&self) -> usize {
(self.offset + self.len).div_ceil(8)
}
}