1use crate::builder::{ArrayBuilder, FixedSizeBinaryBuilder, PrimitiveBuilder};
19use crate::types::ArrowDictionaryKeyType;
20use crate::{Array, ArrayRef, DictionaryArray, PrimitiveArray};
21use arrow_buffer::ArrowNativeType;
22use arrow_schema::DataType::FixedSizeBinary;
23use arrow_schema::{ArrowError, DataType};
24use hashbrown::HashTable;
25use num_traits::NumCast;
26use std::any::Any;
27use std::sync::Arc;
28
29#[derive(Debug)]
61pub struct FixedSizeBinaryDictionaryBuilder<K>
62where
63 K: ArrowDictionaryKeyType,
64{
65 state: ahash::RandomState,
66 dedup: HashTable<usize>,
67
68 keys_builder: PrimitiveBuilder<K>,
69 values_builder: FixedSizeBinaryBuilder,
70 byte_width: i32,
71}
72
73impl<K> FixedSizeBinaryDictionaryBuilder<K>
74where
75 K: ArrowDictionaryKeyType,
76{
77 pub fn new(byte_width: i32) -> Self {
79 let keys_builder = PrimitiveBuilder::new();
80 let values_builder = FixedSizeBinaryBuilder::new(byte_width);
81 Self {
82 state: Default::default(),
83 dedup: HashTable::with_capacity(keys_builder.capacity()),
84 keys_builder,
85 values_builder,
86 byte_width,
87 }
88 }
89
90 pub fn with_capacity(keys_capacity: usize, value_capacity: usize, byte_width: i32) -> Self {
96 Self {
97 state: Default::default(),
98 dedup: Default::default(),
99 keys_builder: PrimitiveBuilder::with_capacity(keys_capacity),
100 values_builder: FixedSizeBinaryBuilder::with_capacity(value_capacity, byte_width),
101 byte_width,
102 }
103 }
104
105 pub fn try_new_from_builder<K2>(
131 mut source: FixedSizeBinaryDictionaryBuilder<K2>,
132 ) -> Result<Self, ArrowError>
133 where
134 K::Native: NumCast,
135 K2: ArrowDictionaryKeyType,
136 K2::Native: NumCast,
137 {
138 let state = source.state;
139 let dedup = source.dedup;
140 let values_builder = source.values_builder;
141 let byte_width = source.byte_width;
142
143 let source_keys = source.keys_builder.finish();
144 let new_keys: PrimitiveArray<K> = source_keys.try_unary(|value| {
145 num_traits::cast::cast::<K2::Native, K::Native>(value).ok_or_else(|| {
146 ArrowError::CastError(format!(
147 "Can't cast dictionary keys from source type {:?} to type {:?}",
148 K2::DATA_TYPE,
149 K::DATA_TYPE
150 ))
151 })
152 })?;
153
154 drop(source_keys);
158
159 Ok(Self {
160 state,
161 dedup,
162 keys_builder: new_keys.into_builder().map_err(|_| {
163 ArrowError::ComputeError(
164 "Internal Error: the keys just derived from the source builder are \
165 unexpectedly shared, so they cannot be reused as a builder"
166 .to_string(),
167 )
168 })?,
169 values_builder,
170 byte_width,
171 })
172 }
173}
174
175impl<K> ArrayBuilder for FixedSizeBinaryDictionaryBuilder<K>
176where
177 K: ArrowDictionaryKeyType,
178{
179 fn as_any(&self) -> &dyn Any {
181 self
182 }
183
184 fn as_any_mut(&mut self) -> &mut dyn Any {
186 self
187 }
188
189 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
191 self
192 }
193
194 fn len(&self) -> usize {
196 self.keys_builder.len()
197 }
198
199 fn finish(&mut self) -> ArrayRef {
201 Arc::new(self.finish())
202 }
203
204 fn finish_cloned(&self) -> ArrayRef {
206 Arc::new(self.finish_cloned())
207 }
208
209 fn finish_preserve_values(&mut self) -> ArrayRef {
210 Arc::new(self.finish_preserve_values())
211 }
212}
213
214impl<K> FixedSizeBinaryDictionaryBuilder<K>
215where
216 K: ArrowDictionaryKeyType,
217{
218 fn get_or_insert_key(&mut self, value: impl AsRef<[u8]>) -> Result<K::Native, ArrowError> {
219 let value_bytes: &[u8] = value.as_ref();
220
221 let state = &self.state;
222 let storage = &mut self.values_builder;
223 let hash = state.hash_one(value_bytes);
224
225 let idx = *self
226 .dedup
227 .entry(
228 hash,
229 |idx| value_bytes == get_bytes(storage, self.byte_width, *idx),
230 |idx| state.hash_one(get_bytes(storage, self.byte_width, *idx)),
231 )
232 .or_insert_with(|| {
233 let idx = storage.len();
234 let _ = storage.append_value(value);
235 idx
236 })
237 .get();
238
239 let key = K::Native::from_usize(idx).ok_or(ArrowError::DictionaryKeyOverflowError)?;
240
241 Ok(key)
242 }
243
244 pub fn append(&mut self, value: impl AsRef<[u8]>) -> Result<K::Native, ArrowError> {
250 if self.byte_width != value.as_ref().len() as i32 {
251 Err(ArrowError::InvalidArgumentError(format!(
252 "Invalid input length passed to FixedSizeBinaryBuilder. Expected {} got {}",
253 self.byte_width,
254 value.as_ref().len()
255 )))
256 } else {
257 let key = self.get_or_insert_key(value)?;
258 self.keys_builder.append_value(key);
259 Ok(key)
260 }
261 }
262
263 pub fn append_n(
268 &mut self,
269 value: impl AsRef<[u8]>,
270 count: usize,
271 ) -> Result<K::Native, ArrowError> {
272 if self.byte_width != value.as_ref().len() as i32 {
273 Err(ArrowError::InvalidArgumentError(format!(
274 "Invalid input length passed to FixedSizeBinaryBuilder. Expected {} got {}",
275 self.byte_width,
276 value.as_ref().len()
277 )))
278 } else {
279 let key = self.get_or_insert_key(value)?;
280 self.keys_builder.append_value_n(key, count);
281 Ok(key)
282 }
283 }
284
285 #[inline]
287 pub fn append_null(&mut self) {
288 self.keys_builder.append_null()
289 }
290
291 #[inline]
293 pub fn append_nulls(&mut self, n: usize) {
294 self.keys_builder.append_nulls(n);
295 }
296
297 pub fn append_value(&mut self, value: impl AsRef<[u8]>) {
303 self.append(value).expect("dictionary key overflow");
304 }
305
306 pub fn finish(&mut self) -> DictionaryArray<K> {
308 self.dedup.clear();
309 let values = self.values_builder.finish();
310 let keys = self.keys_builder.finish();
311
312 let data_type = DataType::Dictionary(
313 Box::new(K::DATA_TYPE),
314 Box::new(FixedSizeBinary(self.byte_width)),
315 );
316
317 let builder = keys
318 .into_data()
319 .into_builder()
320 .data_type(data_type)
321 .child_data(vec![values.into_data()]);
322
323 DictionaryArray::from(unsafe { builder.build_unchecked() })
325 }
326
327 pub fn finish_cloned(&self) -> DictionaryArray<K> {
329 let values = self.values_builder.finish_cloned();
330 let keys = self.keys_builder.finish_cloned();
331
332 let data_type = DataType::Dictionary(
333 Box::new(K::DATA_TYPE),
334 Box::new(FixedSizeBinary(self.byte_width)),
335 );
336
337 let builder = keys
338 .into_data()
339 .into_builder()
340 .data_type(data_type)
341 .child_data(vec![values.into_data()]);
342
343 DictionaryArray::from(unsafe { builder.build_unchecked() })
345 }
346
347 pub fn finish_preserve_values(&mut self) -> DictionaryArray<K> {
365 let values = self.values_builder.finish_cloned();
366 let keys = self.keys_builder.finish();
367
368 let data_type = DataType::Dictionary(
369 Box::new(K::DATA_TYPE),
370 Box::new(FixedSizeBinary(self.byte_width)),
371 );
372
373 let builder = keys
374 .into_data()
375 .into_builder()
376 .data_type(data_type)
377 .child_data(vec![values.into_data()]);
378
379 DictionaryArray::from(unsafe { builder.build_unchecked() })
381 }
382}
383
384fn get_bytes(values: &FixedSizeBinaryBuilder, byte_width: i32, idx: usize) -> &[u8] {
385 let values = values.values_slice();
386 let start = idx * byte_width.as_usize();
387 let end = idx * byte_width.as_usize() + byte_width.as_usize();
388 &values[start..end]
389}
390
391#[cfg(test)]
392mod tests {
393 use super::*;
394
395 use crate::types::{Int8Type, Int16Type, Int32Type, UInt8Type, UInt16Type};
396 use crate::{ArrowPrimitiveType, FixedSizeBinaryArray, Int8Array};
397
398 #[test]
399 fn test_fixed_size_dictionary_builder() {
400 let values = ["abc", "def"];
401
402 let mut b = FixedSizeBinaryDictionaryBuilder::<Int8Type>::new(3);
403 assert_eq!(b.append(values[0]).unwrap(), 0);
404 b.append_null();
405 assert_eq!(b.append(values[1]).unwrap(), 1);
406 assert_eq!(b.append(values[1]).unwrap(), 1);
407 assert_eq!(b.append(values[0]).unwrap(), 0);
408 b.append_nulls(2);
409 assert_eq!(b.append(values[0]).unwrap(), 0);
410 let array = b.finish();
411
412 assert_eq!(
413 array.keys(),
414 &Int8Array::from(vec![
415 Some(0),
416 None,
417 Some(1),
418 Some(1),
419 Some(0),
420 None,
421 None,
422 Some(0)
423 ]),
424 );
425
426 let ava = array
428 .values()
429 .as_any()
430 .downcast_ref::<FixedSizeBinaryArray>()
431 .unwrap();
432
433 assert_eq!(ava.value(0), values[0].as_bytes());
434 assert_eq!(ava.value(1), values[1].as_bytes());
435 }
436
437 #[test]
438 fn test_fixed_size_dictionary_builder_append_n() {
439 let values = ["abc", "def"];
440 let mut b = FixedSizeBinaryDictionaryBuilder::<Int8Type>::new(3);
441 assert_eq!(b.append_n(values[0], 2).unwrap(), 0);
442 assert_eq!(b.append_n(values[1], 3).unwrap(), 1);
443 assert_eq!(b.append_n(values[0], 2).unwrap(), 0);
444 let array = b.finish();
445
446 assert_eq!(
447 array.keys(),
448 &Int8Array::from(vec![
449 Some(0),
450 Some(0),
451 Some(1),
452 Some(1),
453 Some(1),
454 Some(0),
455 Some(0),
456 ]),
457 );
458
459 let ava = array
461 .values()
462 .as_any()
463 .downcast_ref::<FixedSizeBinaryArray>()
464 .unwrap();
465
466 assert_eq!(ava.value(0), values[0].as_bytes());
467 assert_eq!(ava.value(1), values[1].as_bytes());
468 }
469
470 #[test]
471 fn test_fixed_size_dictionary_builder_wrong_size() {
472 let mut b = FixedSizeBinaryDictionaryBuilder::<Int8Type>::new(3);
473 let err = b.append(b"too long").unwrap_err().to_string();
474 assert_eq!(
475 err,
476 "Invalid argument error: Invalid input length passed to FixedSizeBinaryBuilder. Expected 3 got 8"
477 );
478 let err = b.append("").unwrap_err().to_string();
479 assert_eq!(
480 err,
481 "Invalid argument error: Invalid input length passed to FixedSizeBinaryBuilder. Expected 3 got 0"
482 );
483 let err = b.append_n("a", 3).unwrap_err().to_string();
484 assert_eq!(
485 err,
486 "Invalid argument error: Invalid input length passed to FixedSizeBinaryBuilder. Expected 3 got 1"
487 );
488 }
489
490 #[test]
491 fn test_fixed_size_dictionary_builder_finish_cloned() {
492 let values = ["abc", "def", "ghi"];
493
494 let mut builder = FixedSizeBinaryDictionaryBuilder::<Int8Type>::new(3);
495
496 builder.append(values[0]).unwrap();
497 builder.append_null();
498 builder.append(values[1]).unwrap();
499 builder.append(values[1]).unwrap();
500 builder.append(values[0]).unwrap();
501 let mut array = builder.finish_cloned();
502
503 assert_eq!(
504 array.keys(),
505 &Int8Array::from(vec![Some(0), None, Some(1), Some(1), Some(0)])
506 );
507
508 let ava = array
510 .values()
511 .as_any()
512 .downcast_ref::<FixedSizeBinaryArray>()
513 .unwrap();
514
515 assert_eq!(ava.value(0), values[0].as_bytes());
516 assert_eq!(ava.value(1), values[1].as_bytes());
517
518 builder.append(values[0]).unwrap();
519 builder.append(values[2]).unwrap();
520 builder.append(values[1]).unwrap();
521
522 array = builder.finish();
523
524 assert_eq!(
525 array.keys(),
526 &Int8Array::from(vec![
527 Some(0),
528 None,
529 Some(1),
530 Some(1),
531 Some(0),
532 Some(0),
533 Some(2),
534 Some(1)
535 ])
536 );
537
538 let ava2 = array
540 .values()
541 .as_any()
542 .downcast_ref::<FixedSizeBinaryArray>()
543 .unwrap();
544
545 assert_eq!(ava2.value(0), values[0].as_bytes());
546 assert_eq!(ava2.value(1), values[1].as_bytes());
547 assert_eq!(ava2.value(2), values[2].as_bytes());
548 }
549
550 fn _test_try_new_from_builder_generic_for_key_types<K1, K2>(values: Vec<[u8; 3]>)
551 where
552 K1: ArrowDictionaryKeyType,
553 K1::Native: NumCast,
554 K2: ArrowDictionaryKeyType,
555 K2::Native: NumCast + From<u8>,
556 {
557 let mut source = FixedSizeBinaryDictionaryBuilder::<K1>::new(3);
558 source.append_value(values[0]);
559 source.append_null();
560 source.append_value(values[1]);
561 source.append_value(values[2]);
562
563 let mut result =
564 FixedSizeBinaryDictionaryBuilder::<K2>::try_new_from_builder(source).unwrap();
565 let array = result.finish();
566
567 let mut expected_keys_builder = PrimitiveBuilder::<K2>::new();
568 expected_keys_builder
569 .append_value(<<K2 as ArrowPrimitiveType>::Native as From<u8>>::from(0u8));
570 expected_keys_builder.append_null();
571 expected_keys_builder
572 .append_value(<<K2 as ArrowPrimitiveType>::Native as From<u8>>::from(1u8));
573 expected_keys_builder
574 .append_value(<<K2 as ArrowPrimitiveType>::Native as From<u8>>::from(2u8));
575 let expected_keys = expected_keys_builder.finish();
576 assert_eq!(array.keys(), &expected_keys);
577
578 let av = array.values();
579 let ava = av.as_any().downcast_ref::<FixedSizeBinaryArray>().unwrap();
580 assert_eq!(ava.value(0), values[0]);
581 assert_eq!(ava.value(1), values[1]);
582 assert_eq!(ava.value(2), values[2]);
583 }
584
585 #[test]
586 fn test_try_new_from_builder() {
587 let values = vec![[1, 2, 3], [5, 6, 7], [6, 7, 8]];
588 _test_try_new_from_builder_generic_for_key_types::<UInt8Type, UInt16Type>(values.clone());
590 _test_try_new_from_builder_generic_for_key_types::<UInt16Type, UInt8Type>(values.clone());
592 _test_try_new_from_builder_generic_for_key_types::<Int8Type, Int16Type>(values.clone());
594 _test_try_new_from_builder_generic_for_key_types::<Int32Type, Int16Type>(values.clone());
596 _test_try_new_from_builder_generic_for_key_types::<UInt8Type, Int16Type>(values.clone());
598 _test_try_new_from_builder_generic_for_key_types::<Int8Type, UInt8Type>(values.clone());
599 _test_try_new_from_builder_generic_for_key_types::<Int8Type, UInt16Type>(values.clone());
600 _test_try_new_from_builder_generic_for_key_types::<Int32Type, Int16Type>(values.clone());
601 }
602
603 #[test]
604 fn test_try_new_from_builder_cast_fails() {
605 let mut source_builder = FixedSizeBinaryDictionaryBuilder::<UInt16Type>::new(2);
606 for i in 0u16..257u16 {
607 source_builder.append_value(vec![(i >> 8) as u8, i as u8]);
608 }
609
610 let result =
613 FixedSizeBinaryDictionaryBuilder::<UInt8Type>::try_new_from_builder(source_builder);
614 assert!(result.is_err());
615 if let Err(e) = result {
616 assert!(matches!(e, ArrowError::CastError(_)));
617 assert_eq!(
618 e.to_string(),
619 "Cast error: Can't cast dictionary keys from source type UInt16 to type UInt8"
620 );
621 }
622 }
623
624 #[test]
625 fn test_finish_preserve_values() {
626 let mut builder = FixedSizeBinaryDictionaryBuilder::<Int32Type>::new(3);
628 builder.append_value("aaa");
629 builder.append_value("bbb");
630 builder.append_value("ccc");
631 let dict = builder.finish_preserve_values();
632 assert_eq!(dict.keys().values(), &[0, 1, 2]);
633 let values = dict
634 .downcast_dict::<FixedSizeBinaryArray>()
635 .unwrap()
636 .into_iter()
637 .collect::<Vec<_>>();
638 assert_eq!(
639 values,
640 vec![
641 Some(b"aaa".as_slice()),
642 Some(b"bbb".as_slice()),
643 Some(b"ccc".as_slice())
644 ]
645 );
646
647 builder.append_value("ddd");
649 builder.append_value("eee");
650 let dict2 = builder.finish_preserve_values();
651
652 assert_eq!(dict2.keys().values(), &[3, 4]);
655 let values = dict2
656 .downcast_dict::<FixedSizeBinaryArray>()
657 .unwrap()
658 .into_iter()
659 .collect::<Vec<_>>();
660 assert_eq!(values, [Some(b"ddd".as_slice()), Some(b"eee".as_slice())]);
661
662 let all_values = dict2
664 .values()
665 .as_any()
666 .downcast_ref::<FixedSizeBinaryArray>()
667 .unwrap()
668 .into_iter()
669 .collect::<Vec<_>>();
670 assert_eq!(
671 all_values,
672 [
673 Some(b"aaa".as_slice()),
674 Some(b"bbb".as_slice()),
675 Some(b"ccc".as_slice()),
676 Some(b"ddd".as_slice()),
677 Some(b"eee".as_slice())
678 ]
679 );
680 }
681}