1use crate::types::{ByteArrayType, GenericBinaryType};
19use crate::{Array, GenericByteArray, GenericListArray, GenericStringArray, OffsetSizeTrait};
20use arrow_data::ArrayData;
21use arrow_schema::DataType;
22
23pub type GenericBinaryArray<OffsetSize> = GenericByteArray<GenericBinaryType<OffsetSize>>;
25
26impl<OffsetSize: OffsetSizeTrait> GenericBinaryArray<OffsetSize> {
27 pub fn from_vec(v: Vec<&[u8]>) -> Self {
31 Self::from_iter_values(v)
32 }
33
34 pub fn from_opt_vec(v: Vec<Option<&[u8]>>) -> Self {
36 v.into_iter().collect()
37 }
38
39 fn from_list(v: GenericListArray<OffsetSize>) -> Self {
40 let v = v.into_data();
41 assert_eq!(
42 v.child_data().len(),
43 1,
44 "BinaryArray can only be created from list array of u8 values \
45 (i.e. List<PrimitiveArray<u8>>)."
46 );
47 let child_data = &v.child_data()[0];
48
49 assert_eq!(
50 child_data.child_data().len(),
51 0,
52 "BinaryArray can only be created from list array of u8 values \
53 (i.e. List<PrimitiveArray<u8>>)."
54 );
55 assert_eq!(
56 child_data.data_type(),
57 &DataType::UInt8,
58 "BinaryArray can only be created from List<u8> arrays, mismatched data types."
59 );
60 assert_eq!(
61 child_data.null_count(),
62 0,
63 "The child array cannot contain null values."
64 );
65
66 let builder = ArrayData::builder(Self::DATA_TYPE)
67 .len(v.len())
68 .offset(v.offset())
69 .add_buffer(v.buffers()[0].clone())
70 .add_buffer(child_data.buffers()[0].slice(child_data.offset()))
71 .nulls(v.nulls().cloned());
72
73 let data = unsafe { builder.build_unchecked() };
74 Self::from(data)
75 }
76
77 pub fn take_iter<'a>(
79 &'a self,
80 indexes: impl Iterator<Item = Option<usize>> + 'a,
81 ) -> impl Iterator<Item = Option<&'a [u8]>> {
82 indexes.map(|opt_index| opt_index.map(|index| self.value(index)))
83 }
84
85 pub unsafe fn take_iter_unchecked<'a>(
90 &'a self,
91 indexes: impl Iterator<Item = Option<usize>> + 'a,
92 ) -> impl Iterator<Item = Option<&'a [u8]>> {
93 unsafe { indexes.map(|opt_index| opt_index.map(|index| self.value_unchecked(index))) }
94 }
95}
96
97impl<OffsetSize: OffsetSizeTrait> From<Vec<Option<&[u8]>>> for GenericBinaryArray<OffsetSize> {
98 fn from(v: Vec<Option<&[u8]>>) -> Self {
99 Self::from_opt_vec(v)
100 }
101}
102
103impl<OffsetSize: OffsetSizeTrait> From<Vec<&[u8]>> for GenericBinaryArray<OffsetSize> {
104 fn from(v: Vec<&[u8]>) -> Self {
105 Self::from_iter_values(v)
106 }
107}
108
109impl<T: OffsetSizeTrait> From<GenericListArray<T>> for GenericBinaryArray<T> {
110 fn from(v: GenericListArray<T>) -> Self {
111 Self::from_list(v)
112 }
113}
114
115impl<OffsetSize: OffsetSizeTrait> From<GenericStringArray<OffsetSize>>
116 for GenericBinaryArray<OffsetSize>
117{
118 fn from(value: GenericStringArray<OffsetSize>) -> Self {
119 let builder = value
120 .into_data()
121 .into_builder()
122 .data_type(GenericBinaryType::<OffsetSize>::DATA_TYPE);
123
124 Self::from(unsafe { builder.build_unchecked() })
127 }
128}
129
130pub type BinaryArray = GenericBinaryArray<i32>;
171
172pub type LargeBinaryArray = GenericBinaryArray<i64>;
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215 use crate::{ListArray, StringArray};
216 use arrow_buffer::Buffer;
217 use arrow_schema::Field;
218 use std::sync::Arc;
219
220 #[test]
221 fn test_binary_array() {
222 let values = b"helloparquet";
223 let offsets: [i32; 4] = [0, 5, 5, 12];
224
225 let array_data = ArrayData::builder(DataType::Binary)
227 .len(3)
228 .add_buffer(Buffer::from_slice_ref(offsets))
229 .add_buffer(Buffer::from_slice_ref(values))
230 .build()
231 .unwrap();
232 let binary_array = BinaryArray::from(array_data);
233 assert_eq!(3, binary_array.len());
234 assert_eq!(0, binary_array.null_count());
235 assert_eq!([b'h', b'e', b'l', b'l', b'o'], binary_array.value(0));
236 assert_eq!([b'h', b'e', b'l', b'l', b'o'], unsafe {
237 binary_array.value_unchecked(0)
238 });
239 assert_eq!([] as [u8; 0], binary_array.value(1));
240 assert_eq!([] as [u8; 0], unsafe { binary_array.value_unchecked(1) });
241 assert_eq!(
242 [b'p', b'a', b'r', b'q', b'u', b'e', b't'],
243 binary_array.value(2)
244 );
245 assert_eq!([b'p', b'a', b'r', b'q', b'u', b'e', b't'], unsafe {
246 binary_array.value_unchecked(2)
247 });
248 assert_eq!(5, binary_array.value_offsets()[2]);
249 assert_eq!(7, binary_array.value_length(2));
250 for i in 0..3 {
251 assert!(binary_array.is_valid(i));
252 assert!(!binary_array.is_null(i));
253 }
254 }
255
256 #[test]
257 fn test_binary_array_with_offsets() {
258 let values = b"helloparquet";
259 let offsets: [i32; 4] = [0, 5, 5, 12];
260
261 let array_data = ArrayData::builder(DataType::Binary)
263 .len(2)
264 .offset(1)
265 .add_buffer(Buffer::from_slice_ref(offsets))
266 .add_buffer(Buffer::from_slice_ref(values))
267 .build()
268 .unwrap();
269 let binary_array = BinaryArray::from(array_data);
270 assert_eq!(
271 [b'p', b'a', b'r', b'q', b'u', b'e', b't'],
272 binary_array.value(1)
273 );
274 assert_eq!(5, binary_array.value_offsets()[0]);
275 assert_eq!(0, binary_array.value_length(0));
276 assert_eq!(5, binary_array.value_offsets()[1]);
277 assert_eq!(7, binary_array.value_length(1));
278 }
279
280 #[test]
281 fn test_large_binary_array() {
282 let values = b"helloparquet";
283 let offsets: [i64; 4] = [0, 5, 5, 12];
284
285 let array_data = ArrayData::builder(DataType::LargeBinary)
287 .len(3)
288 .add_buffer(Buffer::from_slice_ref(offsets))
289 .add_buffer(Buffer::from_slice_ref(values))
290 .build()
291 .unwrap();
292 let binary_array = LargeBinaryArray::from(array_data);
293 assert_eq!(3, binary_array.len());
294 assert_eq!(0, binary_array.null_count());
295 assert_eq!([b'h', b'e', b'l', b'l', b'o'], binary_array.value(0));
296 assert_eq!([b'h', b'e', b'l', b'l', b'o'], unsafe {
297 binary_array.value_unchecked(0)
298 });
299 assert_eq!([] as [u8; 0], binary_array.value(1));
300 assert_eq!([] as [u8; 0], unsafe { binary_array.value_unchecked(1) });
301 assert_eq!(
302 [b'p', b'a', b'r', b'q', b'u', b'e', b't'],
303 binary_array.value(2)
304 );
305 assert_eq!([b'p', b'a', b'r', b'q', b'u', b'e', b't'], unsafe {
306 binary_array.value_unchecked(2)
307 });
308 assert_eq!(5, binary_array.value_offsets()[2]);
309 assert_eq!(7, binary_array.value_length(2));
310 for i in 0..3 {
311 assert!(binary_array.is_valid(i));
312 assert!(!binary_array.is_null(i));
313 }
314 }
315
316 #[test]
317 fn test_large_binary_array_with_offsets() {
318 let values = b"helloparquet";
319 let offsets: [i64; 4] = [0, 5, 5, 12];
320
321 let array_data = ArrayData::builder(DataType::LargeBinary)
323 .len(2)
324 .offset(1)
325 .add_buffer(Buffer::from_slice_ref(offsets))
326 .add_buffer(Buffer::from_slice_ref(values))
327 .build()
328 .unwrap();
329 let binary_array = LargeBinaryArray::from(array_data);
330 assert_eq!(
331 [b'p', b'a', b'r', b'q', b'u', b'e', b't'],
332 binary_array.value(1)
333 );
334 assert_eq!([b'p', b'a', b'r', b'q', b'u', b'e', b't'], unsafe {
335 binary_array.value_unchecked(1)
336 });
337 assert_eq!(5, binary_array.value_offsets()[0]);
338 assert_eq!(0, binary_array.value_length(0));
339 assert_eq!(5, binary_array.value_offsets()[1]);
340 assert_eq!(7, binary_array.value_length(1));
341 }
342
343 fn _test_generic_binary_array_from_list_array<O: OffsetSizeTrait>() {
344 let values = b"helloparquet";
345 let child_data = ArrayData::builder(DataType::UInt8)
346 .len(12)
347 .add_buffer(Buffer::from(values))
348 .build()
349 .unwrap();
350 let offsets = [0, 5, 5, 12].map(|n| O::from_usize(n).unwrap());
351
352 let array_data1 = ArrayData::builder(GenericBinaryArray::<O>::DATA_TYPE)
354 .len(3)
355 .add_buffer(Buffer::from_slice_ref(offsets))
356 .add_buffer(Buffer::from_slice_ref(values))
357 .build()
358 .unwrap();
359 let binary_array1 = GenericBinaryArray::<O>::from(array_data1);
360
361 let data_type = GenericListArray::<O>::DATA_TYPE_CONSTRUCTOR(Arc::new(
362 Field::new_list_field(DataType::UInt8, false),
363 ));
364
365 let array_data2 = ArrayData::builder(data_type)
366 .len(3)
367 .add_buffer(Buffer::from_slice_ref(offsets))
368 .add_child_data(child_data)
369 .build()
370 .unwrap();
371 let list_array = GenericListArray::<O>::from(array_data2);
372 let binary_array2 = GenericBinaryArray::<O>::from(list_array);
373
374 assert_eq!(binary_array1.len(), binary_array2.len());
375 assert_eq!(binary_array1.null_count(), binary_array2.null_count());
376 assert_eq!(binary_array1.value_offsets(), binary_array2.value_offsets());
377 for i in 0..binary_array1.len() {
378 assert_eq!(binary_array1.value(i), binary_array2.value(i));
379 assert_eq!(binary_array1.value(i), unsafe {
380 binary_array2.value_unchecked(i)
381 });
382 assert_eq!(binary_array1.value_length(i), binary_array2.value_length(i));
383 }
384 }
385
386 #[test]
387 fn test_binary_array_from_list_array() {
388 _test_generic_binary_array_from_list_array::<i32>();
389 }
390
391 #[test]
392 fn test_large_binary_array_from_list_array() {
393 _test_generic_binary_array_from_list_array::<i64>();
394 }
395
396 fn _test_generic_binary_array_from_list_array_with_offset<O: OffsetSizeTrait>() {
397 let values = b"HelloArrowAndParquet";
398 let child_data = ArrayData::builder(DataType::UInt8)
400 .len(15)
401 .offset(5)
402 .add_buffer(Buffer::from(values))
403 .build()
404 .unwrap();
405
406 let offsets = [0, 5, 8, 15].map(|n| O::from_usize(n).unwrap());
407 let null_buffer = Buffer::from_slice_ref([0b101]);
408 let data_type = GenericListArray::<O>::DATA_TYPE_CONSTRUCTOR(Arc::new(
409 Field::new_list_field(DataType::UInt8, false),
410 ));
411
412 let array_data = ArrayData::builder(data_type)
414 .len(2)
415 .offset(1)
416 .add_buffer(Buffer::from_slice_ref(offsets))
417 .null_bit_buffer(Some(null_buffer))
418 .add_child_data(child_data)
419 .build()
420 .unwrap();
421 let list_array = GenericListArray::<O>::from(array_data);
422 let binary_array = GenericBinaryArray::<O>::from(list_array);
423
424 assert_eq!(2, binary_array.len());
425 assert_eq!(1, binary_array.null_count());
426 assert!(binary_array.is_null(0));
427 assert!(binary_array.is_valid(1));
428 assert_eq!(b"Parquet", binary_array.value(1));
429 }
430
431 #[test]
432 fn test_binary_array_from_list_array_with_offset() {
433 _test_generic_binary_array_from_list_array_with_offset::<i32>();
434 }
435
436 #[test]
437 fn test_large_binary_array_from_list_array_with_offset() {
438 _test_generic_binary_array_from_list_array_with_offset::<i64>();
439 }
440
441 fn _test_generic_binary_array_from_list_array_with_child_nulls_failed<O: OffsetSizeTrait>() {
442 let values = b"HelloArrow";
443 let child_data = ArrayData::builder(DataType::UInt8)
444 .len(10)
445 .add_buffer(Buffer::from(values))
446 .null_bit_buffer(Some(Buffer::from_slice_ref([0b1010101010])))
447 .build()
448 .unwrap();
449
450 let offsets = [0, 5, 10].map(|n| O::from_usize(n).unwrap());
451 let data_type = GenericListArray::<O>::DATA_TYPE_CONSTRUCTOR(Arc::new(
452 Field::new_list_field(DataType::UInt8, true),
453 ));
454
455 let array_data = ArrayData::builder(data_type)
457 .len(2)
458 .add_buffer(Buffer::from_slice_ref(offsets))
459 .add_child_data(child_data)
460 .build()
461 .unwrap();
462 let list_array = GenericListArray::<O>::from(array_data);
463 drop(GenericBinaryArray::<O>::from(list_array));
464 }
465
466 #[test]
467 #[should_panic(expected = "The child array cannot contain null values.")]
468 fn test_binary_array_from_list_array_with_child_nulls_failed() {
469 _test_generic_binary_array_from_list_array_with_child_nulls_failed::<i32>();
470 }
471
472 #[test]
473 #[should_panic(expected = "The child array cannot contain null values.")]
474 fn test_large_binary_array_from_list_array_with_child_nulls_failed() {
475 _test_generic_binary_array_from_list_array_with_child_nulls_failed::<i64>();
476 }
477
478 fn test_generic_binary_array_from_opt_vec<T: OffsetSizeTrait>() {
479 let values: Vec<Option<&[u8]>> =
480 vec![Some(b"one"), Some(b"two"), None, Some(b""), Some(b"three")];
481 let array = GenericBinaryArray::<T>::from_opt_vec(values);
482 assert_eq!(array.len(), 5);
483 assert_eq!(array.value(0), b"one");
484 assert_eq!(array.value(1), b"two");
485 assert_eq!(array.value(3), b"");
486 assert_eq!(array.value(4), b"three");
487 assert!(!array.is_null(0));
488 assert!(!array.is_null(1));
489 assert!(array.is_null(2));
490 assert!(!array.is_null(3));
491 assert!(!array.is_null(4));
492 }
493
494 #[test]
495 fn test_large_binary_array_from_opt_vec() {
496 test_generic_binary_array_from_opt_vec::<i64>()
497 }
498
499 #[test]
500 fn test_binary_array_from_opt_vec() {
501 test_generic_binary_array_from_opt_vec::<i32>()
502 }
503
504 #[test]
505 fn test_binary_array_from_unbound_iter() {
506 let value_iter = (0..)
508 .scan(0usize, |pos, i| {
509 if *pos < 10 {
510 *pos += 1;
511 Some(Some(format!("value {i}")))
512 } else {
513 None
515 }
516 })
517 .take(100);
519
520 let (_, upper_size_bound) = value_iter.size_hint();
521 assert_eq!(upper_size_bound, Some(100));
523 let binary_array: BinaryArray = value_iter.collect();
524 assert_eq!(binary_array.len(), 10);
526 }
527
528 #[test]
529 #[should_panic(
530 expected = "BinaryArray can only be created from List<u8> arrays, mismatched data types."
531 )]
532 fn test_binary_array_from_incorrect_list_array() {
533 let values: [u32; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
534 let values_data = ArrayData::builder(DataType::UInt32)
535 .len(12)
536 .add_buffer(Buffer::from_slice_ref(values))
537 .build()
538 .unwrap();
539 let offsets: [i32; 4] = [0, 5, 5, 12];
540
541 let data_type = DataType::List(Arc::new(Field::new_list_field(DataType::UInt32, false)));
542 let array_data = ArrayData::builder(data_type)
543 .len(3)
544 .add_buffer(Buffer::from_slice_ref(offsets))
545 .add_child_data(values_data)
546 .build()
547 .unwrap();
548 let list_array = ListArray::from(array_data);
549 drop(BinaryArray::from(list_array));
550 }
551
552 #[test]
553 #[should_panic(
554 expected = "Trying to access an element at index 4 from a BinaryArray of length 3"
555 )]
556 fn test_binary_array_get_value_index_out_of_bound() {
557 let values: [u8; 12] = [104, 101, 108, 108, 111, 112, 97, 114, 113, 117, 101, 116];
558 let offsets: [i32; 4] = [0, 5, 5, 12];
559 let array_data = ArrayData::builder(DataType::Binary)
560 .len(3)
561 .add_buffer(Buffer::from_slice_ref(offsets))
562 .add_buffer(Buffer::from_slice_ref(values))
563 .build()
564 .unwrap();
565 let binary_array = BinaryArray::from(array_data);
566 binary_array.value(4);
567 }
568
569 #[test]
570 #[should_panic(expected = "LargeBinaryArray expects DataType::LargeBinary")]
571 fn test_binary_array_validation() {
572 let array = BinaryArray::from_iter_values([&[1, 2]]);
573 let _ = LargeBinaryArray::from(array.into_data());
574 }
575
576 #[test]
577 fn test_binary_array_all_null() {
578 let data = vec![None];
579 let array = BinaryArray::from(data);
580 array
581 .into_data()
582 .validate_full()
583 .expect("All null array has valid array data");
584 }
585
586 #[test]
587 fn test_large_binary_array_all_null() {
588 let data = vec![None];
589 let array = LargeBinaryArray::from(data);
590 array
591 .into_data()
592 .validate_full()
593 .expect("All null array has valid array data");
594 }
595
596 #[test]
597 fn test_empty_offsets() {
598 let string = BinaryArray::from(
599 ArrayData::builder(DataType::Binary)
600 .buffers(vec![Buffer::from(&[]), Buffer::from(&[])])
601 .build()
602 .unwrap(),
603 );
604 assert_eq!(string.value_offsets(), &[0]);
605 let string = LargeBinaryArray::from(
606 ArrayData::builder(DataType::LargeBinary)
607 .buffers(vec![Buffer::from(&[]), Buffer::from(&[])])
608 .build()
609 .unwrap(),
610 );
611 assert_eq!(string.len(), 0);
612 assert_eq!(string.value_offsets(), &[0]);
613 }
614
615 #[test]
616 fn test_to_from_string() {
617 let s = StringArray::from_iter_values(["a", "b", "c", "d"]);
618 let b = BinaryArray::from(s.clone());
619 let sa = StringArray::from(b); assert_eq!(s, sa);
622 }
623}