Skip to main content

arrow_array/builder/
null_builder.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::builder::ArrayBuilder;
6use crate::{ArrayRef, NullArray};
7use arrow_data::ArrayData;
8use arrow_schema::DataType;
9use std::any::Any;
10use std::sync::Arc;
11
12/// Builder for [`NullArray`]
13///
14/// # Example
15///
16/// Create a `NullArray` from a `NullBuilder`
17///
18/// ```
19///
20/// # use arrow_array::{Array, NullArray, builder::NullBuilder};
21///
22/// let mut b = NullBuilder::new();
23/// b.append_empty_value();
24/// b.append_null();
25/// b.append_nulls(3);
26/// b.append_empty_values(3);
27/// let arr = b.finish();
28///
29/// assert_eq!(8, arr.len());
30/// assert_eq!(0, arr.null_count());
31/// ```
32#[derive(Debug)]
33pub struct NullBuilder {
34    len: usize,
35}
36
37impl Default for NullBuilder {
38    fn default() -> Self {
39        Self::new()
40    }
41}
42
43impl NullBuilder {
44    /// Creates a new null builder
45    pub fn new() -> Self {
46        Self { len: 0 }
47    }
48
49    /// Appends a null slot into the builder
50    #[inline]
51    pub fn append_null(&mut self) {
52        self.len += 1;
53    }
54
55    /// Appends `n` `null`s into the builder.
56    #[inline]
57    pub fn append_nulls(&mut self, n: usize) {
58        self.len += n;
59    }
60
61    /// Appends a null slot into the builder
62    #[inline]
63    pub fn append_empty_value(&mut self) {
64        self.append_null();
65    }
66
67    /// Appends `n` `null`s into the builder.
68    #[inline]
69    pub fn append_empty_values(&mut self, n: usize) {
70        self.append_nulls(n);
71    }
72
73    /// Builds the [NullArray] and reset this builder.
74    pub fn finish(&mut self) -> NullArray {
75        let len = std::mem::take(&mut self.len);
76        let builder = ArrayData::new_null(&DataType::Null, len).into_builder();
77
78        // SAFETY: ArrayData::new_null produces valid null array data, so all builder invariants hold
79        let array_data = unsafe { builder.build_unchecked() };
80        NullArray::from(array_data)
81    }
82
83    /// Builds the [NullArray] without resetting the builder.
84    pub fn finish_cloned(&self) -> NullArray {
85        let len = self.len();
86        let builder = ArrayData::new_null(&DataType::Null, len).into_builder();
87
88        // SAFETY: ArrayData::new_null produces valid null array data, so all builder invariants hold
89        let array_data = unsafe { builder.build_unchecked() };
90        NullArray::from(array_data)
91    }
92}
93
94impl ArrayBuilder for NullBuilder {
95    /// Returns the builder as a non-mutable `Any` reference.
96    fn as_any(&self) -> &dyn Any {
97        self
98    }
99
100    /// Returns the builder as a mutable `Any` reference.
101    fn as_any_mut(&mut self) -> &mut dyn Any {
102        self
103    }
104
105    /// Returns the boxed builder as a box of `Any`.
106    fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
107        self
108    }
109
110    /// Returns the number of array slots in the builder
111    fn len(&self) -> usize {
112        self.len
113    }
114
115    /// Builds the array and reset this builder.
116    fn finish(&mut self) -> ArrayRef {
117        Arc::new(self.finish())
118    }
119
120    /// Builds the array without resetting the builder.
121    fn finish_cloned(&self) -> ArrayRef {
122        Arc::new(self.finish_cloned())
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129    use crate::Array;
130
131    #[test]
132    fn test_null_array_builder() {
133        let mut builder = NullArray::builder(10);
134        builder.append_null();
135        builder.append_nulls(4);
136        builder.append_empty_value();
137        builder.append_empty_values(4);
138
139        let arr = builder.finish();
140        assert_eq!(10, arr.len());
141        assert_eq!(0, arr.offset());
142        assert_eq!(0, arr.null_count());
143        assert!(arr.is_nullable());
144    }
145
146    #[test]
147    fn test_null_array_builder_finish_cloned() {
148        let mut builder = NullArray::builder(16);
149        builder.append_null();
150        builder.append_empty_value();
151        builder.append_empty_values(3);
152        let mut array = builder.finish_cloned();
153        assert_eq!(5, array.len());
154
155        builder.append_empty_values(5);
156        array = builder.finish();
157        assert_eq!(10, array.len());
158    }
159
160    #[test]
161    fn test_null_array_builder_finish_resets() {
162        let mut builder = NullBuilder::new();
163        builder.append_nulls(10);
164
165        let array = builder.finish();
166        assert_eq!(10, array.len());
167        assert_eq!(0, builder.len());
168        assert!(builder.is_empty());
169
170        builder.append_nulls(3);
171        let array = builder.finish();
172        assert_eq!(3, array.len());
173        assert_eq!(0, builder.len());
174    }
175}