1use crate::builder::ArrayBuilder;
19use crate::{ArrayRef, FixedSizeListArray};
20use arrow_buffer::NullBufferBuilder;
21use arrow_schema::{Field, FieldRef};
22use std::any::Any;
23use std::sync::Arc;
24
25#[derive(Debug)]
65pub struct FixedSizeListBuilder<T: ArrayBuilder> {
66 null_buffer_builder: NullBufferBuilder,
67 values_builder: T,
68 list_len: i32,
69 field: Option<FieldRef>,
70}
71
72impl<T: ArrayBuilder> FixedSizeListBuilder<T> {
73 pub fn new(values_builder: T, value_length: i32) -> Self {
76 let capacity = values_builder
77 .len()
78 .checked_div(value_length as _)
79 .unwrap_or_default();
80
81 Self::with_capacity(values_builder, value_length, capacity)
82 }
83
84 pub fn with_capacity(values_builder: T, value_length: i32, capacity: usize) -> Self {
88 Self {
89 null_buffer_builder: NullBufferBuilder::new(capacity),
90 values_builder,
91 list_len: value_length,
92 field: None,
93 }
94 }
95
96 pub fn with_field(self, field: impl Into<FieldRef>) -> Self {
103 Self {
104 field: Some(field.into()),
105 ..self
106 }
107 }
108}
109
110impl<T: ArrayBuilder> ArrayBuilder for FixedSizeListBuilder<T>
111where
112 T: 'static,
113{
114 fn as_any(&self) -> &dyn Any {
116 self
117 }
118
119 fn as_any_mut(&mut self) -> &mut dyn Any {
121 self
122 }
123
124 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
126 self
127 }
128
129 fn len(&self) -> usize {
131 self.null_buffer_builder.len()
132 }
133
134 fn finish(&mut self) -> ArrayRef {
136 Arc::new(self.finish())
137 }
138
139 fn finish_cloned(&self) -> ArrayRef {
141 Arc::new(self.finish_cloned())
142 }
143
144 fn finish_preserve_values(&mut self) -> ArrayRef {
145 Arc::new(self.finish_preserve_values())
146 }
147}
148
149impl<T: ArrayBuilder> FixedSizeListBuilder<T>
150where
151 T: 'static,
152{
153 pub fn values(&mut self) -> &mut T {
158 &mut self.values_builder
159 }
160
161 pub fn value_length(&self) -> i32 {
163 self.list_len
164 }
165
166 #[inline]
168 pub fn append(&mut self, is_valid: bool) {
169 self.null_buffer_builder.append(is_valid);
170 }
171
172 pub fn finish(&mut self) -> FixedSizeListArray {
178 let len = self.len();
179 let values = self.values_builder.finish();
180 let nulls = self.null_buffer_builder.finish();
181
182 assert_eq!(
183 values.len(),
184 len * self.list_len as usize,
185 "Length of the child array ({}) must be the multiple of the value length ({}) and the array length ({}).",
186 values.len(),
187 self.list_len,
188 len,
189 );
190
191 let field = self
192 .field
193 .clone()
194 .unwrap_or_else(|| Arc::new(Field::new_list_field(values.data_type().clone(), true)));
195
196 FixedSizeListArray::new(field, self.list_len, values, nulls)
197 }
198
199 pub fn finish_cloned(&self) -> FixedSizeListArray {
205 let len = self.len();
206 let values = self.values_builder.finish_cloned();
207 let nulls = self.null_buffer_builder.finish_cloned();
208
209 assert_eq!(
210 values.len(),
211 len * self.list_len as usize,
212 "Length of the child array ({}) must be the multiple of the value length ({}) and the array length ({}).",
213 values.len(),
214 self.list_len,
215 len,
216 );
217
218 let field = self
219 .field
220 .clone()
221 .unwrap_or_else(|| Arc::new(Field::new_list_field(values.data_type().clone(), true)));
222
223 FixedSizeListArray::new(field, self.list_len, values, nulls)
224 }
225
226 fn finish_preserve_values(&mut self) -> FixedSizeListArray {
227 let len = self.len();
228 let values = self.values_builder.finish_preserve_values();
229 let nulls = self.null_buffer_builder.finish();
230
231 assert_eq!(
232 values.len(),
233 len * self.list_len as usize,
234 "Length of the child array ({}) must be the multiple of the value length ({}) and the array length ({}).",
235 values.len(),
236 self.list_len,
237 len,
238 );
239
240 let field = self
241 .field
242 .clone()
243 .unwrap_or_else(|| Arc::new(Field::new_list_field(values.data_type().clone(), true)));
244
245 FixedSizeListArray::new(field, self.list_len, values, nulls)
246 }
247
248 pub fn validity_slice(&self) -> Option<&[u8]> {
250 self.null_buffer_builder.as_slice()
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use arrow_schema::DataType;
258
259 use crate::Array;
260 use crate::Int32Array;
261 use crate::builder::{Int32Builder, tests::PreserveValuesMock};
262
263 fn make_list_builder(
264 include_null_element: bool,
265 include_null_in_values: bool,
266 ) -> FixedSizeListBuilder<crate::builder::PrimitiveBuilder<crate::types::Int32Type>> {
267 let values_builder = Int32Builder::new();
268 let mut builder = FixedSizeListBuilder::new(values_builder, 3);
269
270 builder.values().append_value(0);
271 builder.values().append_value(1);
272 builder.values().append_value(2);
273 builder.append(true);
274
275 builder.values().append_value(2);
276 builder.values().append_value(3);
277 builder.values().append_value(4);
278 builder.append(true);
279
280 if include_null_element {
281 builder.values().append_null();
282 builder.values().append_null();
283 builder.values().append_null();
284 builder.append(false);
285 } else {
286 builder.values().append_value(2);
287 builder.values().append_value(3);
288 builder.values().append_value(4);
289 builder.append(true);
290 }
291
292 if include_null_in_values {
293 builder.values().append_value(3);
294 builder.values().append_null();
295 builder.values().append_value(5);
296 builder.append(true);
297 } else {
298 builder.values().append_value(3);
299 builder.values().append_value(4);
300 builder.values().append_value(5);
301 builder.append(true);
302 }
303
304 builder
305 }
306
307 #[test]
308 fn test_fixed_size_list_array_builder() {
309 let mut builder = make_list_builder(true, true);
310
311 let list_array = builder.finish();
312
313 assert_eq!(DataType::Int32, list_array.value_type());
314 assert_eq!(4, list_array.len());
315 assert_eq!(1, list_array.null_count());
316 assert_eq!(6, list_array.value_offset(2));
317 assert_eq!(3, list_array.value_length());
318 }
319
320 #[test]
321 fn test_fixed_size_list_array_builder_with_field() {
322 let builder = make_list_builder(false, false);
323 let mut builder = builder.with_field(Field::new("list_element", DataType::Int32, false));
324 let list_array = builder.finish();
325
326 assert_eq!(DataType::Int32, list_array.value_type());
327 assert_eq!(4, list_array.len());
328 assert_eq!(0, list_array.null_count());
329 assert_eq!(6, list_array.value_offset(2));
330 assert_eq!(3, list_array.value_length());
331 }
332
333 #[test]
334 fn test_fixed_size_list_array_builder_with_field_and_null() {
335 let builder = make_list_builder(true, false);
336 let mut builder = builder.with_field(Field::new("list_element", DataType::Int32, false));
337 let list_array = builder.finish();
338
339 assert_eq!(DataType::Int32, list_array.value_type());
340 assert_eq!(4, list_array.len());
341 assert_eq!(1, list_array.null_count());
342 assert_eq!(6, list_array.value_offset(2));
343 assert_eq!(3, list_array.value_length());
344 }
345
346 #[test]
347 #[should_panic(expected = "Found unmasked nulls for non-nullable FixedSizeListArray")]
348 fn test_fixed_size_list_array_builder_with_field_null_panic() {
349 let builder = make_list_builder(true, true);
350 let mut builder = builder.with_field(Field::new("list_item", DataType::Int32, false));
351
352 builder.finish();
353 }
354
355 #[test]
356 #[should_panic(expected = "FixedSizeListArray expected data type Int64 got Int32")]
357 fn test_fixed_size_list_array_builder_with_field_type_panic() {
358 let values_builder = Int32Builder::new();
359 let builder = FixedSizeListBuilder::new(values_builder, 3);
360 let mut builder = builder.with_field(Field::new("list_item", DataType::Int64, true));
361
362 builder.values().append_value(0);
364 builder.values().append_value(1);
365 builder.values().append_value(2);
366 builder.append(true);
367 builder.values().append_null();
368 builder.values().append_null();
369 builder.values().append_null();
370 builder.append(false);
371 builder.values().append_value(3);
372 builder.values().append_value(4);
373 builder.values().append_value(5);
374 builder.append(true);
375
376 builder.finish();
377 }
378
379 #[test]
380 fn test_fixed_size_list_array_builder_cloned_with_field() {
381 let builder = make_list_builder(true, true);
382 let builder = builder.with_field(Field::new("list_element", DataType::Int32, true));
383
384 let list_array = builder.finish_cloned();
385
386 assert_eq!(DataType::Int32, list_array.value_type());
387 assert_eq!(4, list_array.len());
388 assert_eq!(1, list_array.null_count());
389 assert_eq!(6, list_array.value_offset(2));
390 assert_eq!(3, list_array.value_length());
391 }
392
393 #[test]
394 #[should_panic(expected = "Found unmasked nulls for non-nullable FixedSizeListArray")]
395 fn test_fixed_size_list_array_builder_cloned_with_field_null_panic() {
396 let builder = make_list_builder(true, true);
397 let builder = builder.with_field(Field::new("list_item", DataType::Int32, false));
398
399 builder.finish_cloned();
400 }
401
402 #[test]
403 fn test_fixed_size_list_array_builder_cloned_with_field_and_null() {
404 let builder = make_list_builder(true, false);
405 let mut builder = builder.with_field(Field::new("list_element", DataType::Int32, false));
406 let list_array = builder.finish();
407
408 assert_eq!(DataType::Int32, list_array.value_type());
409 assert_eq!(4, list_array.len());
410 assert_eq!(1, list_array.null_count());
411 assert_eq!(6, list_array.value_offset(2));
412 assert_eq!(3, list_array.value_length());
413 }
414
415 #[test]
416 #[should_panic(expected = "FixedSizeListArray expected data type Int64 got Int32")]
417 fn test_fixed_size_list_array_builder_cloned_with_field_type_panic() {
418 let builder = make_list_builder(false, false);
419 let builder = builder.with_field(Field::new("list_item", DataType::Int64, true));
420
421 builder.finish_cloned();
422 }
423
424 #[test]
425 fn test_fixed_size_list_array_builder_finish_cloned() {
426 let mut builder = make_list_builder(true, true);
427
428 let mut list_array = builder.finish_cloned();
429
430 assert_eq!(DataType::Int32, list_array.value_type());
431 assert_eq!(4, list_array.len());
432 assert_eq!(1, list_array.null_count());
433 assert_eq!(3, list_array.value_length());
434
435 builder.values().append_value(6);
436 builder.values().append_value(7);
437 builder.values().append_null();
438 builder.append(true);
439 builder.values().append_null();
440 builder.values().append_null();
441 builder.values().append_null();
442 builder.append(false);
443 list_array = builder.finish();
444
445 assert_eq!(DataType::Int32, list_array.value_type());
446 assert_eq!(6, list_array.len());
447 assert_eq!(2, list_array.null_count());
448 assert_eq!(6, list_array.value_offset(2));
449 assert_eq!(3, list_array.value_length());
450 }
451
452 #[test]
453 fn test_fixed_size_list_array_builder_with_field_empty() {
454 let values_builder = Int32Array::builder(0);
455 let mut builder = FixedSizeListBuilder::new(values_builder, 3).with_field(Field::new(
456 "list_item",
457 DataType::Int32,
458 false,
459 ));
460 assert!(builder.is_empty());
461 let arr = builder.finish();
462 assert_eq!(0, arr.len());
463 assert_eq!(0, builder.len());
464 }
465
466 #[test]
467 fn test_fixed_size_list_array_builder_cloned_with_field_empty() {
468 let values_builder = Int32Array::builder(0);
469 let builder = FixedSizeListBuilder::new(values_builder, 3).with_field(Field::new(
470 "list_item",
471 DataType::Int32,
472 false,
473 ));
474 assert!(builder.is_empty());
475 let arr = builder.finish_cloned();
476 assert_eq!(0, arr.len());
477 assert_eq!(0, builder.len());
478 }
479
480 #[test]
481 fn test_fixed_size_list_array_builder_empty() {
482 let values_builder = Int32Array::builder(5);
483 let mut builder = FixedSizeListBuilder::new(values_builder, 3);
484 assert!(builder.is_empty());
485 let arr = builder.finish();
486 assert_eq!(0, arr.len());
487 assert_eq!(0, builder.len());
488 }
489
490 #[test]
491 fn test_fixed_size_list_array_builder_finish() {
492 let values_builder = Int32Array::builder(5);
493 let mut builder = FixedSizeListBuilder::new(values_builder, 3);
494
495 builder.values().append_slice(&[1, 2, 3]);
496 builder.append(true);
497 builder.values().append_slice(&[4, 5, 6]);
498 builder.append(true);
499
500 let mut arr = builder.finish();
501 assert_eq!(2, arr.len());
502 assert_eq!(0, builder.len());
503
504 builder.values().append_slice(&[7, 8, 9]);
505 builder.append(true);
506 arr = builder.finish();
507 assert_eq!(1, arr.len());
508 assert_eq!(0, builder.len());
509 }
510
511 #[test]
512 #[should_panic(
513 expected = "Length of the child array (10) must be the multiple of the value length (3) and the array length (3)."
514 )]
515 fn test_fixed_size_list_array_builder_fail() {
516 let values_builder = Int32Array::builder(5);
517 let mut builder = FixedSizeListBuilder::new(values_builder, 3);
518
519 builder.values().append_slice(&[1, 2, 3]);
520 builder.append(true);
521 builder.values().append_slice(&[4, 5, 6]);
522 builder.append(true);
523 builder.values().append_slice(&[7, 8, 9, 10]);
524 builder.append(true);
525
526 builder.finish();
527 }
528
529 #[test]
530 fn test_finish_preserve_values() {
531 let mut builder = FixedSizeListBuilder::new(PreserveValuesMock::default(), 2);
532
533 builder.values().inner.append_value(0);
534 builder.values().inner.append_value(1);
535 builder.append(true);
536
537 let arr = builder.finish_preserve_values();
538
539 assert_eq!(1, arr.len());
540 assert_eq!(1, builder.values().called);
541 }
542}