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