1use crate::array::print_long_array;
19use crate::iterator::FixedSizeBinaryIter;
20use crate::{Array, ArrayAccessor, ArrayRef, FixedSizeListArray, Scalar};
21use arrow_buffer::buffer::NullBuffer;
22use arrow_buffer::{ArrowNativeType, Buffer, MutableBuffer, bit_util};
23use arrow_data::{ArrayData, ArrayDataBuilder};
24use arrow_schema::{ArrowError, DataType};
25use std::any::Any;
26use std::sync::Arc;
27
28#[derive(Clone)]
53pub struct FixedSizeBinaryArray {
54 data_type: DataType, value_data: Buffer,
56 nulls: Option<NullBuffer>,
57 len: usize,
58 value_length: i32,
59}
60
61impl FixedSizeBinaryArray {
62 pub fn new(size: i32, values: Buffer, nulls: Option<NullBuffer>) -> Self {
68 Self::try_new(size, values, nulls).unwrap()
69 }
70
71 pub fn new_scalar(value: impl AsRef<[u8]>) -> Scalar<Self> {
73 let v = value.as_ref();
74 Scalar::new(Self::new(v.len() as _, Buffer::from(v), None))
75 }
76
77 pub fn try_new(
88 size: i32,
89 values: Buffer,
90 nulls: Option<NullBuffer>,
91 ) -> Result<Self, ArrowError> {
92 let data_type = DataType::FixedSizeBinary(size);
93 let s = size.to_usize().ok_or_else(|| {
94 ArrowError::InvalidArgumentError(format!("Size cannot be negative, got {size}"))
95 })?;
96
97 let len = match values.len().checked_div(s) {
98 Some(len) => {
99 if let Some(n) = nulls.as_ref() {
100 if n.len() != len {
101 return Err(ArrowError::InvalidArgumentError(format!(
102 "Incorrect length of null buffer for FixedSizeBinaryArray, expected {} got {}",
103 len,
104 n.len(),
105 )));
106 }
107 }
108
109 len
110 }
111 None => {
112 if !values.is_empty() {
113 return Err(ArrowError::InvalidArgumentError(
114 "Buffer cannot have non-zero length if the item size is zero".to_owned(),
115 ));
116 }
117
118 nulls.as_ref().map(|n| n.len()).unwrap_or(0)
120 }
121 };
122
123 Ok(Self {
124 data_type,
125 value_data: values,
126 value_length: size,
127 nulls,
128 len,
129 })
130 }
131
132 pub fn new_null(size: i32, len: usize) -> Self {
141 const BITS_IN_A_BYTE: usize = 8;
142 let capacity_in_bytes = size.to_usize().unwrap().checked_mul(len).unwrap();
143 Self {
144 data_type: DataType::FixedSizeBinary(size),
145 value_data: MutableBuffer::new_null(capacity_in_bytes * BITS_IN_A_BYTE).into(),
146 nulls: Some(NullBuffer::new_null(len)),
147 value_length: size,
148 len,
149 }
150 }
151
152 pub fn into_parts(self) -> (i32, Buffer, Option<NullBuffer>) {
154 (self.value_length, self.value_data, self.nulls)
155 }
156
157 pub fn value(&self, i: usize) -> &[u8] {
165 assert!(
166 i < self.len(),
167 "Trying to access an element at index {} from a FixedSizeBinaryArray of length {}",
168 i,
169 self.len()
170 );
171 let offset = i + self.offset();
172 unsafe {
173 let pos = self.value_offset_at(offset);
174 std::slice::from_raw_parts(
175 self.value_data.as_ptr().offset(pos as isize),
176 (self.value_offset_at(offset + 1) - pos) as usize,
177 )
178 }
179 }
180
181 pub unsafe fn value_unchecked(&self, i: usize) -> &[u8] {
191 let offset = i + self.offset();
192 let pos = self.value_offset_at(offset);
193 unsafe {
194 std::slice::from_raw_parts(
195 self.value_data.as_ptr().offset(pos as isize),
196 (self.value_offset_at(offset + 1) - pos) as usize,
197 )
198 }
199 }
200
201 #[inline]
205 pub fn value_offset(&self, i: usize) -> i32 {
206 self.value_offset_at(self.offset() + i)
207 }
208
209 #[inline]
213 pub fn value_length(&self) -> i32 {
214 self.value_length
215 }
216
217 #[inline]
222 pub fn values(&self) -> &Buffer {
223 &self.value_data
224 }
225
226 pub fn value_data(&self) -> &[u8] {
228 self.value_data.as_slice()
229 }
230
231 pub fn slice(&self, offset: usize, len: usize) -> Self {
233 assert!(
234 offset.saturating_add(len) <= self.len,
235 "the length + offset of the sliced FixedSizeBinaryArray cannot exceed the existing length"
236 );
237
238 let size = self.value_length as usize;
239
240 Self {
241 data_type: self.data_type.clone(),
242 nulls: self.nulls.as_ref().map(|n| n.slice(offset, len)),
243 value_length: self.value_length,
244 value_data: self.value_data.slice_with_length(offset * size, len * size),
245 len,
246 }
247 }
248
249 #[deprecated(
272 since = "28.0.0",
273 note = "This function will fail if the iterator produces only None values; prefer `try_from_sparse_iter_with_size`"
274 )]
275 pub fn try_from_sparse_iter<T, U>(mut iter: T) -> Result<Self, ArrowError>
276 where
277 T: Iterator<Item = Option<U>>,
278 U: AsRef<[u8]>,
279 {
280 let mut len = 0;
281 let mut size = None;
282 let mut byte = 0;
283
284 let iter_size_hint = iter.size_hint().0;
285 let mut null_buf = MutableBuffer::new(bit_util::ceil(iter_size_hint, 8));
286 let mut buffer = MutableBuffer::new(0);
287
288 let mut prepend = 0;
289 iter.try_for_each(|item| -> Result<(), ArrowError> {
290 if byte == 0 {
292 null_buf.push(0u8);
293 byte = 8;
294 }
295 byte -= 1;
296
297 if let Some(slice) = item {
298 let slice = slice.as_ref();
299 if let Some(size) = size {
300 if size != slice.len() {
301 return Err(ArrowError::InvalidArgumentError(format!(
302 "Nested array size mismatch: one is {}, and the other is {}",
303 size,
304 slice.len()
305 )));
306 }
307 } else {
308 let len = slice.len();
309 size = Some(len);
310 buffer.reserve(iter_size_hint * len);
314 buffer.extend_zeros(slice.len() * prepend);
315 }
316 bit_util::set_bit(null_buf.as_slice_mut(), len);
317 buffer.extend_from_slice(slice);
318 } else if let Some(size) = size {
319 buffer.extend_zeros(size);
320 } else {
321 prepend += 1;
322 }
323
324 len += 1;
325
326 Ok(())
327 })?;
328
329 if len == 0 {
330 return Err(ArrowError::InvalidArgumentError(
331 "Input iterable argument has no data".to_owned(),
332 ));
333 }
334
335 let nulls = NullBuffer::from_unsliced_buffer(null_buf, len);
336
337 let size = size.unwrap_or(0) as i32;
338 Ok(Self {
339 data_type: DataType::FixedSizeBinary(size),
340 value_data: buffer.into(),
341 nulls,
342 value_length: size,
343 len,
344 })
345 }
346
347 pub fn try_from_sparse_iter_with_size<T, U>(mut iter: T, size: i32) -> Result<Self, ArrowError>
372 where
373 T: Iterator<Item = Option<U>>,
374 U: AsRef<[u8]>,
375 {
376 let mut len = 0;
377 let mut byte = 0;
378
379 let iter_size_hint = iter.size_hint().0;
380 let mut null_buf = MutableBuffer::new(bit_util::ceil(iter_size_hint, 8));
381 let mut buffer = MutableBuffer::new(iter_size_hint * (size as usize));
382
383 iter.try_for_each(|item| -> Result<(), ArrowError> {
384 if byte == 0 {
386 null_buf.push(0u8);
387 byte = 8;
388 }
389 byte -= 1;
390
391 if let Some(slice) = item {
392 let slice = slice.as_ref();
393 if size as usize != slice.len() {
394 return Err(ArrowError::InvalidArgumentError(format!(
395 "Nested array size mismatch: one is {}, and the other is {}",
396 size,
397 slice.len()
398 )));
399 }
400
401 bit_util::set_bit(null_buf.as_slice_mut(), len);
402 buffer.extend_from_slice(slice);
403 } else {
404 buffer.extend_zeros(size as usize);
405 }
406
407 len += 1;
408
409 Ok(())
410 })?;
411
412 let nulls = NullBuffer::from_unsliced_buffer(null_buf, len);
413
414 Ok(Self {
415 data_type: DataType::FixedSizeBinary(size),
416 value_data: buffer.into(),
417 nulls,
418 len,
419 value_length: size,
420 })
421 }
422
423 pub fn try_from_iter<T, U>(mut iter: T) -> Result<Self, ArrowError>
441 where
442 T: Iterator<Item = U>,
443 U: AsRef<[u8]>,
444 {
445 let mut len = 0;
446 let mut size = None;
447 let iter_size_hint = iter.size_hint().0;
448 let mut buffer = MutableBuffer::new(0);
449
450 iter.try_for_each(|item| -> Result<(), ArrowError> {
451 let slice = item.as_ref();
452 if let Some(size) = size {
453 if size != slice.len() {
454 return Err(ArrowError::InvalidArgumentError(format!(
455 "Nested array size mismatch: one is {}, and the other is {}",
456 size,
457 slice.len()
458 )));
459 }
460 } else {
461 let len = slice.len();
462 size = Some(len);
463 buffer.reserve(iter_size_hint * len);
464 }
465
466 buffer.extend_from_slice(slice);
467
468 len += 1;
469
470 Ok(())
471 })?;
472
473 if len == 0 {
474 return Err(ArrowError::InvalidArgumentError(
475 "Input iterable argument has no data".to_owned(),
476 ));
477 }
478
479 let size = size.unwrap_or(0).try_into().unwrap();
480 Ok(Self {
481 data_type: DataType::FixedSizeBinary(size),
482 value_data: buffer.into(),
483 nulls: None,
484 value_length: size,
485 len,
486 })
487 }
488
489 #[inline]
490 fn value_offset_at(&self, i: usize) -> i32 {
491 self.value_length * i as i32
492 }
493
494 pub fn iter(&self) -> FixedSizeBinaryIter<'_> {
496 FixedSizeBinaryIter::new(self)
497 }
498}
499
500impl From<ArrayData> for FixedSizeBinaryArray {
501 fn from(data: ArrayData) -> Self {
502 let (data_type, len, nulls, offset, buffers, _child_data) = data.into_parts();
503
504 assert_eq!(
505 buffers.len(),
506 1,
507 "FixedSizeBinaryArray data should contain 1 buffer only (values)"
508 );
509 let value_length = match data_type {
510 DataType::FixedSizeBinary(len) => len,
511 _ => panic!("Expected data type to be FixedSizeBinary"),
512 };
513
514 let size = value_length as usize;
515 let value_data = buffers[0].slice_with_length(offset * size, len * size);
516
517 Self {
518 data_type,
519 nulls,
520 len,
521 value_data,
522 value_length,
523 }
524 }
525}
526
527impl From<FixedSizeBinaryArray> for ArrayData {
528 fn from(array: FixedSizeBinaryArray) -> Self {
529 let builder = ArrayDataBuilder::new(array.data_type)
530 .len(array.len)
531 .buffers(vec![array.value_data])
532 .nulls(array.nulls);
533
534 unsafe { builder.build_unchecked() }
535 }
536}
537
538impl From<FixedSizeListArray> for FixedSizeBinaryArray {
540 fn from(v: FixedSizeListArray) -> Self {
541 let value_len = v.value_length();
542 let v = v.into_data();
543 assert_eq!(
544 v.child_data().len(),
545 1,
546 "FixedSizeBinaryArray can only be created from list array of u8 values \
547 (i.e. FixedSizeList<PrimitiveArray<u8>>)."
548 );
549 let child_data = &v.child_data()[0];
550
551 assert_eq!(
552 child_data.child_data().len(),
553 0,
554 "FixedSizeBinaryArray can only be created from list array of u8 values \
555 (i.e. FixedSizeList<PrimitiveArray<u8>>)."
556 );
557 assert_eq!(
558 child_data.data_type(),
559 &DataType::UInt8,
560 "FixedSizeBinaryArray can only be created from FixedSizeList<u8> arrays, mismatched data types."
561 );
562 assert_eq!(
563 child_data.null_count(),
564 0,
565 "The child array cannot contain null values."
566 );
567
568 let builder = ArrayData::builder(DataType::FixedSizeBinary(value_len))
569 .len(v.len())
570 .offset(v.offset())
571 .add_buffer(child_data.buffers()[0].slice(child_data.offset()))
572 .nulls(v.nulls().cloned());
573
574 let data = unsafe { builder.build_unchecked() };
575 Self::from(data)
576 }
577}
578
579impl From<Vec<Option<&[u8]>>> for FixedSizeBinaryArray {
580 fn from(v: Vec<Option<&[u8]>>) -> Self {
581 #[allow(deprecated)]
582 Self::try_from_sparse_iter(v.into_iter()).unwrap()
583 }
584}
585
586impl From<Vec<&[u8]>> for FixedSizeBinaryArray {
587 fn from(v: Vec<&[u8]>) -> Self {
588 Self::try_from_iter(v.into_iter()).unwrap()
589 }
590}
591
592impl<const N: usize> From<Vec<&[u8; N]>> for FixedSizeBinaryArray {
593 fn from(v: Vec<&[u8; N]>) -> Self {
594 Self::try_from_iter(v.into_iter()).unwrap()
595 }
596}
597
598impl std::fmt::Debug for FixedSizeBinaryArray {
599 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
600 write!(f, "FixedSizeBinaryArray<{}>\n[\n", self.value_length())?;
601 print_long_array(self, f, |array, index, f| {
602 std::fmt::Debug::fmt(&array.value(index), f)
603 })?;
604 write!(f, "]")
605 }
606}
607
608unsafe impl Array for FixedSizeBinaryArray {
610 fn as_any(&self) -> &dyn Any {
611 self
612 }
613
614 fn to_data(&self) -> ArrayData {
615 self.clone().into()
616 }
617
618 fn into_data(self) -> ArrayData {
619 self.into()
620 }
621
622 fn data_type(&self) -> &DataType {
623 &self.data_type
624 }
625
626 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
627 Arc::new(self.slice(offset, length))
628 }
629
630 fn len(&self) -> usize {
631 self.len
632 }
633
634 fn is_empty(&self) -> bool {
635 self.len == 0
636 }
637
638 fn shrink_to_fit(&mut self) {
639 self.value_data.shrink_to_fit();
640 if let Some(nulls) = &mut self.nulls {
641 nulls.shrink_to_fit();
642 }
643 }
644
645 fn offset(&self) -> usize {
646 0
647 }
648
649 fn nulls(&self) -> Option<&NullBuffer> {
650 self.nulls.as_ref()
651 }
652
653 fn logical_null_count(&self) -> usize {
654 self.null_count()
656 }
657
658 fn get_buffer_memory_size(&self) -> usize {
659 let mut sum = self.value_data.capacity();
660 if let Some(n) = &self.nulls {
661 sum += n.buffer().capacity();
662 }
663 sum
664 }
665
666 fn get_array_memory_size(&self) -> usize {
667 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
668 }
669
670 #[cfg(feature = "pool")]
671 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
672 self.value_data.claim(pool);
673 if let Some(nulls) = &self.nulls {
674 nulls.claim(pool);
675 }
676 }
677}
678
679impl<'a> ArrayAccessor for &'a FixedSizeBinaryArray {
680 type Item = &'a [u8];
681
682 fn value(&self, index: usize) -> Self::Item {
683 FixedSizeBinaryArray::value(self, index)
684 }
685
686 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
687 unsafe { FixedSizeBinaryArray::value_unchecked(self, index) }
688 }
689}
690
691impl<'a> IntoIterator for &'a FixedSizeBinaryArray {
692 type Item = Option<&'a [u8]>;
693 type IntoIter = FixedSizeBinaryIter<'a>;
694
695 fn into_iter(self) -> Self::IntoIter {
696 FixedSizeBinaryIter::<'a>::new(self)
697 }
698}
699
700#[cfg(test)]
701mod tests {
702 use super::*;
703 use crate::RecordBatch;
704 use arrow_schema::{Field, Schema};
705
706 #[test]
707 fn test_fixed_size_binary_array() {
708 let values: [u8; 15] = *b"hellotherearrow";
709
710 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
711 .len(3)
712 .add_buffer(Buffer::from(&values))
713 .build()
714 .unwrap();
715 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
716 assert_eq!(3, fixed_size_binary_array.len());
717 assert_eq!(0, fixed_size_binary_array.null_count());
718 assert_eq!(
719 [b'h', b'e', b'l', b'l', b'o'],
720 fixed_size_binary_array.value(0)
721 );
722 assert_eq!(
723 [b't', b'h', b'e', b'r', b'e'],
724 fixed_size_binary_array.value(1)
725 );
726 assert_eq!(
727 [b'a', b'r', b'r', b'o', b'w'],
728 fixed_size_binary_array.value(2)
729 );
730 assert_eq!(5, fixed_size_binary_array.value_length());
731 assert_eq!(10, fixed_size_binary_array.value_offset(2));
732 for i in 0..3 {
733 assert!(fixed_size_binary_array.is_valid(i));
734 assert!(!fixed_size_binary_array.is_null(i));
735 }
736
737 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
739 .len(2)
740 .offset(1)
741 .add_buffer(Buffer::from(&values))
742 .build()
743 .unwrap();
744 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
745 assert_eq!(
746 [b't', b'h', b'e', b'r', b'e'],
747 fixed_size_binary_array.value(0)
748 );
749 assert_eq!(
750 [b'a', b'r', b'r', b'o', b'w'],
751 fixed_size_binary_array.value(1)
752 );
753 assert_eq!(2, fixed_size_binary_array.len());
754 assert_eq!(0, fixed_size_binary_array.value_offset(0));
755 assert_eq!(5, fixed_size_binary_array.value_length());
756 assert_eq!(5, fixed_size_binary_array.value_offset(1));
757 }
758
759 #[test]
760 fn test_fixed_size_binary_array_from_fixed_size_list_array() {
761 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
762 let values_data = ArrayData::builder(DataType::UInt8)
763 .len(12)
764 .offset(2)
765 .add_buffer(Buffer::from_slice_ref(values))
766 .build()
767 .unwrap();
768 let array_data = unsafe {
770 ArrayData::builder(DataType::FixedSizeList(
771 Arc::new(Field::new_list_field(DataType::UInt8, false)),
772 4,
773 ))
774 .len(2)
775 .offset(1)
776 .add_child_data(values_data)
777 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101])))
778 .build_unchecked()
779 };
780 let list_array = FixedSizeListArray::from(array_data);
781 let binary_array = FixedSizeBinaryArray::from(list_array);
782
783 assert_eq!(2, binary_array.len());
784 assert_eq!(1, binary_array.null_count());
785 assert!(binary_array.is_null(0));
786 assert!(binary_array.is_valid(1));
787 assert_eq!(&[10, 11, 12, 13], binary_array.value(1));
788 }
789
790 #[test]
791 #[should_panic(
792 expected = "FixedSizeBinaryArray can only be created from FixedSizeList<u8> arrays"
793 )]
794 #[cfg(not(feature = "force_validate"))]
797 fn test_fixed_size_binary_array_from_incorrect_fixed_size_list_array() {
798 let values: [u32; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
799 let values_data = ArrayData::builder(DataType::UInt32)
800 .len(12)
801 .add_buffer(Buffer::from_slice_ref(values))
802 .build()
803 .unwrap();
804
805 let array_data = unsafe {
806 ArrayData::builder(DataType::FixedSizeList(
807 Arc::new(Field::new_list_field(DataType::Binary, false)),
808 4,
809 ))
810 .len(3)
811 .add_child_data(values_data)
812 .build_unchecked()
813 };
814 let list_array = FixedSizeListArray::from(array_data);
815 drop(FixedSizeBinaryArray::from(list_array));
816 }
817
818 #[test]
819 #[should_panic(expected = "The child array cannot contain null values.")]
820 fn test_fixed_size_binary_array_from_fixed_size_list_array_with_child_nulls_failed() {
821 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
822 let values_data = ArrayData::builder(DataType::UInt8)
823 .len(12)
824 .add_buffer(Buffer::from_slice_ref(values))
825 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101010101010])))
826 .build()
827 .unwrap();
828
829 let array_data = unsafe {
830 ArrayData::builder(DataType::FixedSizeList(
831 Arc::new(Field::new_list_field(DataType::UInt8, false)),
832 4,
833 ))
834 .len(3)
835 .add_child_data(values_data)
836 .build_unchecked()
837 };
838 let list_array = FixedSizeListArray::from(array_data);
839 drop(FixedSizeBinaryArray::from(list_array));
840 }
841
842 #[test]
843 fn test_fixed_size_binary_array_fmt_debug() {
844 let values: [u8; 15] = *b"hellotherearrow";
845
846 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
847 .len(3)
848 .add_buffer(Buffer::from(&values))
849 .build()
850 .unwrap();
851 let arr = FixedSizeBinaryArray::from(array_data);
852 assert_eq!(
853 "FixedSizeBinaryArray<5>\n[\n [104, 101, 108, 108, 111],\n [116, 104, 101, 114, 101],\n [97, 114, 114, 111, 119],\n]",
854 format!("{arr:?}")
855 );
856 }
857
858 #[test]
859 fn test_fixed_size_binary_array_from_iter() {
860 let input_arg = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
861 let arr = FixedSizeBinaryArray::try_from_iter(input_arg.into_iter()).unwrap();
862
863 assert_eq!(2, arr.value_length());
864 assert_eq!(3, arr.len())
865 }
866
867 #[test]
868 fn test_all_none_fixed_size_binary_array_from_sparse_iter() {
869 let none_option: Option<[u8; 32]> = None;
870 let input_arg = vec![none_option, none_option, none_option];
871 #[allow(deprecated)]
872 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.into_iter()).unwrap();
873 assert_eq!(0, arr.value_length());
874 assert_eq!(3, arr.len())
875 }
876
877 #[test]
878 fn test_fixed_size_binary_array_from_sparse_iter() {
879 let input_arg = vec![
880 None,
881 Some(vec![7, 8]),
882 Some(vec![9, 10]),
883 None,
884 Some(vec![13, 14]),
885 ];
886 #[allow(deprecated)]
887 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.iter().cloned()).unwrap();
888 assert_eq!(2, arr.value_length());
889 assert_eq!(5, arr.len());
890
891 let arr =
892 FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 2).unwrap();
893 assert_eq!(2, arr.value_length());
894 assert_eq!(5, arr.len());
895 }
896
897 #[test]
898 fn test_fixed_size_binary_array_from_sparse_iter_with_size_all_none() {
899 let input_arg = vec![None, None, None, None, None] as Vec<Option<Vec<u8>>>;
900
901 let arr = FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 16)
902 .unwrap();
903 assert_eq!(16, arr.value_length());
904 assert_eq!(5, arr.len())
905 }
906
907 #[test]
908 fn test_fixed_size_binary_array_from_vec() {
909 let values = vec!["one".as_bytes(), b"two", b"six", b"ten"];
910 let array = FixedSizeBinaryArray::from(values);
911 assert_eq!(array.len(), 4);
912 assert_eq!(array.null_count(), 0);
913 assert_eq!(array.logical_null_count(), 0);
914 assert_eq!(array.value(0), b"one");
915 assert_eq!(array.value(1), b"two");
916 assert_eq!(array.value(2), b"six");
917 assert_eq!(array.value(3), b"ten");
918 assert!(!array.is_null(0));
919 assert!(!array.is_null(1));
920 assert!(!array.is_null(2));
921 assert!(!array.is_null(3));
922 }
923
924 #[test]
925 #[should_panic(expected = "Nested array size mismatch: one is 3, and the other is 5")]
926 fn test_fixed_size_binary_array_from_vec_incorrect_length() {
927 let values = vec!["one".as_bytes(), b"two", b"three", b"four"];
928 let _ = FixedSizeBinaryArray::from(values);
929 }
930
931 #[test]
932 fn test_fixed_size_binary_array_from_opt_vec() {
933 let values = vec![
934 Some("one".as_bytes()),
935 Some(b"two"),
936 None,
937 Some(b"six"),
938 Some(b"ten"),
939 ];
940 let array = FixedSizeBinaryArray::from(values);
941 assert_eq!(array.len(), 5);
942 assert_eq!(array.value(0), b"one");
943 assert_eq!(array.value(1), b"two");
944 assert_eq!(array.value(3), b"six");
945 assert_eq!(array.value(4), b"ten");
946 assert!(!array.is_null(0));
947 assert!(!array.is_null(1));
948 assert!(array.is_null(2));
949 assert!(!array.is_null(3));
950 assert!(!array.is_null(4));
951 }
952
953 #[test]
954 #[should_panic(expected = "Nested array size mismatch: one is 3, and the other is 5")]
955 fn test_fixed_size_binary_array_from_opt_vec_incorrect_length() {
956 let values = vec![
957 Some("one".as_bytes()),
958 Some(b"two"),
959 None,
960 Some(b"three"),
961 Some(b"four"),
962 ];
963 let _ = FixedSizeBinaryArray::from(values);
964 }
965
966 #[test]
967 fn fixed_size_binary_array_all_null() {
968 let data = vec![None] as Vec<Option<String>>;
969 let array =
970 FixedSizeBinaryArray::try_from_sparse_iter_with_size(data.into_iter(), 0).unwrap();
971 array
972 .into_data()
973 .validate_full()
974 .expect("All null array has valid array data");
975 }
976
977 #[test]
978 fn fixed_size_binary_array_all_null_in_batch_with_schema() {
980 let schema = Schema::new(vec![Field::new("a", DataType::FixedSizeBinary(2), true)]);
981
982 let none_option: Option<[u8; 2]> = None;
983 let item = FixedSizeBinaryArray::try_from_sparse_iter_with_size(
984 vec![none_option, none_option, none_option].into_iter(),
985 2,
986 )
987 .unwrap();
988
989 RecordBatch::try_new(Arc::new(schema), vec![Arc::new(item)]).unwrap();
991 }
992
993 #[test]
994 #[should_panic(
995 expected = "Trying to access an element at index 4 from a FixedSizeBinaryArray of length 3"
996 )]
997 fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
998 let values = vec![Some("one".as_bytes()), Some(b"two"), None];
999 let array = FixedSizeBinaryArray::from(values);
1000
1001 array.value(4);
1002 }
1003
1004 #[test]
1005 fn test_constructors() {
1006 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1007 let a = FixedSizeBinaryArray::new(2, buffer.clone(), None);
1008 assert_eq!(a.len(), 5);
1009
1010 let nulls = NullBuffer::new_null(5);
1011 FixedSizeBinaryArray::new(2, buffer.clone(), Some(nulls));
1012
1013 let null_array = FixedSizeBinaryArray::new_null(4, 3);
1014 assert_eq!(null_array.len(), 3);
1015 assert_eq!(null_array.values().len(), 12);
1016
1017 let a = FixedSizeBinaryArray::new(3, buffer.clone(), None);
1018 assert_eq!(a.len(), 3);
1019
1020 let nulls = NullBuffer::new_null(3);
1021 FixedSizeBinaryArray::new(3, buffer.clone(), Some(nulls));
1022
1023 let err = FixedSizeBinaryArray::try_new(-1, buffer.clone(), None).unwrap_err();
1024
1025 assert_eq!(
1026 err.to_string(),
1027 "Invalid argument error: Size cannot be negative, got -1"
1028 );
1029
1030 let nulls = NullBuffer::new_null(3);
1031 let err = FixedSizeBinaryArray::try_new(2, buffer.clone(), Some(nulls)).unwrap_err();
1032 assert_eq!(
1033 err.to_string(),
1034 "Invalid argument error: Incorrect length of null buffer for FixedSizeBinaryArray, expected 5 got 3"
1035 );
1036
1037 let zero_sized = FixedSizeBinaryArray::new(0, Buffer::default(), None);
1038 assert_eq!(zero_sized.len(), 0);
1039 assert_eq!(zero_sized.null_count(), 0);
1040 assert_eq!(zero_sized.values().len(), 0);
1041
1042 let nulls = NullBuffer::new_null(3);
1043 let zero_sized_with_nulls = FixedSizeBinaryArray::new(0, Buffer::default(), Some(nulls));
1044 assert_eq!(zero_sized_with_nulls.len(), 3);
1045 assert_eq!(zero_sized_with_nulls.null_count(), 3);
1046 assert_eq!(zero_sized_with_nulls.values().len(), 0);
1047
1048 let zero_sized_with_non_empty_buffer_err =
1049 FixedSizeBinaryArray::try_new(0, buffer, None).unwrap_err();
1050 assert_eq!(
1051 zero_sized_with_non_empty_buffer_err.to_string(),
1052 "Invalid argument error: Buffer cannot have non-zero length if the item size is zero"
1053 );
1054 }
1055}