use std::any::Any;
use polars_error::{PolarsResult, polars_bail};
use polars_utils::IdxSize;
use super::Splitable;
use crate::array::builder::{ShareStrategy, StaticArrayBuilder};
use crate::array::{Array, FromFfi, MutableArray, ToFfi};
use crate::bitmap::{Bitmap, MutableBitmap};
use crate::datatypes::{ArrowDataType, PhysicalType};
use crate::ffi;
#[derive(Clone)]
pub struct NullArray {
dtype: ArrowDataType,
validity: Bitmap,
length: usize,
}
impl NullArray {
pub fn try_new(dtype: ArrowDataType, length: usize) -> PolarsResult<Self> {
if dtype.to_physical_type() != PhysicalType::Null {
polars_bail!(ComputeError: "NullArray can only be initialized with a DataType whose physical type is Null");
}
let validity = Bitmap::new_zeroed(length);
Ok(Self {
dtype,
validity,
length,
})
}
pub fn new(dtype: ArrowDataType, length: usize) -> Self {
Self::try_new(dtype, length).unwrap()
}
pub fn new_empty(dtype: ArrowDataType) -> Self {
Self::new(dtype, 0)
}
pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
Self::new(dtype, 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;
self.validity.slice_unchecked(offset, length);
}
#[inline]
pub fn len(&self) -> usize {
self.length
}
}
impl Array for NullArray {
impl_common_array!();
fn validity(&self) -> Option<&Bitmap> {
Some(&self.validity)
}
fn with_validity(&self, _: Option<Bitmap>) -> Box<dyn Array> {
self.clone().boxed()
}
}
#[derive(Debug)]
pub struct MutableNullArray {
inner: NullArray,
}
impl MutableNullArray {
pub fn new(dtype: ArrowDataType, length: usize) -> Self {
let inner = NullArray::try_new(dtype, length).unwrap();
Self { inner }
}
}
impl From<MutableNullArray> for NullArray {
fn from(value: MutableNullArray) -> Self {
value.inner
}
}
impl MutableArray for MutableNullArray {
fn dtype(&self) -> &ArrowDataType {
&ArrowDataType::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 Splitable for NullArray {
fn check_bound(&self, offset: usize) -> bool {
offset <= self.len()
}
unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
let (lhs, rhs) = self.validity.split_at(offset);
(
Self {
dtype: self.dtype.clone(),
validity: lhs,
length: offset,
},
Self {
dtype: self.dtype.clone(),
validity: rhs,
length: self.len() - offset,
},
)
}
}
impl<A: ffi::ArrowArrayRef> FromFfi<A> for NullArray {
unsafe fn try_from_ffi(array: A) -> PolarsResult<Self> {
let dtype = array.dtype().clone();
Self::try_new(dtype, array.array().len())
}
}
pub struct NullArrayBuilder {
dtype: ArrowDataType,
length: usize,
}
impl NullArrayBuilder {
pub fn new(dtype: ArrowDataType) -> Self {
Self { dtype, length: 0 }
}
}
impl StaticArrayBuilder for NullArrayBuilder {
type Array = NullArray;
fn dtype(&self) -> &ArrowDataType {
&self.dtype
}
fn reserve(&mut self, _additional: usize) {}
fn freeze(self) -> NullArray {
NullArray::new(self.dtype, self.length)
}
fn freeze_reset(&mut self) -> Self::Array {
let out = NullArray::new(self.dtype.clone(), self.length);
self.length = 0;
out
}
fn len(&self) -> usize {
self.length
}
fn extend_nulls(&mut self, length: usize) {
self.length += length;
}
fn subslice_extend(
&mut self,
_other: &NullArray,
_start: usize,
length: usize,
_share: ShareStrategy,
) {
self.length += length;
}
fn subslice_extend_repeated(
&mut self,
_other: &NullArray,
_start: usize,
length: usize,
repeats: usize,
_share: ShareStrategy,
) {
self.length += length * repeats;
}
fn subslice_extend_each_repeated(
&mut self,
_other: &NullArray,
_start: usize,
length: usize,
repeats: usize,
_share: ShareStrategy,
) {
self.length += length * repeats;
}
unsafe fn gather_extend(
&mut self,
_other: &NullArray,
idxs: &[IdxSize],
_share: ShareStrategy,
) {
self.length += idxs.len();
}
fn opt_gather_extend(&mut self, _other: &NullArray, idxs: &[IdxSize], _share: ShareStrategy) {
self.length += idxs.len();
}
}