use vortex_buffer::BitBuffer;
use vortex_buffer::BitBufferMut;
use vortex_error::VortexExpect;
use vortex_error::vortex_panic;
use vortex_mask::Mask;
use crate::dtype::Nullability;
use crate::dtype::Nullability::NonNullable;
use crate::dtype::Nullability::Nullable;
use crate::validity::Validity;
pub struct LazyBitBufferBuilder {
inner: Option<BitBufferMut>,
len: usize,
capacity: usize,
}
impl LazyBitBufferBuilder {
pub fn new(capacity: usize) -> Self {
Self {
inner: None,
len: 0,
capacity,
}
}
#[inline]
pub fn append_n_non_nulls(&mut self, n: usize) {
if let Some(buf) = self.inner.as_mut() {
buf.append_n(true, n)
} else {
self.len += n;
}
}
#[inline]
pub fn append_non_null(&mut self) {
if let Some(buf) = self.inner.as_mut() {
buf.append(true)
} else {
self.len += 1;
}
}
#[inline]
pub fn append_n_nulls(&mut self, n: usize) {
self.materialize_if_needed();
self.inner
.as_mut()
.vortex_expect("cannot append null to non-nullable builder")
.append_n(false, n);
}
#[inline]
pub fn append_null(&mut self) {
self.materialize_if_needed();
self.inner
.as_mut()
.vortex_expect("cannot append null to non-nullable builder")
.append(false);
}
#[inline]
pub fn append_buffer(&mut self, bool_buffer: &BitBuffer) {
self.materialize_if_needed();
self.inner
.as_mut()
.vortex_expect("buffer just materialized")
.append_buffer(bool_buffer);
}
pub fn append_validity_mask(&mut self, validity_mask: Mask) {
match validity_mask {
Mask::AllTrue(len) => self.append_n_non_nulls(len),
Mask::AllFalse(len) => self.append_n_nulls(len),
Mask::Values(is_valid) => self.append_buffer(is_valid.bit_buffer()),
}
}
pub fn set_bit(&mut self, index: usize, v: bool) {
self.materialize_if_needed();
self.inner
.as_mut()
.vortex_expect("buffer just materialized")
.set_to(index, v);
}
pub fn len(&self) -> usize {
self.inner.as_ref().map(|i| i.len()).unwrap_or(self.len)
}
fn finish(&mut self) -> Option<BitBuffer> {
self.len = 0;
self.inner.take().map(|b| b.freeze())
}
pub fn finish_with_nullability(&mut self, nullability: Nullability) -> Validity {
let nulls = self.finish();
match (nullability, nulls) {
(NonNullable, None) => Validity::NonNullable,
(Nullable, None) => Validity::AllValid,
(Nullable, Some(arr)) => Validity::from(arr),
_ => vortex_panic!("Invalid nullability/nulls combination"),
}
}
pub fn reserve_exact(&mut self, additional: usize) {
if self.inner.is_none() {
self.capacity += additional;
} else {
self.inner
.as_mut()
.vortex_expect("buffer just materialized")
.reserve(additional);
}
}
fn materialize_if_needed(&mut self) {
if self.inner.is_none() {
self.materialize()
}
}
#[cold]
#[inline(never)]
fn materialize(&mut self) {
if self.inner.is_none() {
let mut bit_mut = BitBufferMut::with_capacity(self.len.max(self.capacity));
bit_mut.append_n(true, self.len);
self.inner = Some(bit_mut);
}
}
}