Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-arrow/src/array/null.rs
6939 views
1
use std::any::Any;
2
3
use polars_error::{PolarsResult, polars_bail};
4
use polars_utils::IdxSize;
5
6
use super::Splitable;
7
use crate::array::builder::{ShareStrategy, StaticArrayBuilder};
8
use crate::array::{Array, FromFfi, MutableArray, ToFfi};
9
use crate::bitmap::{Bitmap, MutableBitmap};
10
use crate::datatypes::{ArrowDataType, PhysicalType};
11
use crate::ffi;
12
13
/// The concrete [`Array`] of [`ArrowDataType::Null`].
14
#[derive(Clone)]
15
pub struct NullArray {
16
dtype: ArrowDataType,
17
18
/// Validity mask. This is always all-zeroes.
19
validity: Bitmap,
20
21
length: usize,
22
}
23
24
impl NullArray {
25
/// Returns a new [`NullArray`].
26
/// # Errors
27
/// This function errors iff:
28
/// * The `dtype`'s [`crate::datatypes::PhysicalType`] is not equal to [`crate::datatypes::PhysicalType::Null`].
29
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
/// Returns a new [`NullArray`].
44
/// # Panics
45
/// This function errors iff:
46
/// * The `dtype`'s [`crate::datatypes::PhysicalType`] is not equal to [`crate::datatypes::PhysicalType::Null`].
47
pub fn new(dtype: ArrowDataType, length: usize) -> Self {
48
Self::try_new(dtype, length).unwrap()
49
}
50
51
/// Returns a new empty [`NullArray`].
52
pub fn new_empty(dtype: ArrowDataType) -> Self {
53
Self::new(dtype, 0)
54
}
55
56
/// Returns a new [`NullArray`].
57
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
65
impl NullArray {
66
/// Returns a slice of the [`NullArray`].
67
/// # Panic
68
/// This function panics iff `offset + length > self.len()`.
69
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
/// Returns a slice of the [`NullArray`].
78
///
79
/// # Safety
80
/// The caller must ensure that `offset + length < self.len()`.
81
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
92
impl 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
// Nulls with invalid nulls are also nulls.
101
self.clone().boxed()
102
}
103
}
104
105
#[derive(Debug)]
106
/// A distinct type to disambiguate
107
/// clashing methods
108
pub struct MutableNullArray {
109
inner: NullArray,
110
}
111
112
impl MutableNullArray {
113
/// Returns a new [`MutableNullArray`].
114
/// # Panics
115
/// This function errors iff:
116
/// * The `dtype`'s [`crate::datatypes::PhysicalType`] is not equal to [`crate::datatypes::PhysicalType::Null`].
117
pub fn new(dtype: ArrowDataType, length: usize) -> Self {
118
let inner = NullArray::try_new(dtype, length).unwrap();
119
Self { inner }
120
}
121
}
122
123
impl From<MutableNullArray> for NullArray {
124
fn from(value: MutableNullArray) -> Self {
125
value.inner
126
}
127
}
128
129
impl 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
// no-op
160
}
161
162
fn shrink_to_fit(&mut self) {
163
// no-op
164
}
165
}
166
167
impl 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
173
unsafe impl ToFfi for NullArray {
174
fn buffers(&self) -> Vec<Option<*const u8>> {
175
// `None` is technically not required by the specification, but older C++ implementations require it, so leaving
176
// it here for backward compatibility
177
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
189
impl 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
212
impl<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
219
pub struct NullArrayBuilder {
220
dtype: ArrowDataType,
221
length: usize,
222
}
223
224
impl NullArrayBuilder {
225
pub fn new(dtype: ArrowDataType) -> Self {
226
Self { dtype, length: 0 }
227
}
228
}
229
230
impl 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
}
302
303