Skip to main content

arrow_array/builder/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines push-based APIs for constructing arrays
19//!
20//! # Basic Usage
21//!
22//! Builders can be used to build simple, non-nested arrays
23//!
24//! ```
25//! # use arrow_array::builder::Int32Builder;
26//! # use arrow_array::PrimitiveArray;
27//! let mut a = Int32Builder::new();
28//! a.append_value(1);
29//! a.append_null();
30//! a.append_value(2);
31//! let a = a.finish();
32//!
33//! assert_eq!(a, PrimitiveArray::from(vec![Some(1), None, Some(2)]));
34//! ```
35//!
36//! ```
37//! # use arrow_array::builder::StringBuilder;
38//! # use arrow_array::{Array, StringArray};
39//! let mut a = StringBuilder::new();
40//! a.append_value("foo");
41//! a.append_value("bar");
42//! a.append_null();
43//! let a = a.finish();
44//!
45//! assert_eq!(a, StringArray::from_iter([Some("foo"), Some("bar"), None]));
46//! ```
47//!
48//! # Nested Usage
49//!
50//! Builders can also be used to build more complex nested arrays, such as lists
51//!
52//! ```
53//! # use arrow_array::builder::{Int32Builder, ListBuilder};
54//! # use arrow_array::ListArray;
55//! # use arrow_array::types::Int32Type;
56//! let mut a = ListBuilder::new(Int32Builder::new());
57//! // [1, 2]
58//! a.values().append_value(1);
59//! a.values().append_value(2);
60//! a.append(true);
61//! // null
62//! a.append(false);
63//! // []
64//! a.append(true);
65//! // [3, null]
66//! a.values().append_value(3);
67//! a.values().append_null();
68//! a.append(true);
69//!
70//! // [[1, 2], null, [], [3, null]]
71//! let a = a.finish();
72//!
73//! assert_eq!(a, ListArray::from_iter_primitive::<Int32Type, _, _>([
74//!     Some(vec![Some(1), Some(2)]),
75//!     None,
76//!     Some(vec![]),
77//!     Some(vec![Some(3), None])]
78//! ))
79//! ```
80//!
81//! # Using the [`Extend`] trait to append values from an iterable:
82//!
83//! ```
84//! # use arrow_array::{Array};
85//! # use arrow_array::builder::{ArrayBuilder, StringBuilder};
86//!
87//! let mut builder = StringBuilder::new();
88//! builder.extend(vec![Some("🍐"), Some("🍎"), None]);
89//! assert_eq!(builder.finish().len(), 3);
90//! ```
91//!
92//! # Using the [`Extend`] trait to write generic functions:
93//!
94//! ```
95//! # use arrow_array::{Array, ArrayRef, StringArray};
96//! # use arrow_array::builder::{ArrayBuilder, Int32Builder, ListBuilder, StringBuilder};
97//!
98//! // For generic methods that fill a list of values for an [`ArrayBuilder`], use the [`Extend`] trait.
99//! fn filter_and_fill<V, I: IntoIterator<Item = V>>(builder: &mut impl Extend<V>, values: I, filter: V)
100//! where V: PartialEq
101//! {
102//!     builder.extend(values.into_iter().filter(|v| *v == filter));
103//! }
104//! let mut string_builder = StringBuilder::new();
105//! filter_and_fill(
106//!     &mut string_builder,
107//!     vec![Some("🍐"), Some("🍎"), None],
108//!     Some("🍎"),
109//! );
110//! assert_eq!(string_builder.finish().len(), 1);
111//!
112//! let mut int_builder = Int32Builder::new();
113//! filter_and_fill(
114//!     &mut int_builder,
115//!     vec![Some(11), Some(42), None],
116//!     Some(42),
117//! );
118//! assert_eq!(int_builder.finish().len(), 1);
119//!
120//! // For generic methods that fill lists-of-lists for an [`ArrayBuilder`], use the [`Extend`] trait.
121//! fn filter_and_fill_if_contains<T, V, I: IntoIterator<Item = Option<V>>>(
122//!     list_builder: &mut impl Extend<Option<V>>,
123//!     values: I,
124//!     filter: Option<T>,
125//! ) where
126//!     T: PartialEq,
127//!     for<'a> &'a V: IntoIterator<Item = &'a Option<T>>,
128//! {
129//!     list_builder.extend(values.into_iter().filter(|string: &Option<V>| {
130//!         string
131//!             .as_ref()
132//!             .map(|str: &V| str.into_iter().any(|ch: &Option<T>| ch == &filter))
133//!             .unwrap_or(false)
134//!     }));
135//!  }
136//! let builder = StringBuilder::new();
137//! let mut list_builder = ListBuilder::new(builder);
138//! let pear_pear = vec![Some("🍐"),Some("🍐")];
139//! let pear_app = vec![Some("🍐"),Some("🍎")];
140//! filter_and_fill_if_contains(
141//!     &mut list_builder,
142//!     vec![Some(pear_pear), Some(pear_app), None],
143//!     Some("🍎"),
144//! );
145//! assert_eq!(list_builder.finish().len(), 1);
146//! ```
147//!
148//! # Custom Builders
149//!
150//! It is common to have a collection of statically defined Rust types that
151//! you want to convert to Arrow arrays.
152//!
153//! An example of doing so is below
154//!
155//! ```
156//! # use std::any::Any;
157//! # use arrow_array::builder::{ArrayBuilder, Int32Builder, ListBuilder, StringBuilder};
158//! # use arrow_array::{ArrayRef, RecordBatch, StructArray};
159//! # use arrow_schema::{DataType, Field};
160//! # use std::sync::Arc;
161//! /// A custom row representation
162//! struct MyRow {
163//!     i32: i32,
164//!     optional_i32: Option<i32>,
165//!     string: Option<String>,
166//!     i32_list: Option<Vec<Option<i32>>>,
167//! }
168//!
169//! /// Converts `Vec<Row>` into `StructArray`
170//! #[derive(Debug, Default)]
171//! struct MyRowBuilder {
172//!     i32: Int32Builder,
173//!     string: StringBuilder,
174//!     i32_list: ListBuilder<Int32Builder>,
175//! }
176//!
177//! impl MyRowBuilder {
178//!     fn append(&mut self, row: &MyRow) {
179//!         self.i32.append_value(row.i32);
180//!         self.string.append_option(row.string.as_ref());
181//!         self.i32_list.append_option(row.i32_list.as_ref().map(|x| x.iter().copied()));
182//!     }
183//!
184//!     /// Note: returns StructArray to allow nesting within another array if desired
185//!     fn finish(&mut self) -> StructArray {
186//!         let i32 = Arc::new(self.i32.finish()) as ArrayRef;
187//!         let i32_field = Arc::new(Field::new("i32", DataType::Int32, false));
188//!
189//!         let string = Arc::new(self.string.finish()) as ArrayRef;
190//!         let string_field = Arc::new(Field::new("i32", DataType::Utf8, false));
191//!
192//!         let i32_list = Arc::new(self.i32_list.finish()) as ArrayRef;
193//!         let value_field = Arc::new(Field::new_list_field(DataType::Int32, true));
194//!         let i32_list_field = Arc::new(Field::new("i32_list", DataType::List(value_field), true));
195//!
196//!         StructArray::from(vec![
197//!             (i32_field, i32),
198//!             (string_field, string),
199//!             (i32_list_field, i32_list),
200//!         ])
201//!     }
202//! }
203//!
204//! /// For building arrays in generic code, use Extend instead of the append_* methods
205//! /// e.g. append_value, append_option, append_null
206//! impl<'a> Extend<&'a MyRow> for MyRowBuilder {
207//!     fn extend<T: IntoIterator<Item = &'a MyRow>>(&mut self, iter: T) {
208//!         iter.into_iter().for_each(|row| self.append(row));
209//!     }
210//! }
211//!
212//! /// Converts a slice of [`MyRow`] to a [`RecordBatch`]
213//! fn rows_to_batch(rows: &[MyRow]) -> RecordBatch {
214//!     let mut builder = MyRowBuilder::default();
215//!     builder.extend(rows);
216//!     RecordBatch::from(&builder.finish())
217//! }
218//! ```
219//!
220//! # Null / Validity Masks
221//!
222//! The [`NullBufferBuilder`] is optimized for creating the null mask for an array.
223//!
224//! ```
225//! # use arrow_array::builder::NullBufferBuilder;
226//! let mut builder = NullBufferBuilder::new(8);
227//! let mut builder = NullBufferBuilder::new(8);
228//! builder.append_n_non_nulls(7);
229//! builder.append_null();
230//! let buffer = builder.finish().unwrap();
231//! assert_eq!(buffer.len(), 8);
232//! assert_eq!(buffer.iter().collect::<Vec<_>>(), vec![true, true, true, true, true, true, true, false]);
233//! ```
234
235pub use arrow_buffer::BooleanBufferBuilder;
236pub use arrow_buffer::NullBufferBuilder;
237
238mod boolean_builder;
239pub use boolean_builder::*;
240mod buffer_builder;
241pub use buffer_builder::*;
242mod fixed_size_binary_builder;
243pub use fixed_size_binary_builder::*;
244mod fixed_size_list_builder;
245pub use fixed_size_list_builder::*;
246mod fixed_size_binary_dictionary_builder;
247pub use fixed_size_binary_dictionary_builder::*;
248mod generic_bytes_builder;
249pub use generic_bytes_builder::*;
250mod generic_list_builder;
251pub use generic_list_builder::*;
252mod map_builder;
253pub use map_builder::*;
254mod null_builder;
255pub use null_builder::*;
256mod primitive_builder;
257pub use primitive_builder::*;
258mod primitive_dictionary_builder;
259pub use primitive_dictionary_builder::*;
260mod primitive_run_builder;
261pub use primitive_run_builder::*;
262mod struct_builder;
263pub use struct_builder::*;
264mod struct_array_assembler;
265pub use struct_array_assembler::*;
266mod generic_bytes_dictionary_builder;
267pub use generic_bytes_dictionary_builder::*;
268mod generic_byte_run_builder;
269pub use generic_byte_run_builder::*;
270mod generic_bytes_view_builder;
271pub use generic_bytes_view_builder::*;
272mod generic_list_view_builder;
273pub use generic_list_view_builder::*;
274mod union_builder;
275
276pub use union_builder::*;
277
278use crate::ArrayRef;
279use crate::types::{Int8Type, Int16Type, Int32Type, Int64Type};
280use arrow_schema::{DataType, IntervalUnit, TimeUnit};
281use std::any::Any;
282
283/// Trait for dealing with different array builders at runtime
284///
285/// # Example
286///
287/// ```
288/// // Create
289/// # use arrow_array::{ArrayRef, StringArray};
290/// # use arrow_array::builder::{ArrayBuilder, Float64Builder, Int64Builder, StringBuilder};
291///
292/// let mut data_builders: Vec<Box<dyn ArrayBuilder>> = vec![
293///     Box::new(Float64Builder::new()),
294///     Box::new(Int64Builder::new()),
295///     Box::new(StringBuilder::new()),
296/// ];
297///
298/// // Fill
299/// data_builders[0]
300///     .as_any_mut()
301///     .downcast_mut::<Float64Builder>()
302///     .unwrap()
303///     .append_value(3.14);
304/// data_builders[1]
305///     .as_any_mut()
306///     .downcast_mut::<Int64Builder>()
307///     .unwrap()
308///     .append_value(-1);
309/// data_builders[2]
310///     .as_any_mut()
311///     .downcast_mut::<StringBuilder>()
312///     .unwrap()
313///     .append_value("🍎");
314///
315/// // Finish
316/// let array_refs: Vec<ArrayRef> = data_builders
317///     .iter_mut()
318///     .map(|builder| builder.finish())
319///     .collect();
320/// assert_eq!(array_refs[0].len(), 1);
321/// assert_eq!(array_refs[1].is_null(0), false);
322/// assert_eq!(
323///     array_refs[2]
324///         .as_any()
325///         .downcast_ref::<StringArray>()
326///         .unwrap()
327///         .value(0),
328///     "🍎"
329/// );
330/// ```
331pub trait ArrayBuilder: Any + Send + Sync {
332    /// Returns the number of array slots in the builder
333    fn len(&self) -> usize;
334
335    /// Returns whether number of array slots is zero
336    fn is_empty(&self) -> bool {
337        self.len() == 0
338    }
339
340    /// Builds the array
341    fn finish(&mut self) -> ArrayRef;
342
343    /// Builds the array without resetting the underlying builder.
344    fn finish_cloned(&self) -> ArrayRef;
345
346    /// Builds the array without resetting the values builder.
347    ///
348    /// This is relevant for dictionary builders but also for composite builders.
349    /// Those are not affected directly, but will call the corresponding method
350    /// on their constituent builders.
351    ///
352    /// The default implementation just calls [`finish`][Self::finish] which is sufficient
353    /// for all but the above mentioned builders.
354    fn finish_preserve_values(&mut self) -> ArrayRef {
355        self.finish()
356    }
357
358    /// Returns the builder as a non-mutable `Any` reference.
359    ///
360    /// This is most useful when one wants to call non-mutable APIs on a specific builder
361    /// type. In this case, one can first cast this into a `Any`, and then use
362    /// `downcast_ref` to get a reference on the specific builder.
363    fn as_any(&self) -> &dyn Any;
364
365    /// Returns the builder as a mutable `Any` reference.
366    ///
367    /// This is most useful when one wants to call mutable APIs on a specific builder
368    /// type. In this case, one can first cast this into a `Any`, and then use
369    /// `downcast_mut` to get a reference on the specific builder.
370    fn as_any_mut(&mut self) -> &mut dyn Any;
371
372    /// Returns the boxed builder as a box of `Any`.
373    fn into_box_any(self: Box<Self>) -> Box<dyn Any>;
374}
375
376impl ArrayBuilder for Box<dyn ArrayBuilder> {
377    fn len(&self) -> usize {
378        (**self).len()
379    }
380
381    fn is_empty(&self) -> bool {
382        (**self).is_empty()
383    }
384
385    fn finish(&mut self) -> ArrayRef {
386        (**self).finish()
387    }
388
389    fn finish_cloned(&self) -> ArrayRef {
390        (**self).finish_cloned()
391    }
392
393    fn finish_preserve_values(&mut self) -> ArrayRef {
394        (**self).finish_preserve_values()
395    }
396
397    fn as_any(&self) -> &dyn Any {
398        (**self).as_any()
399    }
400
401    fn as_any_mut(&mut self) -> &mut dyn Any {
402        (**self).as_any_mut()
403    }
404
405    fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
406        self
407    }
408}
409
410/// Builder for [`ListArray`](crate::array::ListArray)
411pub type ListBuilder<T> = GenericListBuilder<i32, T>;
412
413/// Builder for [`LargeListArray`](crate::array::LargeListArray)
414pub type LargeListBuilder<T> = GenericListBuilder<i64, T>;
415
416/// Builder for [`ListViewArray`](crate::array::ListViewArray)
417pub type ListViewBuilder<T> = GenericListViewBuilder<i32, T>;
418
419/// Builder for [`LargeListViewArray`](crate::array::LargeListViewArray)
420pub type LargeListViewBuilder<T> = GenericListViewBuilder<i64, T>;
421
422/// Builder for [`BinaryArray`](crate::array::BinaryArray)
423///
424/// See examples on [`GenericBinaryBuilder`]
425pub type BinaryBuilder = GenericBinaryBuilder<i32>;
426
427/// Builder for [`LargeBinaryArray`](crate::array::LargeBinaryArray)
428///
429/// See examples on [`GenericBinaryBuilder`]
430pub type LargeBinaryBuilder = GenericBinaryBuilder<i64>;
431
432/// Builder for [`StringArray`](crate::array::StringArray)
433///
434/// See examples on [`GenericStringBuilder`]
435pub type StringBuilder = GenericStringBuilder<i32>;
436
437/// Builder for [`LargeStringArray`](crate::array::LargeStringArray)
438///
439/// See examples on [`GenericStringBuilder`]
440pub type LargeStringBuilder = GenericStringBuilder<i64>;
441
442/// Returns a builder with capacity for `capacity` elements of datatype
443/// `DataType`.
444///
445/// This function is useful to construct arrays from an arbitrary vectors with
446/// known/expected schema.
447///
448/// See comments on [StructBuilder] for retrieving collection builders built by
449/// make_builder.
450///
451/// # Panics
452///
453/// Panics if `datatype` is not supported, see [`ArrayBuilder`] implementations
454pub fn make_builder(datatype: &DataType, capacity: usize) -> Box<dyn ArrayBuilder> {
455    use crate::builder::*;
456    match datatype {
457        DataType::Null => Box::new(NullBuilder::new()),
458        DataType::Boolean => Box::new(BooleanBuilder::with_capacity(capacity)),
459        DataType::Int8 => Box::new(Int8Builder::with_capacity(capacity)),
460        DataType::Int16 => Box::new(Int16Builder::with_capacity(capacity)),
461        DataType::Int32 => Box::new(Int32Builder::with_capacity(capacity)),
462        DataType::Int64 => Box::new(Int64Builder::with_capacity(capacity)),
463        DataType::UInt8 => Box::new(UInt8Builder::with_capacity(capacity)),
464        DataType::UInt16 => Box::new(UInt16Builder::with_capacity(capacity)),
465        DataType::UInt32 => Box::new(UInt32Builder::with_capacity(capacity)),
466        DataType::UInt64 => Box::new(UInt64Builder::with_capacity(capacity)),
467        DataType::Float16 => Box::new(Float16Builder::with_capacity(capacity)),
468        DataType::Float32 => Box::new(Float32Builder::with_capacity(capacity)),
469        DataType::Float64 => Box::new(Float64Builder::with_capacity(capacity)),
470        DataType::Binary => Box::new(BinaryBuilder::with_capacity(capacity, 1024)),
471        DataType::LargeBinary => Box::new(LargeBinaryBuilder::with_capacity(capacity, 1024)),
472        DataType::BinaryView => Box::new(BinaryViewBuilder::with_capacity(capacity)),
473        DataType::FixedSizeBinary(len) => {
474            Box::new(FixedSizeBinaryBuilder::with_capacity(capacity, *len))
475        }
476        DataType::Decimal32(p, s) => Box::new(
477            Decimal32Builder::with_capacity(capacity).with_data_type(DataType::Decimal32(*p, *s)),
478        ),
479        DataType::Decimal64(p, s) => Box::new(
480            Decimal64Builder::with_capacity(capacity).with_data_type(DataType::Decimal64(*p, *s)),
481        ),
482        DataType::Decimal128(p, s) => Box::new(
483            Decimal128Builder::with_capacity(capacity).with_data_type(DataType::Decimal128(*p, *s)),
484        ),
485        DataType::Decimal256(p, s) => Box::new(
486            Decimal256Builder::with_capacity(capacity).with_data_type(DataType::Decimal256(*p, *s)),
487        ),
488        DataType::Utf8 => Box::new(StringBuilder::with_capacity(capacity, 1024)),
489        DataType::LargeUtf8 => Box::new(LargeStringBuilder::with_capacity(capacity, 1024)),
490        DataType::Utf8View => Box::new(StringViewBuilder::with_capacity(capacity)),
491        DataType::Date32 => Box::new(Date32Builder::with_capacity(capacity)),
492        DataType::Date64 => Box::new(Date64Builder::with_capacity(capacity)),
493        DataType::Time32(TimeUnit::Second) => {
494            Box::new(Time32SecondBuilder::with_capacity(capacity))
495        }
496        DataType::Time32(TimeUnit::Millisecond) => {
497            Box::new(Time32MillisecondBuilder::with_capacity(capacity))
498        }
499        DataType::Time64(TimeUnit::Microsecond) => {
500            Box::new(Time64MicrosecondBuilder::with_capacity(capacity))
501        }
502        DataType::Time64(TimeUnit::Nanosecond) => {
503            Box::new(Time64NanosecondBuilder::with_capacity(capacity))
504        }
505        DataType::Timestamp(TimeUnit::Second, tz) => Box::new(
506            TimestampSecondBuilder::with_capacity(capacity)
507                .with_data_type(DataType::Timestamp(TimeUnit::Second, tz.clone())),
508        ),
509        DataType::Timestamp(TimeUnit::Millisecond, tz) => Box::new(
510            TimestampMillisecondBuilder::with_capacity(capacity)
511                .with_data_type(DataType::Timestamp(TimeUnit::Millisecond, tz.clone())),
512        ),
513        DataType::Timestamp(TimeUnit::Microsecond, tz) => Box::new(
514            TimestampMicrosecondBuilder::with_capacity(capacity)
515                .with_data_type(DataType::Timestamp(TimeUnit::Microsecond, tz.clone())),
516        ),
517        DataType::Timestamp(TimeUnit::Nanosecond, tz) => Box::new(
518            TimestampNanosecondBuilder::with_capacity(capacity)
519                .with_data_type(DataType::Timestamp(TimeUnit::Nanosecond, tz.clone())),
520        ),
521        DataType::Interval(IntervalUnit::YearMonth) => {
522            Box::new(IntervalYearMonthBuilder::with_capacity(capacity))
523        }
524        DataType::Interval(IntervalUnit::DayTime) => {
525            Box::new(IntervalDayTimeBuilder::with_capacity(capacity))
526        }
527        DataType::Interval(IntervalUnit::MonthDayNano) => {
528            Box::new(IntervalMonthDayNanoBuilder::with_capacity(capacity))
529        }
530        DataType::Duration(TimeUnit::Second) => {
531            Box::new(DurationSecondBuilder::with_capacity(capacity))
532        }
533        DataType::Duration(TimeUnit::Millisecond) => {
534            Box::new(DurationMillisecondBuilder::with_capacity(capacity))
535        }
536        DataType::Duration(TimeUnit::Microsecond) => {
537            Box::new(DurationMicrosecondBuilder::with_capacity(capacity))
538        }
539        DataType::Duration(TimeUnit::Nanosecond) => {
540            Box::new(DurationNanosecondBuilder::with_capacity(capacity))
541        }
542        DataType::List(field) => {
543            let builder = make_builder(field.data_type(), capacity);
544            Box::new(ListBuilder::with_capacity(builder, capacity).with_field(field.clone()))
545        }
546        DataType::LargeList(field) => {
547            let builder = make_builder(field.data_type(), capacity);
548            Box::new(LargeListBuilder::with_capacity(builder, capacity).with_field(field.clone()))
549        }
550        DataType::FixedSizeList(field, size) => {
551            let size = *size;
552            let values_builder_capacity = {
553                let size: usize = size.try_into().unwrap();
554                capacity * size
555            };
556            let builder = make_builder(field.data_type(), values_builder_capacity);
557            Box::new(
558                FixedSizeListBuilder::with_capacity(builder, size, capacity)
559                    .with_field(field.clone()),
560            )
561        }
562        DataType::ListView(field) => {
563            let builder = make_builder(field.data_type(), capacity);
564            Box::new(ListViewBuilder::with_capacity(builder, capacity).with_field(field.clone()))
565        }
566        DataType::LargeListView(field) => {
567            let builder = make_builder(field.data_type(), capacity);
568            Box::new(
569                LargeListViewBuilder::with_capacity(builder, capacity).with_field(field.clone()),
570            )
571        }
572        DataType::Map(field, _) => match field.data_type() {
573            DataType::Struct(fields) => {
574                let map_field_names = MapFieldNames {
575                    key: fields[0].name().clone(),
576                    value: fields[1].name().clone(),
577                    entry: field.name().clone(),
578                };
579                let key_builder = make_builder(fields[0].data_type(), capacity);
580                let value_builder = make_builder(fields[1].data_type(), capacity);
581                Box::new(
582                    MapBuilder::with_capacity(
583                        Some(map_field_names),
584                        key_builder,
585                        value_builder,
586                        capacity,
587                    )
588                    .with_keys_field(fields[0].clone())
589                    .with_values_field(fields[1].clone()),
590                )
591            }
592            t => panic!("The field of Map data type {t} should have a child Struct field"),
593        },
594        DataType::Struct(fields) => Box::new(StructBuilder::from_fields(fields.clone(), capacity)),
595        t @ DataType::Dictionary(key_type, value_type) => {
596            macro_rules! dict_builder {
597                ($key_type:ty) => {
598                    match &**value_type {
599                        DataType::Utf8 => {
600                            let dict_builder: StringDictionaryBuilder<$key_type> =
601                                StringDictionaryBuilder::with_capacity(capacity, 256, 1024);
602                            Box::new(dict_builder)
603                        }
604                        DataType::LargeUtf8 => {
605                            let dict_builder: LargeStringDictionaryBuilder<$key_type> =
606                                LargeStringDictionaryBuilder::with_capacity(capacity, 256, 1024);
607                            Box::new(dict_builder)
608                        }
609                        DataType::Binary => {
610                            let dict_builder: BinaryDictionaryBuilder<$key_type> =
611                                BinaryDictionaryBuilder::with_capacity(capacity, 256, 1024);
612                            Box::new(dict_builder)
613                        }
614                        DataType::LargeBinary => {
615                            let dict_builder: LargeBinaryDictionaryBuilder<$key_type> =
616                                LargeBinaryDictionaryBuilder::with_capacity(capacity, 256, 1024);
617                            Box::new(dict_builder)
618                        }
619                        t => unimplemented!("Dictionary value type {t} is not currently supported"),
620                    }
621                };
622            }
623            match &**key_type {
624                DataType::Int8 => dict_builder!(Int8Type),
625                DataType::Int16 => dict_builder!(Int16Type),
626                DataType::Int32 => dict_builder!(Int32Type),
627                DataType::Int64 => dict_builder!(Int64Type),
628                _ => {
629                    unimplemented!(
630                        "Data type {t} with key type {key_type} is not currently supported"
631                    )
632                }
633            }
634        }
635        t => unimplemented!("Data type {t} is not currently supported"),
636    }
637}
638
639#[cfg(test)]
640mod tests {
641    use super::*;
642
643    #[derive(Default)]
644    pub struct PreserveValuesMock {
645        pub called: usize,
646        pub inner: Int32Builder,
647    }
648
649    impl ArrayBuilder for PreserveValuesMock {
650        fn as_any(&self) -> &dyn Any {
651            self
652        }
653
654        fn as_any_mut(&mut self) -> &mut dyn Any {
655            self
656        }
657
658        fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
659            self
660        }
661
662        fn len(&self) -> usize {
663            self.inner.len()
664        }
665
666        fn finish(&mut self) -> ArrayRef {
667            panic!("finish should never be called on PreserveValuesMock")
668        }
669
670        fn finish_cloned(&self) -> ArrayRef {
671            panic!("finish_cloned should never be called on PreserveValuesMock")
672        }
673
674        fn finish_preserve_values(&mut self) -> ArrayRef {
675            self.called += 1;
676            self.inner.finish_preserve_values()
677        }
678    }
679}