1use crate::builder::ArrayBuilder;
6use crate::{Array, ArrayRef, MapArray, StructArray};
7use arrow_buffer::Buffer;
8use arrow_buffer::{NullBuffer, NullBufferBuilder};
9use arrow_data::ArrayData;
10use arrow_schema::{ArrowError, DataType, Field, FieldRef};
11use std::any::Any;
12use std::sync::Arc;
13
14#[derive(Debug)]
45pub struct MapBuilder<K: ArrayBuilder, V: ArrayBuilder> {
46 offsets_builder: Vec<i32>,
47 null_buffer_builder: NullBufferBuilder,
48 field_names: MapFieldNames,
49 key_builder: K,
50 value_builder: V,
51 key_field: Option<FieldRef>,
52 value_field: Option<FieldRef>,
53}
54
55#[derive(Debug, Clone)]
57pub struct MapFieldNames {
58 pub entry: String,
60 pub key: String,
62 pub value: String,
64}
65
66impl Default for MapFieldNames {
67 fn default() -> Self {
68 Self {
69 entry: Field::MAP_ENTRIES_FIELD_DEFAULT_NAME.to_string(),
70 key: Field::MAP_KEY_FIELD_DEFAULT_NAME.to_string(),
71 value: Field::MAP_VALUE_FIELD_DEFAULT_NAME.to_string(),
72 }
73 }
74}
75
76impl<K: ArrayBuilder, V: ArrayBuilder> MapBuilder<K, V> {
77 pub fn new(field_names: Option<MapFieldNames>, key_builder: K, value_builder: V) -> Self {
79 let capacity = key_builder.len();
80 Self::with_capacity(field_names, key_builder, value_builder, capacity)
81 }
82
83 pub fn with_capacity(
85 field_names: Option<MapFieldNames>,
86 key_builder: K,
87 value_builder: V,
88 capacity: usize,
89 ) -> Self {
90 let mut offsets_builder = Vec::with_capacity(capacity + 1);
91 offsets_builder.push(0);
92 Self {
93 offsets_builder,
94 null_buffer_builder: NullBufferBuilder::new(capacity),
95 field_names: field_names.unwrap_or_default(),
96 key_builder,
97 value_builder,
98 key_field: None,
99 value_field: None,
100 }
101 }
102
103 pub fn with_keys_field(self, field: impl Into<FieldRef>) -> Self {
110 Self {
111 key_field: Some(field.into()),
112 ..self
113 }
114 }
115
116 pub fn with_values_field(self, field: impl Into<FieldRef>) -> Self {
123 Self {
124 value_field: Some(field.into()),
125 ..self
126 }
127 }
128
129 pub fn keys(&mut self) -> &mut K {
131 &mut self.key_builder
132 }
133
134 pub fn values(&mut self) -> &mut V {
136 &mut self.value_builder
137 }
138
139 pub fn entries(&mut self) -> (&mut K, &mut V) {
141 (&mut self.key_builder, &mut self.value_builder)
142 }
143
144 #[inline]
146 fn validate_equal_lengths(&self) -> Result<(), ArrowError> {
147 if self.key_builder.len() != self.value_builder.len() {
148 return Err(ArrowError::InvalidArgumentError(format!(
149 "Cannot append to a map builder when its keys and values have unequal lengths of {} and {}",
150 self.key_builder.len(),
151 self.value_builder.len()
152 )));
153 }
154 Ok(())
155 }
156
157 #[inline]
161 fn next_offset(&self) -> Result<i32, ArrowError> {
162 let len = self.key_builder.len();
163 i32::try_from(len).map_err(|_| {
164 ArrowError::InvalidArgumentError(format!(
165 "Cannot append to a map builder with {len} entries: offset exceeds i32::MAX"
166 ))
167 })
168 }
169
170 #[inline]
175 pub fn append(&mut self, is_valid: bool) -> Result<(), ArrowError> {
176 self.validate_equal_lengths()?;
177 let offset = self.next_offset()?;
178 self.offsets_builder.push(offset);
179 self.null_buffer_builder.append(is_valid);
180 Ok(())
181 }
182
183 #[inline]
188 pub fn append_nulls(&mut self, n: usize) -> Result<(), ArrowError> {
189 self.validate_equal_lengths()?;
190 let offset = self.next_offset()?;
191 self.offsets_builder.extend(std::iter::repeat_n(offset, n));
192 self.null_buffer_builder.append_n_nulls(n);
193 Ok(())
194 }
195
196 pub fn finish(&mut self) -> MapArray {
204 let len = self.len();
205 let keys_arr = self.key_builder.finish();
207 let values_arr = self.value_builder.finish();
208 let offset_buffer = Buffer::from_vec(std::mem::take(&mut self.offsets_builder));
209 self.offsets_builder.push(0);
210 let null_bit_buffer = self.null_buffer_builder.finish();
211
212 self.finish_helper(keys_arr, values_arr, offset_buffer, null_bit_buffer, len)
213 }
214
215 pub fn finish_cloned(&self) -> MapArray {
223 let len = self.len();
224 let keys_arr = self.key_builder.finish_cloned();
226 let values_arr = self.value_builder.finish_cloned();
227 let offset_buffer = Buffer::from_slice_ref(self.offsets_builder.as_slice());
228 let nulls = self.null_buffer_builder.finish_cloned();
229 self.finish_helper(keys_arr, values_arr, offset_buffer, nulls, len)
230 }
231
232 fn finish_preserve_values(&mut self) -> MapArray {
233 let len = self.len();
234 let keys_arr = self.key_builder.finish_preserve_values();
236 let values_arr = self.value_builder.finish_preserve_values();
237 let offset_buffer = Buffer::from_vec(std::mem::take(&mut self.offsets_builder));
238 self.offsets_builder.push(0);
239 let null_bit_buffer = self.null_buffer_builder.finish();
240
241 self.finish_helper(keys_arr, values_arr, offset_buffer, null_bit_buffer, len)
242 }
243
244 fn finish_helper(
245 &self,
246 keys_arr: Arc<dyn Array>,
247 values_arr: Arc<dyn Array>,
248 offset_buffer: Buffer,
249 nulls: Option<NullBuffer>,
250 len: usize,
251 ) -> MapArray {
252 assert!(
253 keys_arr.null_count() == 0,
254 "Keys array must have no null values, found {} null value(s)",
255 keys_arr.null_count()
256 );
257
258 let keys_field = match &self.key_field {
259 Some(f) => {
260 assert!(!f.is_nullable(), "Keys field must not be nullable");
261 f.clone()
262 }
263 None => Arc::new(Field::new(
264 self.field_names.key.as_str(),
265 keys_arr.data_type().clone(),
266 false, )),
268 };
269 let values_field = match &self.value_field {
270 Some(f) => f.clone(),
271 None => Arc::new(Field::new(
272 self.field_names.value.as_str(),
273 values_arr.data_type().clone(),
274 true,
275 )),
276 };
277
278 let struct_array =
279 StructArray::from(vec![(keys_field, keys_arr), (values_field, values_arr)]);
280
281 let map_field = Arc::new(Field::new(
282 self.field_names.entry.as_str(),
283 struct_array.data_type().clone(),
284 false, ));
286 let array_data = ArrayData::builder(DataType::Map(map_field, false)) .len(len)
288 .add_buffer(offset_buffer)
289 .add_child_data(struct_array.into_data())
290 .nulls(nulls);
291
292 let array_data = unsafe { array_data.build_unchecked() };
294
295 MapArray::from(array_data)
296 }
297
298 pub fn validity_slice(&self) -> Option<&[u8]> {
300 self.null_buffer_builder.as_slice()
301 }
302}
303
304impl<K: ArrayBuilder, V: ArrayBuilder> ArrayBuilder for MapBuilder<K, V> {
305 fn len(&self) -> usize {
306 self.null_buffer_builder.len()
307 }
308
309 fn finish(&mut self) -> ArrayRef {
310 Arc::new(self.finish())
311 }
312
313 fn finish_cloned(&self) -> ArrayRef {
315 Arc::new(self.finish_cloned())
316 }
317
318 fn finish_preserve_values(&mut self) -> ArrayRef {
319 Arc::new(self.finish_preserve_values())
320 }
321
322 fn as_any(&self) -> &dyn Any {
323 self
324 }
325
326 fn as_any_mut(&mut self) -> &mut dyn Any {
327 self
328 }
329
330 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
331 self
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 use crate::builder::{Int32Builder, StringBuilder, make_builder, tests::PreserveValuesMock};
339 use crate::{Int32Array, StringArray};
340 use std::collections::HashMap;
341
342 #[test]
343 #[should_panic(expected = "Keys array must have no null values, found 1 null value(s)")]
344 fn test_map_builder_with_null_keys_panics() {
345 let mut builder = MapBuilder::new(None, StringBuilder::new(), Int32Builder::new());
346 builder.keys().append_null();
347 builder.values().append_value(42);
348 builder.append(true).unwrap();
349
350 builder.finish();
351 }
352
353 #[test]
354 fn test_boxed_map_builder() {
355 let keys_builder = make_builder(&DataType::Utf8, 5);
356 let values_builder = make_builder(&DataType::Int32, 5);
357
358 let mut builder = MapBuilder::new(None, keys_builder, values_builder);
359 builder
360 .keys()
361 .as_any_mut()
362 .downcast_mut::<StringBuilder>()
363 .expect("should be an StringBuilder")
364 .append_value("1");
365 builder
366 .values()
367 .as_any_mut()
368 .downcast_mut::<Int32Builder>()
369 .expect("should be an Int32Builder")
370 .append_value(42);
371 builder.append(true).unwrap();
372
373 let map_array = builder.finish();
374
375 assert_eq!(
376 map_array
377 .keys()
378 .as_any()
379 .downcast_ref::<StringArray>()
380 .expect("should be an StringArray")
381 .value(0),
382 "1"
383 );
384 assert_eq!(
385 map_array
386 .values()
387 .as_any()
388 .downcast_ref::<Int32Array>()
389 .expect("should be an Int32Array")
390 .value(0),
391 42
392 );
393 }
394
395 #[test]
396 fn test_with_values_field() {
397 let value_field = Arc::new(Field::new("bars", DataType::Int32, false));
398 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new())
399 .with_values_field(value_field.clone());
400 builder.keys().append_value(1);
401 builder.values().append_value(2);
402 builder.append(true).unwrap();
403 builder.append(false).unwrap(); builder.keys().append_value(3);
405 builder.values().append_value(4);
406 builder.append(true).unwrap();
407 let map = builder.finish();
408
409 assert_eq!(map.len(), 3);
410 assert_eq!(
411 map.data_type(),
412 &DataType::Map(
413 Arc::new(Field::new(
414 Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
415 DataType::Struct(
416 vec![
417 Arc::new(Field::new(
418 Field::MAP_KEY_FIELD_DEFAULT_NAME,
419 DataType::Int32,
420 false
421 )),
422 value_field.clone()
423 ]
424 .into()
425 ),
426 false,
427 )),
428 false
429 )
430 );
431
432 builder.keys().append_value(5);
433 builder.values().append_value(6);
434 builder.append(true).unwrap();
435 let map = builder.finish();
436
437 assert_eq!(map.len(), 1);
438 assert_eq!(
439 map.data_type(),
440 &DataType::Map(
441 Arc::new(Field::new(
442 Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
443 DataType::Struct(
444 vec![
445 Arc::new(Field::new(
446 Field::MAP_KEY_FIELD_DEFAULT_NAME,
447 DataType::Int32,
448 false
449 )),
450 value_field
451 ]
452 .into()
453 ),
454 false,
455 )),
456 false
457 )
458 );
459 }
460
461 #[test]
462 fn test_with_keys_field() {
463 let mut key_metadata = HashMap::new();
464 key_metadata.insert("foo".to_string(), "bar".to_string());
465 let key_field = Arc::new(
466 Field::new("other_key", DataType::Int32, false).with_metadata(key_metadata.clone()),
467 );
468 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new())
469 .with_keys_field(key_field.clone());
470 builder.keys().append_value(1);
471 builder.values().append_value(2);
472 builder.append(true).unwrap();
473 let map = builder.finish();
474
475 assert_eq!(map.len(), 1);
476 assert_eq!(
477 map.data_type(),
478 &DataType::Map(
479 Arc::new(Field::new(
480 Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
481 DataType::Struct(
482 vec![
483 Arc::new(
484 Field::new("other_key", DataType::Int32, false)
485 .with_metadata(key_metadata)
486 ),
487 Arc::new(Field::new(
488 Field::MAP_VALUE_FIELD_DEFAULT_NAME,
489 DataType::Int32,
490 true
491 ))
492 ]
493 .into()
494 ),
495 false,
496 )),
497 false
498 )
499 );
500 }
501
502 #[test]
503 fn test_append_nulls() {
504 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new());
505
506 builder.keys().append_value(1);
507 builder.values().append_value(100);
508 builder.append(true).unwrap();
509
510 builder.append_nulls(3).unwrap();
511
512 builder.keys().append_value(2);
513 builder.values().append_value(200);
514 builder.append(true).unwrap();
515
516 let map = builder.finish();
517 assert_eq!(map.len(), 5);
518 assert_eq!(map.null_count(), 3);
519 assert!(map.is_valid(0));
520 assert!(map.is_null(1));
521 assert!(map.is_null(2));
522 assert!(map.is_null(3));
523 assert!(map.is_valid(4));
524 assert_eq!(map.value_offsets(), &[0, 1, 1, 1, 1, 2]);
525 }
526
527 #[test]
528 fn test_append_nulls_inconsistent_state() {
529 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new());
530 builder.keys().append_value(1);
532
533 let result = builder.append_nulls(2);
534 assert!(result.is_err());
535 assert!(result.unwrap_err().to_string().contains("unequal lengths"));
536 }
537
538 #[test]
539 #[should_panic(expected = "Keys field must not be nullable")]
540 fn test_with_nullable_keys_field() {
541 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new())
542 .with_keys_field(Arc::new(Field::new(
543 Field::MAP_KEY_FIELD_DEFAULT_NAME,
544 DataType::Int32,
545 true,
546 )));
547
548 builder.keys().append_value(1);
549 builder.values().append_value(2);
550 builder.append(true).unwrap();
551
552 builder.finish();
553 }
554
555 #[test]
556 #[should_panic(expected = "Incorrect datatype")]
557 fn test_keys_field_type_mismatch() {
558 let mut builder = MapBuilder::new(None, Int32Builder::new(), Int32Builder::new())
559 .with_keys_field(Arc::new(Field::new(
560 Field::MAP_KEY_FIELD_DEFAULT_NAME,
561 DataType::Utf8,
562 false,
563 )));
564
565 builder.keys().append_value(1);
566 builder.values().append_value(2);
567 builder.append(true).unwrap();
568
569 builder.finish();
570 }
571
572 #[test]
573 fn test_finish_preserve_values() {
574 let mut builder = MapBuilder::new(
575 None,
576 PreserveValuesMock::default(),
577 PreserveValuesMock::default(),
578 );
579
580 builder.keys().inner.append_value(1);
581 builder.values().inner.append_value(2);
582 builder.append(true).unwrap();
583
584 let map = builder.finish_preserve_values();
585
586 assert_eq!(1, map.len());
587 assert_eq!(1, builder.keys().called);
588 assert_eq!(1, builder.values().called);
589 }
590
591 struct FixedLenBuilder(usize);
594
595 impl ArrayBuilder for FixedLenBuilder {
596 fn as_any(&self) -> &dyn Any {
597 self
598 }
599
600 fn as_any_mut(&mut self) -> &mut dyn Any {
601 self
602 }
603
604 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
605 self
606 }
607
608 fn len(&self) -> usize {
609 self.0
610 }
611
612 fn finish(&mut self) -> ArrayRef {
613 panic!("finish should never be called on FixedLenBuilder")
614 }
615
616 fn finish_cloned(&self) -> ArrayRef {
617 panic!("finish_cloned should never be called on FixedLenBuilder")
618 }
619 }
620
621 #[test]
622 fn test_append_offset_overflow() {
623 let len = i32::MAX as usize + 1;
624 let mut builder = MapBuilder::new(None, FixedLenBuilder(len), FixedLenBuilder(len));
625
626 let result = builder.append(true);
627 assert!(result.is_err());
628 assert!(result.unwrap_err().to_string().contains("exceeds i32::MAX"));
629
630 let result = builder.append_nulls(1);
631 assert!(result.is_err());
632 assert!(result.unwrap_err().to_string().contains("exceeds i32::MAX"));
633
634 assert_eq!(builder.offsets_builder, vec![0]);
636 assert_eq!(builder.len(), 0);
637 }
638}