polars_arrow/array/
null.rs1use std::any::Any;
2
3use polars_error::{PolarsResult, polars_bail};
4use polars_utils::IdxSize;
5
6use super::Splitable;
7use crate::array::builder::{ShareStrategy, StaticArrayBuilder};
8use crate::array::{Array, FromFfi, MutableArray, ToFfi};
9use crate::bitmap::{Bitmap, MutableBitmap};
10use crate::datatypes::{ArrowDataType, PhysicalType};
11use crate::ffi;
12
13#[derive(Clone)]
15pub struct NullArray {
16 dtype: ArrowDataType,
17
18 validity: Bitmap,
20
21 length: usize,
22}
23
24impl NullArray {
25 pub fn try_new(dtype: ArrowDataType, length: usize) -> PolarsResult<Self> {
30 if dtype.to_physical_type() != PhysicalType::Null {
31 polars_bail!(ComputeError: "NullArray can only be initialized with a DataType whose physical type is Null");
32 }
33
34 let validity = Bitmap::new_zeroed(length);
35
36 Ok(Self {
37 dtype,
38 validity,
39 length,
40 })
41 }
42
43 pub fn new(dtype: ArrowDataType, length: usize) -> Self {
48 Self::try_new(dtype, length).unwrap()
49 }
50
51 pub fn new_empty(dtype: ArrowDataType) -> Self {
53 Self::new(dtype, 0)
54 }
55
56 pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
58 Self::new(dtype, length)
59 }
60
61 impl_sliced!();
62 impl_into_array!();
63}
64
65impl NullArray {
66 pub fn slice(&mut self, offset: usize, length: usize) {
70 assert!(
71 offset + length <= self.len(),
72 "the offset of the new array cannot exceed the arrays' length"
73 );
74 unsafe { self.slice_unchecked(offset, length) };
75 }
76
77 pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
82 self.length = length;
83 self.validity.slice_unchecked(offset, length);
84 }
85
86 #[inline]
87 pub fn len(&self) -> usize {
88 self.length
89 }
90}
91
92impl Array for NullArray {
93 impl_common_array!();
94
95 fn validity(&self) -> Option<&Bitmap> {
96 Some(&self.validity)
97 }
98
99 fn with_validity(&self, _: Option<Bitmap>) -> Box<dyn Array> {
100 self.clone().boxed()
102 }
103}
104
105#[derive(Debug)]
106pub struct MutableNullArray {
109 inner: NullArray,
110}
111
112impl MutableNullArray {
113 pub fn new(dtype: ArrowDataType, length: usize) -> Self {
118 let inner = NullArray::try_new(dtype, length).unwrap();
119 Self { inner }
120 }
121}
122
123impl From<MutableNullArray> for NullArray {
124 fn from(value: MutableNullArray) -> Self {
125 value.inner
126 }
127}
128
129impl MutableArray for MutableNullArray {
130 fn dtype(&self) -> &ArrowDataType {
131 &ArrowDataType::Null
132 }
133
134 fn len(&self) -> usize {
135 self.inner.length
136 }
137
138 fn validity(&self) -> Option<&MutableBitmap> {
139 None
140 }
141
142 fn as_box(&mut self) -> Box<dyn Array> {
143 self.inner.clone().boxed()
144 }
145
146 fn as_any(&self) -> &dyn Any {
147 self
148 }
149
150 fn as_mut_any(&mut self) -> &mut dyn Any {
151 self
152 }
153
154 fn push_null(&mut self) {
155 self.inner.length += 1;
156 }
157
158 fn reserve(&mut self, _additional: usize) {
159 }
161
162 fn shrink_to_fit(&mut self) {
163 }
165}
166
167impl std::fmt::Debug for NullArray {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(f, "NullArray({})", self.len())
170 }
171}
172
173unsafe impl ToFfi for NullArray {
174 fn buffers(&self) -> Vec<Option<*const u8>> {
175 vec![None]
178 }
179
180 fn offset(&self) -> Option<usize> {
181 Some(0)
182 }
183
184 fn to_ffi_aligned(&self) -> Self {
185 self.clone()
186 }
187}
188
189impl Splitable for NullArray {
190 fn check_bound(&self, offset: usize) -> bool {
191 offset <= self.len()
192 }
193
194 unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
195 let (lhs, rhs) = self.validity.split_at(offset);
196
197 (
198 Self {
199 dtype: self.dtype.clone(),
200 validity: lhs,
201 length: offset,
202 },
203 Self {
204 dtype: self.dtype.clone(),
205 validity: rhs,
206 length: self.len() - offset,
207 },
208 )
209 }
210}
211
212impl<A: ffi::ArrowArrayRef> FromFfi<A> for NullArray {
213 unsafe fn try_from_ffi(array: A) -> PolarsResult<Self> {
214 let dtype = array.dtype().clone();
215 Self::try_new(dtype, array.array().len())
216 }
217}
218
219pub struct NullArrayBuilder {
220 dtype: ArrowDataType,
221 length: usize,
222}
223
224impl NullArrayBuilder {
225 pub fn new(dtype: ArrowDataType) -> Self {
226 Self { dtype, length: 0 }
227 }
228}
229
230impl StaticArrayBuilder for NullArrayBuilder {
231 type Array = NullArray;
232
233 fn dtype(&self) -> &ArrowDataType {
234 &self.dtype
235 }
236
237 fn reserve(&mut self, _additional: usize) {}
238
239 fn freeze(self) -> NullArray {
240 NullArray::new(self.dtype, self.length)
241 }
242
243 fn freeze_reset(&mut self) -> Self::Array {
244 let out = NullArray::new(self.dtype.clone(), self.length);
245 self.length = 0;
246 out
247 }
248
249 fn len(&self) -> usize {
250 self.length
251 }
252
253 fn extend_nulls(&mut self, length: usize) {
254 self.length += length;
255 }
256
257 fn subslice_extend(
258 &mut self,
259 _other: &NullArray,
260 _start: usize,
261 length: usize,
262 _share: ShareStrategy,
263 ) {
264 self.length += length;
265 }
266
267 fn subslice_extend_repeated(
268 &mut self,
269 _other: &NullArray,
270 _start: usize,
271 length: usize,
272 repeats: usize,
273 _share: ShareStrategy,
274 ) {
275 self.length += length * repeats;
276 }
277
278 fn subslice_extend_each_repeated(
279 &mut self,
280 _other: &NullArray,
281 _start: usize,
282 length: usize,
283 repeats: usize,
284 _share: ShareStrategy,
285 ) {
286 self.length += length * repeats;
287 }
288
289 unsafe fn gather_extend(
290 &mut self,
291 _other: &NullArray,
292 idxs: &[IdxSize],
293 _share: ShareStrategy,
294 ) {
295 self.length += idxs.len();
296 }
297
298 fn opt_gather_extend(&mut self, _other: &NullArray, idxs: &[IdxSize], _share: ShareStrategy) {
299 self.length += idxs.len();
300 }
301}