1use crate::cast::*;
6
7pub(crate) fn dictionary_cast<K: ArrowDictionaryKeyType>(
12 array: &dyn Array,
13 to_type: &DataType,
14 cast_options: &CastOptions,
15) -> Result<ArrayRef, ArrowError> {
16 use DataType::*;
17
18 #[inline]
20 fn is_sparse<K: ArrowDictionaryKeyType>(array: &DictionaryArray<K>) -> bool {
21 array.keys().len() < array.values().len() / 2
22 }
23
24 #[inline]
25 fn values_buffer_fits_in_view<T: ByteArrayType>(values: &GenericByteArray<T>) -> bool {
26 values.values().len() < i32::MAX as usize
27 }
28
29 let array = array.as_dictionary::<K>();
30 let from_child_type = array.values().data_type();
31 match (from_child_type, to_type) {
32 (_, Dictionary(to_index_type, to_value_type)) => {
33 dictionary_to_dictionary_cast(array, to_index_type, to_value_type, cast_options)
34 }
35 (Utf8, Utf8View) if is_sparse(array) => {
44 view_from_dict_values::<K, Utf8Type, StringViewType>(
45 array.keys(),
46 array.values().as_string::<i32>(),
47 )
48 }
49 (Binary, BinaryView) if is_sparse(array) => {
50 view_from_dict_values::<K, BinaryType, BinaryViewType>(
51 array.keys(),
52 array.values().as_binary::<i32>(),
53 )
54 }
55 (LargeUtf8, Utf8View)
61 if is_sparse(array)
62 && values_buffer_fits_in_view(array.values().as_string::<i64>()) =>
63 {
64 view_from_dict_values::<K, LargeUtf8Type, StringViewType>(
65 array.keys(),
66 array.values().as_string::<i64>(),
67 )
68 }
69 (LargeBinary, BinaryView)
70 if is_sparse(array)
71 && values_buffer_fits_in_view(array.values().as_binary::<i64>()) =>
72 {
73 view_from_dict_values::<K, LargeBinaryType, BinaryViewType>(
74 array.keys(),
75 array.values().as_binary::<i64>(),
76 )
77 }
78 (Utf8, BinaryView) if is_sparse(array) => {
80 view_from_dict_values::<K, Utf8Type, BinaryViewType>(
81 array.keys(),
82 array.values().as_string::<i32>(),
83 )
84 }
85 (LargeUtf8, BinaryView)
86 if is_sparse(array)
87 && values_buffer_fits_in_view(array.values().as_string::<i64>()) =>
88 {
89 view_from_dict_values::<K, LargeUtf8Type, BinaryViewType>(
90 array.keys(),
91 array.values().as_string::<i64>(),
92 )
93 }
94 (Binary, Utf8View) if is_sparse(array) => binary_dict_to_string_view::<K, i32>(
96 array.keys(),
97 array.values().as_binary::<i32>(),
98 cast_options,
99 ),
100 (LargeBinary, Utf8View)
101 if is_sparse(array)
102 && values_buffer_fits_in_view(array.values().as_binary::<i64>()) =>
103 {
104 binary_dict_to_string_view::<K, i64>(
105 array.keys(),
106 array.values().as_binary::<i64>(),
107 cast_options,
108 )
109 }
110 _ => unpack_dictionary(array, to_type, cast_options),
111 }
112}
113
114fn dictionary_to_dictionary_cast<K: ArrowDictionaryKeyType>(
115 array: &DictionaryArray<K>,
116 to_index_type: &DataType,
117 to_value_type: &DataType,
118 cast_options: &CastOptions,
119) -> Result<ArrayRef, ArrowError> {
120 use DataType::*;
121
122 if array.values().data_type() == to_value_type
124 && !matches!(array.values().data_type(), Dictionary(_, _))
125 {
126 return cast_keys_only(array, to_index_type, cast_options);
127 }
128
129 if matches!(array.values().data_type(), Dictionary(_, _)) {
136 let flattened = take(array.values().as_ref(), array.keys(), None)?;
137 return cast_with_options(
138 &flattened,
139 &Dictionary(
140 Box::new(to_index_type.clone()),
141 Box::new(to_value_type.clone()),
142 ),
143 cast_options,
144 );
145 }
146
147 let keys_array: ArrayRef = Arc::new(PrimitiveArray::<K>::from(array.keys().to_data()));
148 let values_array = array.values();
149 let cast_keys = cast_with_options(&keys_array, to_index_type, cast_options)?;
150 let cast_values = cast_with_options(values_array, to_value_type, cast_options)?;
151
152 if cast_keys.null_count() > keys_array.null_count() {
155 return Err(ArrowError::ComputeError(format!(
156 "Could not convert {} dictionary indexes from {:?} to {:?}",
157 cast_keys.null_count() - keys_array.null_count(),
158 keys_array.data_type(),
159 to_index_type
160 )));
161 }
162
163 let data = cast_keys.into_data();
164 let builder = data
165 .into_builder()
166 .data_type(Dictionary(
167 Box::new(to_index_type.clone()),
168 Box::new(to_value_type.clone()),
169 ))
170 .child_data(vec![cast_values.into_data()]);
171
172 let data = unsafe { builder.build_unchecked() };
175
176 let new_array: ArrayRef = match to_index_type {
178 Int8 => Arc::new(DictionaryArray::<Int8Type>::from(data)),
179 Int16 => Arc::new(DictionaryArray::<Int16Type>::from(data)),
180 Int32 => Arc::new(DictionaryArray::<Int32Type>::from(data)),
181 Int64 => Arc::new(DictionaryArray::<Int64Type>::from(data)),
182 UInt8 => Arc::new(DictionaryArray::<UInt8Type>::from(data)),
183 UInt16 => Arc::new(DictionaryArray::<UInt16Type>::from(data)),
184 UInt32 => Arc::new(DictionaryArray::<UInt32Type>::from(data)),
185 UInt64 => Arc::new(DictionaryArray::<UInt64Type>::from(data)),
186 _ => {
187 return Err(ArrowError::InvalidArgumentError(format!(
188 "Unsupported type {to_index_type} for dictionary index"
189 )));
190 }
191 };
192
193 Ok(new_array)
194}
195
196fn finish_keys_only<K2: ArrowDictionaryKeyType>(
197 cast_keys: ArrayRef,
198 values: ArrayRef,
199) -> Result<ArrayRef, ArrowError> {
200 let new_keys = cast_keys
201 .as_any()
202 .downcast_ref::<PrimitiveArray<K2>>()
203 .ok_or_else(|| {
204 ArrowError::ComputeError(
205 "Internal Error: cast keys did not downcast to target key type".to_string(),
206 )
207 })?
208 .clone();
209 Ok(Arc::new(unsafe {
211 DictionaryArray::<K2>::new_unchecked(new_keys, values)
212 }))
213}
214
215fn cast_keys_only<K: ArrowDictionaryKeyType>(
216 array: &DictionaryArray<K>,
217 to_index_type: &DataType,
218 cast_options: &CastOptions,
219) -> Result<ArrayRef, ArrowError> {
220 let source_keys = array.keys();
221 let cast_keys = cast_with_options(&source_keys, to_index_type, cast_options)?;
222
223 if cast_keys.null_count() > source_keys.null_count() {
224 return Err(ArrowError::ComputeError(format!(
225 "Could not convert {} dictionary indexes from {:?} to {:?}",
226 cast_keys.null_count() - source_keys.null_count(),
227 source_keys.data_type(),
228 to_index_type
229 )));
230 }
231
232 let values = array.values().clone();
233 match to_index_type {
234 DataType::Int8 => finish_keys_only::<Int8Type>(cast_keys, values),
235 DataType::Int16 => finish_keys_only::<Int16Type>(cast_keys, values),
236 DataType::Int32 => finish_keys_only::<Int32Type>(cast_keys, values),
237 DataType::Int64 => finish_keys_only::<Int64Type>(cast_keys, values),
238 DataType::UInt8 => finish_keys_only::<UInt8Type>(cast_keys, values),
239 DataType::UInt16 => finish_keys_only::<UInt16Type>(cast_keys, values),
240 DataType::UInt32 => finish_keys_only::<UInt32Type>(cast_keys, values),
241 DataType::UInt64 => finish_keys_only::<UInt64Type>(cast_keys, values),
242 _ => Err(ArrowError::InvalidArgumentError(format!(
243 "Unsupported type {to_index_type} for dictionary index"
244 ))),
245 }
246}
247
248fn binary_dict_to_string_view<K: ArrowDictionaryKeyType, O: OffsetSizeTrait>(
255 keys: &PrimitiveArray<K>,
256 values: &GenericByteArray<GenericBinaryType<O>>,
257 cast_options: &CastOptions,
258) -> Result<ArrayRef, ArrowError> {
259 match GenericStringArray::<O>::try_from_binary(values.clone()) {
260 Ok(_) => {
261 view_from_dict_values::<K, GenericBinaryType<O>, StringViewType>(keys, values)
263 }
264 Err(e) => {
265 if !cast_options.safe {
266 return Err(e);
267 }
268 let valid: Vec<bool> = (0..values.len())
271 .map(|i| !values.is_null(i) && std::str::from_utf8(values.value(i)).is_ok())
272 .collect();
273
274 let value_buffer = values.values();
275 let value_offsets = values.value_offsets();
276 let mut builder = StringViewBuilder::with_capacity(keys.len());
277 builder.append_block(value_buffer.clone());
278
279 for key in keys {
280 match key {
281 Some(v) => {
282 let idx = v.to_usize().ok_or_else(|| {
283 ArrowError::ComputeError("Invalid dictionary index".to_string())
284 })?;
285 let is_valid = *valid.get(idx).ok_or_else(|| {
286 ArrowError::InvalidArgumentError(format!(
287 "Dictionary key {idx} out of bounds for dictionary values of length {}",
288 valid.len()
289 ))
290 })?;
291 if is_valid {
292 unsafe {
298 let offset = value_offsets.get_unchecked(idx).as_usize();
299 let end = value_offsets.get_unchecked(idx + 1).as_usize();
300 let length = end - offset;
301 builder.append_view_unchecked(0, offset as u32, length as u32);
302 }
303 } else {
304 builder.append_null();
305 }
306 }
307 None => builder.append_null(),
308 }
309 }
310 Ok(Arc::new(builder.finish()))
311 }
312 }
313}
314
315fn view_from_dict_values<K: ArrowDictionaryKeyType, V: ByteArrayType, T: ByteViewType>(
316 keys: &PrimitiveArray<K>,
317 values: &GenericByteArray<V>,
318) -> Result<ArrayRef, ArrowError> {
319 let value_buffer = values.values();
320 let value_offsets = values.value_offsets();
321 let values_have_nulls = values.null_count() != 0;
323 let mut builder = GenericByteViewBuilder::<T>::with_capacity(keys.len());
324 builder.append_block(value_buffer.clone());
325 for i in keys {
326 match i {
327 Some(v) => {
328 let idx = v.to_usize().ok_or_else(|| {
329 ArrowError::ComputeError("Invalid dictionary index".to_string())
330 })?;
331
332 if values_have_nulls && values.is_null(idx) {
333 builder.append_null();
334 continue;
335 }
336
337 unsafe {
341 let offset = value_offsets.get_unchecked(idx).as_usize();
342 let end = value_offsets.get_unchecked(idx + 1).as_usize();
343 let length = end - offset;
344 builder.append_view_unchecked(0, offset as u32, length as u32)
345 }
346 }
347 None => {
348 builder.append_null();
349 }
350 }
351 }
352 Ok(Arc::new(builder.finish()))
353}
354
355pub(crate) fn unpack_dictionary<K: ArrowDictionaryKeyType>(
357 array: &DictionaryArray<K>,
358 to_type: &DataType,
359 cast_options: &CastOptions,
360) -> Result<ArrayRef, ArrowError> {
361 let cast_dict_values = cast_with_options(array.values(), to_type, cast_options)?;
362 take(cast_dict_values.as_ref(), array.keys(), None)
363}
364
365pub(crate) fn pack_array_to_dictionary_via_primitive<K: ArrowDictionaryKeyType>(
367 array: &dyn Array,
368 primitive_type: DataType,
369 dict_value_type: &DataType,
370 cast_options: &CastOptions,
371) -> Result<ArrayRef, ArrowError> {
372 let primitive = cast_with_options(array, &primitive_type, cast_options)?;
373 let dict = cast_with_options(
374 primitive.as_ref(),
375 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(primitive_type)),
376 cast_options,
377 )?;
378 cast_with_options(
379 dict.as_ref(),
380 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(dict_value_type.clone())),
381 cast_options,
382 )
383}
384
385pub(crate) fn cast_to_dictionary<K: ArrowDictionaryKeyType>(
390 array: &dyn Array,
391 dict_value_type: &DataType,
392 cast_options: &CastOptions,
393) -> Result<ArrayRef, ArrowError> {
394 use DataType::*;
395
396 match *dict_value_type {
397 Int8 => pack_numeric_to_dictionary::<K, Int8Type>(array, dict_value_type, cast_options),
398 Int16 => pack_numeric_to_dictionary::<K, Int16Type>(array, dict_value_type, cast_options),
399 Int32 => pack_numeric_to_dictionary::<K, Int32Type>(array, dict_value_type, cast_options),
400 Int64 => pack_numeric_to_dictionary::<K, Int64Type>(array, dict_value_type, cast_options),
401 UInt8 => pack_numeric_to_dictionary::<K, UInt8Type>(array, dict_value_type, cast_options),
402 UInt16 => pack_numeric_to_dictionary::<K, UInt16Type>(array, dict_value_type, cast_options),
403 UInt32 => pack_numeric_to_dictionary::<K, UInt32Type>(array, dict_value_type, cast_options),
404 UInt64 => pack_numeric_to_dictionary::<K, UInt64Type>(array, dict_value_type, cast_options),
405 Decimal32(p, s) => pack_decimal_to_dictionary::<K, Decimal32Type>(
406 array,
407 dict_value_type,
408 p,
409 s,
410 cast_options,
411 ),
412 Decimal64(p, s) => pack_decimal_to_dictionary::<K, Decimal64Type>(
413 array,
414 dict_value_type,
415 p,
416 s,
417 cast_options,
418 ),
419 Decimal128(p, s) => pack_decimal_to_dictionary::<K, Decimal128Type>(
420 array,
421 dict_value_type,
422 p,
423 s,
424 cast_options,
425 ),
426 Decimal256(p, s) => pack_decimal_to_dictionary::<K, Decimal256Type>(
427 array,
428 dict_value_type,
429 p,
430 s,
431 cast_options,
432 ),
433 Float16 => {
434 pack_numeric_to_dictionary::<K, Float16Type>(array, dict_value_type, cast_options)
435 }
436 Float32 => {
437 pack_numeric_to_dictionary::<K, Float32Type>(array, dict_value_type, cast_options)
438 }
439 Float64 => {
440 pack_numeric_to_dictionary::<K, Float64Type>(array, dict_value_type, cast_options)
441 }
442 Date32 => pack_array_to_dictionary_via_primitive::<K>(
443 array,
444 DataType::Int32,
445 dict_value_type,
446 cast_options,
447 ),
448 Date64 => pack_array_to_dictionary_via_primitive::<K>(
449 array,
450 DataType::Int64,
451 dict_value_type,
452 cast_options,
453 ),
454 Time32(_) => pack_array_to_dictionary_via_primitive::<K>(
455 array,
456 DataType::Int32,
457 dict_value_type,
458 cast_options,
459 ),
460 Time64(_) => pack_array_to_dictionary_via_primitive::<K>(
461 array,
462 DataType::Int64,
463 dict_value_type,
464 cast_options,
465 ),
466 Timestamp(_, _) => pack_array_to_dictionary_via_primitive::<K>(
467 array,
468 DataType::Int64,
469 dict_value_type,
470 cast_options,
471 ),
472 Utf8 => {
473 if array.data_type() == &DataType::Utf8View {
475 return string_view_to_dictionary::<K, i32>(array);
476 }
477 pack_byte_to_dictionary::<K, GenericStringType<i32>>(array, cast_options)
478 }
479 LargeUtf8 => {
480 if array.data_type() == &DataType::Utf8View {
482 return string_view_to_dictionary::<K, i64>(array);
483 }
484 pack_byte_to_dictionary::<K, GenericStringType<i64>>(array, cast_options)
485 }
486 Utf8View => {
487 let base_value_type = match array.data_type() {
488 DataType::LargeUtf8 | DataType::Utf8View => DataType::LargeUtf8,
489 _ => DataType::Utf8,
490 };
491
492 let dict_base = cast_to_dictionary::<K>(array, &base_value_type, cast_options)?;
493 dictionary_cast::<K>(
494 dict_base.as_ref(),
495 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(DataType::Utf8View)),
496 cast_options,
497 )
498 }
499 Binary => {
500 if array.data_type() == &DataType::BinaryView {
502 return binary_view_to_dictionary::<K, i32>(array);
503 }
504 pack_byte_to_dictionary::<K, GenericBinaryType<i32>>(array, cast_options)
505 }
506 LargeBinary => {
507 if array.data_type() == &DataType::BinaryView {
509 return binary_view_to_dictionary::<K, i64>(array);
510 }
511 pack_byte_to_dictionary::<K, GenericBinaryType<i64>>(array, cast_options)
512 }
513 BinaryView => {
514 let base_value_type = match array.data_type() {
515 DataType::LargeBinary | DataType::BinaryView => DataType::LargeBinary,
516 _ => DataType::Binary,
517 };
518
519 let dict_base = cast_to_dictionary::<K>(array, &base_value_type, cast_options)?;
520 dictionary_cast::<K>(
521 dict_base.as_ref(),
522 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(DataType::BinaryView)),
523 cast_options,
524 )
525 }
526 FixedSizeBinary(byte_size) => {
527 pack_byte_to_fixed_size_dictionary::<K>(array, cast_options, byte_size)
528 }
529 Struct(_) => pack_struct_to_dictionary::<K>(array, dict_value_type, cast_options),
530 _ => Err(ArrowError::InvalidArgumentError(format!(
531 "Unsupported output type for dictionary packing: {dict_value_type}"
532 ))),
533 }
534}
535
536fn pack_struct_to_dictionary<K: ArrowDictionaryKeyType>(
546 array: &dyn Array,
547 dict_value_type: &DataType,
548 cast_options: &CastOptions,
549) -> Result<ArrayRef, ArrowError> {
550 let cast_values = cast_with_options(array, dict_value_type, cast_options)?;
551 let len = cast_values.len();
552
553 let mut builder = PrimitiveBuilder::<K>::with_capacity(len);
556 for i in 0..len {
557 if cast_values.is_null(i) {
558 builder.append_null();
559 } else {
560 let key = K::Native::from_usize(i).ok_or_else(|| {
561 ArrowError::CastError(format!(
562 "Cannot fit {len} dictionary keys in {:?}",
563 K::DATA_TYPE,
564 ))
565 })?;
566 builder.append_value(key);
567 }
568 }
569 let keys = builder.finish();
570
571 Ok(Arc::new(DictionaryArray::<K>::try_new(keys, cast_values)?))
572}
573
574pub(crate) fn pack_numeric_to_dictionary<K, V>(
577 array: &dyn Array,
578 dict_value_type: &DataType,
579 cast_options: &CastOptions,
580) -> Result<ArrayRef, ArrowError>
581where
582 K: ArrowDictionaryKeyType,
583 V: ArrowPrimitiveType,
584{
585 let cast_values = cast_with_options(array, dict_value_type, cast_options)?;
587 let values = cast_values.as_primitive::<V>();
588
589 let mut b = PrimitiveDictionaryBuilder::<K, V>::with_capacity(values.len(), values.len());
590
591 for i in 0..values.len() {
593 if values.is_null(i) {
594 b.append_null();
595 } else {
596 b.append(values.value(i))?;
597 }
598 }
599 Ok(Arc::new(b.finish()))
600}
601
602pub(crate) fn pack_decimal_to_dictionary<K, D>(
603 array: &dyn Array,
604 dict_value_type: &DataType,
605 precision: u8,
606 scale: i8,
607 cast_options: &CastOptions,
608) -> Result<ArrayRef, ArrowError>
609where
610 K: ArrowDictionaryKeyType,
611 D: DecimalType + ArrowPrimitiveType,
612{
613 let dict = pack_numeric_to_dictionary::<K, D>(array, dict_value_type, cast_options)?;
614 let dict = dict.as_dictionary::<K>();
615 let value = dict
616 .values()
617 .as_primitive::<D>()
618 .clone()
619 .with_precision_and_scale(precision, scale)?;
620 Ok(Arc::new(dict.with_values(Arc::new(value))))
621}
622
623pub(crate) fn string_view_to_dictionary<K, O: OffsetSizeTrait>(
624 array: &dyn Array,
625) -> Result<ArrayRef, ArrowError>
626where
627 K: ArrowDictionaryKeyType,
628{
629 let mut b = GenericByteDictionaryBuilder::<K, GenericStringType<O>>::with_capacity(
630 array.len(),
631 1024,
632 1024,
633 );
634 let string_view = array.as_string_view();
635 for v in string_view {
636 match v {
637 Some(v) => {
638 b.append(v)?;
639 }
640 None => {
641 b.append_null();
642 }
643 }
644 }
645
646 Ok(Arc::new(b.finish()))
647}
648
649pub(crate) fn binary_view_to_dictionary<K, O: OffsetSizeTrait>(
650 array: &dyn Array,
651) -> Result<ArrayRef, ArrowError>
652where
653 K: ArrowDictionaryKeyType,
654{
655 let mut b = GenericByteDictionaryBuilder::<K, GenericBinaryType<O>>::with_capacity(
656 array.len(),
657 1024,
658 1024,
659 );
660 let binary_view = array.as_binary_view();
661 for v in binary_view {
662 match v {
663 Some(v) => {
664 b.append(v)?;
665 }
666 None => {
667 b.append_null();
668 }
669 }
670 }
671
672 Ok(Arc::new(b.finish()))
673}
674
675pub(crate) fn pack_byte_to_dictionary<K, T>(
678 array: &dyn Array,
679 cast_options: &CastOptions,
680) -> Result<ArrayRef, ArrowError>
681where
682 K: ArrowDictionaryKeyType,
683 T: ByteArrayType,
684{
685 let cast_values = cast_with_options(array, &T::DATA_TYPE, cast_options)?;
686 let values = cast_values.as_bytes::<T>();
687 let mut b = GenericByteDictionaryBuilder::<K, T>::with_capacity(values.len(), 1024, 1024);
688 b.append_array(values)?;
689 Ok(Arc::new(b.finish()))
690}
691
692pub(crate) fn pack_byte_to_fixed_size_dictionary<K>(
695 array: &dyn Array,
696 cast_options: &CastOptions,
697 byte_width: i32,
698) -> Result<ArrayRef, ArrowError>
699where
700 K: ArrowDictionaryKeyType,
701{
702 let cast_values =
703 cast_with_options(array, &DataType::FixedSizeBinary(byte_width), cast_options)?;
704 let values = cast_values.as_fixed_size_binary();
705 let mut b = FixedSizeBinaryDictionaryBuilder::<K>::with_capacity(1024, 1024, byte_width);
706
707 for i in 0..values.len() {
709 if values.is_null(i) {
710 b.append_null();
711 } else {
712 b.append(values.value(i))?;
713 }
714 }
715 Ok(Arc::new(b.finish()))
716}
717
718#[cfg(test)]
719mod tests {
720 use super::*;
721 use DataType::*;
722
723 fn sparse_keys(values: &ArrayRef) -> Int32Array {
726 let keys = Int32Array::from(vec![Some(0), Some(2), None, Some(3)]);
727 assert!(
728 keys.len() < values.len() / 2,
729 "keys must reach the direct path"
730 );
731 keys
732 }
733
734 fn dense_keys(values: &ArrayRef) -> Int32Array {
736 let keys = Int32Array::from(vec![
737 Some(0),
738 Some(2),
739 None,
740 Some(3),
741 Some(1),
742 Some(0),
743 Some(4),
744 Some(2),
745 Some(3),
746 Some(5),
747 ]);
748 assert!(
749 keys.len() >= values.len() / 2,
750 "keys must reach unpack_dictionary"
751 );
752 keys
753 }
754
755 fn make_dict(keys: &Int32Array, values: &ArrayRef) -> DictionaryArray<Int32Type> {
756 DictionaryArray::try_new(keys.clone(), values.clone()).unwrap()
757 }
758
759 #[test]
760 fn test_dict_to_view_matches_take_then_cast() {
761 let long = "a value over twelve bytes";
762 let utf8: ArrayRef = Arc::new(StringArray::from(vec![
763 Some("aa"),
764 Some("bb"),
765 Some(long),
766 None,
767 Some("ee"),
768 Some("ff"),
769 Some("gg"),
770 Some("hh"),
771 Some("ii"),
772 Some("jj"),
773 ]));
774
775 for from in [Utf8, LargeUtf8, Binary, LargeBinary] {
776 let values = cast(&utf8, &from).unwrap();
777 for to in [Utf8View, BinaryView] {
778 for keys in [sparse_keys(&values), dense_keys(&values)] {
779 let expected = cast(&take(&values, &keys, None).unwrap(), &to).unwrap();
780 let casted = cast(&make_dict(&keys, &values), &to).unwrap();
781 assert_eq!(casted.as_ref(), expected.as_ref(), "{from:?} -> {to:?}");
782 }
783 }
784 }
785 }
786
787 #[test]
788 fn test_dict_binary_to_utf8view_invalid_utf8() {
789 let bytes: Vec<&[u8]> = vec![
790 b"aa",
791 b"bb",
792 &[0xFF, 0xFE],
793 b"dd",
794 b"ee",
795 b"ff",
796 b"gg",
797 b"hh",
798 b"ii",
799 b"jj",
800 ];
801 let strict = CastOptions {
802 safe: false,
803 ..Default::default()
804 };
805 let safe = CastOptions {
806 safe: true,
807 ..Default::default()
808 };
809
810 for values in [
811 Arc::new(BinaryArray::from_vec(bytes.clone())) as ArrayRef,
812 Arc::new(LargeBinaryArray::from_vec(bytes.clone())) as ArrayRef,
813 ] {
814 for (keys, expected) in [
816 (
817 sparse_keys(&values),
818 vec![Some("aa"), None, None, Some("dd")],
819 ),
820 (
821 dense_keys(&values),
822 vec![
823 Some("aa"),
824 None,
825 None,
826 Some("dd"),
827 Some("bb"),
828 Some("aa"),
829 Some("ee"),
830 None,
831 Some("dd"),
832 Some("ff"),
833 ],
834 ),
835 ] {
836 let dict = make_dict(&keys, &values);
837 assert!(cast_with_options(&dict, &Utf8View, &strict).is_err());
838
839 let casted = cast_with_options(&dict, &Utf8View, &safe).unwrap();
840 assert_eq!(casted.as_string_view(), &StringViewArray::from(expected));
841 }
842 }
843 }
844}