polars_arrow/array/
null.rs1use std::any::Any;
2
3use polars_error::{polars_bail, PolarsResult};
4
5use super::Splitable;
6use crate::array::{Array, FromFfi, MutableArray, ToFfi};
7use crate::bitmap::{Bitmap, MutableBitmap};
8use crate::datatypes::{ArrowDataType, PhysicalType};
9use crate::ffi;
10
11#[derive(Clone)]
13pub struct NullArray {
14 dtype: ArrowDataType,
15
16 validity: Bitmap,
18
19 length: usize,
20}
21
22impl NullArray {
23 pub fn try_new(dtype: ArrowDataType, length: usize) -> PolarsResult<Self> {
28 if dtype.to_physical_type() != PhysicalType::Null {
29 polars_bail!(ComputeError: "NullArray can only be initialized with a DataType whose physical type is Null");
30 }
31
32 let validity = Bitmap::new_zeroed(length);
33
34 Ok(Self {
35 dtype,
36 validity,
37 length,
38 })
39 }
40
41 pub fn new(dtype: ArrowDataType, length: usize) -> Self {
46 Self::try_new(dtype, length).unwrap()
47 }
48
49 pub fn new_empty(dtype: ArrowDataType) -> Self {
51 Self::new(dtype, 0)
52 }
53
54 pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
56 Self::new(dtype, length)
57 }
58
59 impl_sliced!();
60 impl_into_array!();
61}
62
63impl NullArray {
64 pub fn slice(&mut self, offset: usize, length: usize) {
68 assert!(
69 offset + length <= self.len(),
70 "the offset of the new array cannot exceed the arrays' length"
71 );
72 unsafe { self.slice_unchecked(offset, length) };
73 }
74
75 pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
80 self.length = length;
81 self.validity.slice_unchecked(offset, length);
82 }
83
84 #[inline]
85 fn len(&self) -> usize {
86 self.length
87 }
88}
89
90impl Array for NullArray {
91 impl_common_array!();
92
93 fn validity(&self) -> Option<&Bitmap> {
94 Some(&self.validity)
95 }
96
97 fn with_validity(&self, _: Option<Bitmap>) -> Box<dyn Array> {
98 self.clone().boxed()
100 }
101}
102
103#[derive(Debug)]
104pub struct MutableNullArray {
107 inner: NullArray,
108}
109
110impl MutableNullArray {
111 pub fn new(dtype: ArrowDataType, length: usize) -> Self {
116 let inner = NullArray::try_new(dtype, length).unwrap();
117 Self { inner }
118 }
119}
120
121impl From<MutableNullArray> for NullArray {
122 fn from(value: MutableNullArray) -> Self {
123 value.inner
124 }
125}
126
127impl MutableArray for MutableNullArray {
128 fn dtype(&self) -> &ArrowDataType {
129 &ArrowDataType::Null
130 }
131
132 fn len(&self) -> usize {
133 self.inner.length
134 }
135
136 fn validity(&self) -> Option<&MutableBitmap> {
137 None
138 }
139
140 fn as_box(&mut self) -> Box<dyn Array> {
141 self.inner.clone().boxed()
142 }
143
144 fn as_any(&self) -> &dyn Any {
145 self
146 }
147
148 fn as_mut_any(&mut self) -> &mut dyn Any {
149 self
150 }
151
152 fn push_null(&mut self) {
153 self.inner.length += 1;
154 }
155
156 fn reserve(&mut self, _additional: usize) {
157 }
159
160 fn shrink_to_fit(&mut self) {
161 }
163}
164
165impl std::fmt::Debug for NullArray {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 write!(f, "NullArray({})", self.len())
168 }
169}
170
171unsafe impl ToFfi for NullArray {
172 fn buffers(&self) -> Vec<Option<*const u8>> {
173 vec![None]
176 }
177
178 fn offset(&self) -> Option<usize> {
179 Some(0)
180 }
181
182 fn to_ffi_aligned(&self) -> Self {
183 self.clone()
184 }
185}
186
187impl Splitable for NullArray {
188 fn check_bound(&self, offset: usize) -> bool {
189 offset <= self.len()
190 }
191
192 unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
193 let (lhs, rhs) = self.validity.split_at(offset);
194
195 (
196 Self {
197 dtype: self.dtype.clone(),
198 validity: lhs,
199 length: offset,
200 },
201 Self {
202 dtype: self.dtype.clone(),
203 validity: rhs,
204 length: self.len() - offset,
205 },
206 )
207 }
208}
209
210impl<A: ffi::ArrowArrayRef> FromFfi<A> for NullArray {
211 unsafe fn try_from_ffi(array: A) -> PolarsResult<Self> {
212 let dtype = array.dtype().clone();
213 Self::try_new(dtype, array.array().len())
214 }
215}