1use std::any::Any;
34use std::sync::Arc;
35
36use vortex_error::VortexResult;
37use vortex_mask::Mask;
38
39use crate::ArrayRef;
40use crate::ExecutionCtx;
41use crate::canonical::Canonical;
42use crate::dtype::DType;
43use crate::match_each_decimal_value_type;
44use crate::match_each_native_ptype;
45use crate::memory::HostAllocatorRef;
46use crate::scalar::Scalar;
47
48mod lazy_null_builder;
49pub(crate) use lazy_null_builder::LazyBitBufferBuilder;
50
51mod bool;
52mod decimal;
53pub mod dict;
54mod extension;
55mod fixed_size_list;
56mod list;
57mod listview;
58mod map;
59mod null;
60mod primitive;
61mod struct_;
62mod varbinview;
63
64pub use bool::*;
65pub use decimal::*;
66pub use extension::*;
67pub use fixed_size_list::*;
68pub use list::*;
69pub use listview::*;
70pub use map::*;
71pub use null::*;
72pub use primitive::*;
73pub use struct_::*;
74pub use varbinview::*;
75
76pub use crate::arrays::varbin::builder::VarBinBuilder;
77
78#[cfg(test)]
79mod tests;
80
81pub const DEFAULT_BUILDER_CAPACITY: usize = 1024;
85
86pub trait ArrayBuilder: Send {
87 fn as_any(&self) -> &dyn Any;
88
89 fn as_any_mut(&mut self) -> &mut dyn Any;
90
91 fn dtype(&self) -> &DType;
92
93 fn len(&self) -> usize;
94
95 fn is_empty(&self) -> bool {
96 self.len() == 0
97 }
98
99 fn append_zero(&mut self) {
103 self.append_zeros(1)
104 }
105
106 fn append_zeros(&mut self, n: usize);
110
111 fn append_null(&mut self) {
115 self.append_nulls(1)
116 }
117
118 unsafe fn append_nulls_unchecked(&mut self, n: usize);
124
125 fn append_nulls(&mut self, n: usize) {
129 assert!(
130 self.dtype().is_nullable(),
131 "tried to append {n} nulls to a non-nullable array builder"
132 );
133
134 unsafe {
136 self.append_nulls_unchecked(n);
137 }
138 }
139
140 fn append_default(&mut self) {
142 self.append_defaults(1)
143 }
144
145 fn append_defaults(&mut self, n: usize) {
150 if self.dtype().is_nullable() {
151 self.append_nulls(n);
152 } else {
153 self.append_zeros(n);
154 }
155 }
156
157 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()>;
159
160 fn reserve_exact(&mut self, additional: usize);
162
163 fn set_validity(&mut self, validity: Mask) {
167 if !self.dtype().is_nullable() {
168 return;
169 }
170 assert_eq!(self.len(), validity.len());
171 unsafe { self.set_validity_unchecked(validity) }
172 }
173
174 unsafe fn set_validity_unchecked(&mut self, validity: Mask);
180
181 fn finish(&mut self) -> ArrayRef;
191
192 fn finish_into_canonical(&mut self, ctx: &mut ExecutionCtx) -> Canonical;
198}
199
200#[macro_export]
211macro_rules! match_each_list_builder {
212 ($dyn_builder:expr, | $builder:ident | $body:expr) => {{
213 let __dyn_builder: &mut dyn $crate::builders::ArrayBuilder = $dyn_builder;
214 match $crate::__match_each_list_builder!(
215 __dyn_builder,
216 $builder,
217 $body,
218 [u32, u64, i32, i64]
219 ) {
220 ::core::option::Option::Some(__result) => ::core::option::Option::Some(__result),
221 ::core::option::Option::None => $crate::__match_each_listview_builder!(
222 __dyn_builder,
223 $builder,
224 $body,
225 [u32, u64, i32, i64]
226 ),
227 }
228 }};
229}
230
231#[doc(hidden)]
232#[macro_export]
233macro_rules! __match_each_list_builder {
234 ($target:ident, $builder:ident, $body:expr, []) => {
235 ::core::option::Option::None
236 };
237 ($target:ident, $builder:ident, $body:expr, [$offset:ty $(, $rest:ty)*]) => {
238 if let ::core::option::Option::Some($builder) =
239 $crate::builders::ArrayBuilder::as_any_mut($target)
240 .downcast_mut::<$crate::builders::ListBuilder<$offset>>()
241 {
242 ::core::option::Option::Some($body)
243 } else {
244 $crate::__match_each_list_builder!($target, $builder, $body, [$($rest),*])
245 }
246 };
247}
248
249#[doc(hidden)]
250#[macro_export]
251macro_rules! __match_each_listview_builder {
252 ($target:ident, $builder:ident, $body:expr, []) => {
253 ::core::option::Option::None
254 };
255 ($target:ident, $builder:ident, $body:expr, [$offset:ty $(, $rest:ty)*]) => {
256 match $crate::__match_each_listview_builder_size!(
257 $target,
258 $builder,
259 $body,
260 $offset,
261 [u32, u64, i32, i64]
262 ) {
263 ::core::option::Option::Some(__result) => ::core::option::Option::Some(__result),
264 ::core::option::Option::None => $crate::__match_each_listview_builder!(
265 $target,
266 $builder,
267 $body,
268 [$($rest),*]
269 ),
270 }
271 };
272}
273
274#[doc(hidden)]
275#[macro_export]
276macro_rules! __match_each_listview_builder_size {
277 ($target:ident, $builder:ident, $body:expr, $offset:ty, []) => {
278 ::core::option::Option::None
279 };
280 ($target:ident, $builder:ident, $body:expr, $offset:ty, [$size:ty $(, $rest:ty)*]) => {
281 if let ::core::option::Option::Some($builder) =
282 $crate::builders::ArrayBuilder::as_any_mut($target)
283 .downcast_mut::<$crate::builders::ListViewBuilder<$offset, $size>>()
284 {
285 ::core::option::Option::Some($body)
286 } else {
287 $crate::__match_each_listview_builder_size!(
288 $target, $builder, $body, $offset, [$($rest),*]
289 )
290 }
291 };
292}
293
294#[macro_export]
299macro_rules! match_each_map_builder {
300 ($dyn_builder:expr, | $builder:ident | $body:expr) => {{
301 let __dyn_builder: &mut dyn $crate::builders::ArrayBuilder = $dyn_builder;
302 $crate::__match_each_map_builder!(__dyn_builder, $builder, $body, [u32, u64, i32, i64])
303 }};
304}
305
306#[doc(hidden)]
307#[macro_export]
308macro_rules! __match_each_map_builder {
309 ($target:ident, $builder:ident, $body:expr, []) => {
310 ::core::option::Option::None
311 };
312 ($target:ident, $builder:ident, $body:expr, [$offset:ty $(, $rest:ty)*]) => {
313 match $crate::__match_each_map_builder_size!(
314 $target,
315 $builder,
316 $body,
317 $offset,
318 [u32, u64, i32, i64]
319 ) {
320 ::core::option::Option::Some(__result) => ::core::option::Option::Some(__result),
321 ::core::option::Option::None => $crate::__match_each_map_builder!(
322 $target,
323 $builder,
324 $body,
325 [$($rest),*]
326 ),
327 }
328 };
329}
330
331#[doc(hidden)]
332#[macro_export]
333macro_rules! __match_each_map_builder_size {
334 ($target:ident, $builder:ident, $body:expr, $offset:ty, []) => {
335 ::core::option::Option::None
336 };
337 ($target:ident, $builder:ident, $body:expr, $offset:ty, [$size:ty $(, $rest:ty)*]) => {
338 if let ::core::option::Option::Some($builder) =
339 $crate::builders::ArrayBuilder::as_any_mut($target)
340 .downcast_mut::<$crate::builders::MapBuilder<$offset, $size>>()
341 {
342 ::core::option::Option::Some($body)
343 } else {
344 $crate::__match_each_map_builder_size!(
345 $target, $builder, $body, $offset, [$($rest),*]
346 )
347 }
348 };
349}
350
351pub fn builder_with_capacity(dtype: &DType, capacity: usize) -> Box<dyn ArrayBuilder> {
378 match dtype {
379 DType::Null => Box::new(NullBuilder::new()),
380 DType::Bool(n) => Box::new(BoolBuilder::with_capacity(*n, capacity)),
381 DType::Primitive(ptype, n) => {
382 match_each_native_ptype!(ptype, |P| {
383 Box::new(PrimitiveBuilder::<P>::with_capacity(*n, capacity))
384 })
385 }
386 DType::Decimal(decimal_type, n) => {
387 match_each_decimal_value_type!(
388 DecimalType::smallest_decimal_value_type(decimal_type),
389 |D| {
390 Box::new(DecimalBuilder::with_capacity::<D>(
391 capacity,
392 *decimal_type,
393 *n,
394 ))
395 }
396 )
397 }
398 DType::Utf8(n) => Box::new(VarBinViewBuilder::with_capacity(DType::Utf8(*n), capacity)),
399 DType::Binary(n) => Box::new(VarBinViewBuilder::with_capacity(
400 DType::Binary(*n),
401 capacity,
402 )),
403 DType::List(dtype, n) => Box::new(ListViewBuilder::<u64, u64>::with_capacity(
404 Arc::clone(dtype),
405 *n,
406 2 * capacity, capacity,
408 )),
409 DType::Map(map_dtype, nullability) => Box::new(MapBuilder::<u64, u64>::with_capacity(
410 map_dtype.clone(),
411 *nullability,
412 capacity,
413 )),
414 DType::FixedSizeList(elem_dtype, list_size, null) => {
415 Box::new(FixedSizeListBuilder::with_capacity(
416 Arc::clone(elem_dtype),
417 *list_size,
418 *null,
419 capacity,
420 ))
421 }
422 DType::Struct(struct_dtype, n) => Box::new(StructBuilder::with_capacity(
423 struct_dtype.clone(),
424 *n,
425 capacity,
426 )),
427 DType::Union(..) => todo!("TODO(connor)[Union]: unimplemented"),
428 DType::Variant(_) => {
429 unimplemented!()
430 }
431 DType::Extension(ext_dtype) => {
432 Box::new(ExtensionBuilder::with_capacity(ext_dtype.clone(), capacity))
433 }
434 }
435}
436
437pub fn builder_with_capacity_in(
440 allocator: HostAllocatorRef,
441 dtype: &DType,
442 capacity: usize,
443) -> Box<dyn ArrayBuilder> {
444 let _allocator = allocator;
445 builder_with_capacity(dtype, capacity)
446}