use crate::{bitmap::Bitmap, datatypes::DataType};
use std::any::Any;
use crate::array::MutableArray;
use crate::bitmap::MutableBitmap;
use crate::{
array::{Array, FromFfi, ToFfi},
datatypes::PhysicalType,
error::Error,
ffi,
};
#[derive(Clone)]
pub struct NullArray {
data_type: DataType,
length: usize,
}
impl NullArray {
pub fn try_new(data_type: DataType, length: usize) -> Result<Self, Error> {
if data_type.to_physical_type() != PhysicalType::Null {
return Err(Error::oos(
"NullArray can only be initialized with a DataType whose physical type is Boolean",
));
}
Ok(Self { data_type, length })
}
pub fn new(data_type: DataType, length: usize) -> Self {
Self::try_new(data_type, length).unwrap()
}
pub fn new_empty(data_type: DataType) -> Self {
Self::new(data_type, 0)
}
pub fn new_null(data_type: DataType, length: usize) -> Self {
Self::new(data_type, length)
}
impl_sliced!();
impl_into_array!();
}
impl NullArray {
pub fn slice(&mut self, offset: usize, length: usize) {
assert!(
offset + length <= self.len(),
"the offset of the new array cannot exceed the arrays' length"
);
unsafe { self.slice_unchecked(offset, length) };
}
pub unsafe fn slice_unchecked(&mut self, _offset: usize, length: usize) {
self.length = length;
}
#[inline]
fn len(&self) -> usize {
self.length
}
}
impl Array for NullArray {
impl_common_array!();
fn validity(&self) -> Option<&Bitmap> {
None
}
fn with_validity(&self, _: Option<Bitmap>) -> Box<dyn Array> {
panic!("cannot set validity of a null array")
}
}
#[derive(Debug)]
pub struct MutableNullArray {
inner: NullArray,
}
impl MutableNullArray {
pub fn new(data_type: DataType, length: usize) -> Self {
let inner = NullArray::try_new(data_type, length).unwrap();
Self { inner }
}
}
impl From<MutableNullArray> for NullArray {
fn from(value: MutableNullArray) -> Self {
value.inner
}
}
impl MutableArray for MutableNullArray {
fn data_type(&self) -> &DataType {
&DataType::Null
}
fn len(&self) -> usize {
self.inner.length
}
fn validity(&self) -> Option<&MutableBitmap> {
None
}
fn as_box(&mut self) -> Box<dyn Array> {
self.inner.clone().boxed()
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_mut_any(&mut self) -> &mut dyn Any {
self
}
fn push_null(&mut self) {
self.inner.length += 1;
}
fn reserve(&mut self, _additional: usize) {
}
fn shrink_to_fit(&mut self) {
}
}
impl std::fmt::Debug for NullArray {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "NullArray({})", self.len())
}
}
unsafe impl ToFfi for NullArray {
fn buffers(&self) -> Vec<Option<*const u8>> {
vec![None]
}
fn offset(&self) -> Option<usize> {
Some(0)
}
fn to_ffi_aligned(&self) -> Self {
self.clone()
}
}
impl<A: ffi::ArrowArrayRef> FromFfi<A> for NullArray {
unsafe fn try_from_ffi(array: A) -> Result<Self, Error> {
let data_type = array.data_type().clone();
Self::try_new(data_type, array.array().len())
}
}
#[cfg(feature = "arrow")]
mod arrow {
use super::*;
use arrow_data::{ArrayData, ArrayDataBuilder};
impl NullArray {
pub fn to_data(&self) -> ArrayData {
let builder = ArrayDataBuilder::new(arrow_schema::DataType::Null).len(self.len());
unsafe { builder.build_unchecked() }
}
pub fn from_data(data: &ArrayData) -> Self {
Self::new(DataType::Null, data.len())
}
}
}