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)]
90pub struct FixedSizeBinaryArray {
91 data_type: DataType,
93 value_data: Buffer,
95 nulls: Option<NullBuffer>,
97 len: usize,
99 value_size: usize,
108}
109
110impl FixedSizeBinaryArray {
111 pub fn new(value_length: i32, values: Buffer, nulls: Option<NullBuffer>) -> Self {
118 Self::try_new(value_length, values, nulls).unwrap()
119 }
120
121 pub unsafe fn new_unchecked(
128 value_length: i32,
129 values: Buffer,
130 nulls: Option<NullBuffer>,
131 len: usize,
132 ) -> Self {
133 if cfg!(feature = "force_validate") {
134 return Self::try_new_with_len(value_length, values, nulls, len).unwrap();
135 }
136 Self {
137 data_type: DataType::FixedSizeBinary(value_length),
138 value_data: values,
139 value_size: value_length as usize,
140 nulls,
141 len,
142 }
143 }
144
145 pub fn new_scalar(value: impl AsRef<[u8]>) -> Scalar<Self> {
150 let v = value.as_ref();
151 let value_length =
152 i32::try_from(v.len()).expect("FixedSizeBinaryArray value length exceeds i32");
153 Scalar::new(Self::new(value_length, Buffer::from(v), None))
154 }
155
156 pub fn try_new(
168 value_length: i32,
169 values: Buffer,
170 nulls: Option<NullBuffer>,
171 ) -> Result<Self, ArrowError> {
172 let value_size = value_length.to_usize().ok_or_else(|| {
173 ArrowError::InvalidArgumentError(format!(
174 "Value length cannot be negative, got {value_length}"
175 ))
176 })?;
177
178 let len = match values.len().checked_div(value_size) {
179 Some(len) => {
180 if let Some(n) = nulls.as_ref()
181 && n.len() != len
182 {
183 return Err(ArrowError::InvalidArgumentError(format!(
184 "Incorrect length of null buffer for FixedSizeBinaryArray, expected {} got {}",
185 len,
186 n.len(),
187 )));
188 }
189
190 len
191 }
192 None => {
193 if !values.is_empty() {
194 return Err(ArrowError::InvalidArgumentError(
195 "Buffer cannot have non-zero length if the value length is zero".to_owned(),
196 ));
197 }
198
199 nulls.as_ref().map(|n| n.len()).unwrap_or(0)
201 }
202 };
203
204 Self::try_new_with_len(value_length, values, nulls, len)
205 }
206
207 pub fn try_new_with_len(
219 value_length: i32,
220 values: Buffer,
221 nulls: Option<NullBuffer>,
222 len: usize,
223 ) -> Result<Self, ArrowError> {
224 let data_type = DataType::FixedSizeBinary(value_length);
225 let value_size = value_length.to_usize().ok_or_else(|| {
226 ArrowError::InvalidArgumentError(format!(
227 "Value length cannot be negative, got {value_length}"
228 ))
229 })?;
230
231 if let Some(nulls) = &nulls
232 && nulls.len() != len
233 {
234 return Err(ArrowError::InvalidArgumentError(format!(
235 "Incorrect length of null buffer for FixedSizeBinaryArray, expected {} got {}",
236 len,
237 nulls.len(),
238 )));
239 }
240
241 if value_size != 0 && values.len() / value_size != len {
242 return Err(ArrowError::InvalidArgumentError(format!(
243 "Incorrect length of values buffer for FixedSizeBinaryArray, expected {} got {}",
244 len,
245 values.len() / value_size,
246 )));
247 }
248
249 if value_size == 0 && !values.is_empty() {
250 return Err(ArrowError::InvalidArgumentError(
251 "Buffer cannot have non-zero length if the value length is zero".to_owned(),
252 ));
253 }
254
255 Ok(Self {
256 data_type,
257 value_data: values,
258 value_size,
259 nulls,
260 len,
261 })
262 }
263
264 pub fn new_null(value_length: i32, len: usize) -> Self {
274 const BITS_IN_A_BYTE: usize = 8;
275 let value_size = value_length.to_usize().unwrap();
276 let capacity_in_bytes = value_size.checked_mul(len).unwrap();
277 let capacity_in_bits = capacity_in_bytes.checked_mul(BITS_IN_A_BYTE).unwrap();
278 Self {
279 data_type: DataType::FixedSizeBinary(value_length),
280 value_data: MutableBuffer::new_null(capacity_in_bits).into(),
281 nulls: Some(NullBuffer::new_null(len)),
282 value_size,
283 len,
284 }
285 }
286
287 pub fn into_parts(self) -> (i32, Buffer, Option<NullBuffer>) {
289 let value_length = self.value_length();
290 (value_length, self.value_data, self.nulls)
291 }
292
293 pub fn value(&self, i: usize) -> &[u8] {
301 let len = self.len();
302 assert!(
303 i < len,
304 "Trying to access an element at index {i} from a FixedSizeBinaryArray of length {len}",
305 );
306 let position = i * self.value_size;
307 unsafe {
308 std::slice::from_raw_parts(self.value_data.as_ptr().add(position), self.value_size)
309 }
310 }
311
312 pub unsafe fn value_unchecked(&self, i: usize) -> &[u8] {
322 let position = i * self.value_size;
323 unsafe {
324 std::slice::from_raw_parts(self.value_data.as_ptr().add(position), self.value_size)
325 }
326 }
327
328 #[deprecated(since = "59.0.0", note = "Use i * value_size() instead")]
336 #[inline]
337 pub fn value_offset(&self, i: usize) -> i32 {
338 self.value_length() * i as i32
339 }
340
341 #[inline]
349 pub fn value_length(&self) -> i32 {
350 self.value_size as i32
352 }
353
354 #[inline]
360 pub fn value_size(&self) -> usize {
361 self.value_size
362 }
363
364 #[inline]
369 pub fn values(&self) -> &Buffer {
370 &self.value_data
371 }
372
373 pub fn value_data(&self) -> &[u8] {
375 self.value_data.as_slice()
376 }
377
378 pub fn slice(&self, offset: usize, len: usize) -> Self {
383 assert!(
384 offset.saturating_add(len) <= self.len,
385 "the length + offset of the sliced FixedSizeBinaryArray cannot exceed the existing length"
386 );
387 let offset_bytes = offset
388 .checked_mul(self.value_size)
389 .expect("offset overflow");
390 let len_bytes = len.checked_mul(self.value_size).expect("offset overflow");
391
392 Self {
393 data_type: self.data_type.clone(),
394 nulls: self.nulls.as_ref().map(|n| n.slice(offset, len)),
395 value_size: self.value_size,
396 value_data: self.value_data.slice_with_length(offset_bytes, len_bytes),
397 len,
398 }
399 }
400
401 #[deprecated(
424 since = "28.0.0",
425 note = "This function will fail if the iterator produces only None values; prefer `try_from_sparse_iter_with_size`"
426 )]
427 pub fn try_from_sparse_iter<T, U>(mut iter: T) -> Result<Self, ArrowError>
428 where
429 T: Iterator<Item = Option<U>>,
430 U: AsRef<[u8]>,
431 {
432 let mut len = 0;
433 let mut value_size = None;
434 let mut byte = 0;
435
436 let iter_size_hint = iter.size_hint().0;
437 let mut null_buf = MutableBuffer::new(bit_util::ceil(iter_size_hint, 8));
438 let mut buffer = MutableBuffer::new(0);
439
440 let mut prepend = 0;
441 iter.try_for_each(|item| -> Result<(), ArrowError> {
442 if byte == 0 {
444 null_buf.push(0u8);
445 byte = 8;
446 }
447 byte -= 1;
448
449 if let Some(slice) = item {
450 let slice = slice.as_ref();
451 if let Some(size) = value_size {
452 if size != slice.len() {
453 return Err(ArrowError::InvalidArgumentError(format!(
454 "Nested array size mismatch: one is {}, and the other is {}",
455 size,
456 slice.len()
457 )));
458 }
459 } else {
460 let len = slice.len();
461 value_size = Some(len);
462 if let Some(capacity) = iter_size_hint.checked_mul(len) {
466 buffer
467 .try_reserve(capacity)
468 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
469 }
470 let prepend_zeros = slice.len().checked_mul(prepend).ok_or_else(|| {
471 ArrowError::InvalidArgumentError(format!(
472 "FixedSizeBinaryArray error: value size {} * prepend {prepend} exceeds usize",
473 slice.len()
474 ))
475 })?;
476 buffer
477 .try_extend_zeros(prepend_zeros)
478 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
479 }
480 bit_util::set_bit(null_buf.as_slice_mut(), len);
481 buffer
482 .try_extend_from_slice(slice)
483 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
484 } else if let Some(size) = value_size {
485 buffer
486 .try_extend_zeros(size)
487 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
488 } else {
489 prepend += 1;
490 }
491
492 len += 1;
493
494 Ok(())
495 })?;
496
497 if len == 0 {
498 return Err(ArrowError::InvalidArgumentError(
499 "Input iterable argument has no data".to_owned(),
500 ));
501 }
502
503 let nulls = NullBuffer::from_unsliced_buffer(null_buf, len);
504
505 let value_size = value_size.unwrap_or(0);
506 let value_length = value_size.try_into().map_err(|_| {
507 ArrowError::InvalidArgumentError(format!(
508 "FixedSizeBinaryArray value length exceeds i32, got {value_size}"
509 ))
510 })?;
511 Ok(Self {
512 data_type: DataType::FixedSizeBinary(value_length),
513 value_data: buffer.into(),
514 nulls,
515 value_size,
516 len,
517 })
518 }
519
520 pub fn try_from_sparse_iter_with_size<T, U>(
545 mut iter: T,
546 value_length: i32,
547 ) -> Result<Self, ArrowError>
548 where
549 T: Iterator<Item = Option<U>>,
550 U: AsRef<[u8]>,
551 {
552 let value_size = value_length.to_usize().ok_or_else(|| {
553 ArrowError::InvalidArgumentError(format!(
554 "Value length cannot be negative, got {value_length}"
555 ))
556 })?;
557 let mut len = 0;
558 let mut byte = 0;
559
560 let iter_size_hint = iter.size_hint().0;
561 let mut null_buf = MutableBuffer::new(bit_util::ceil(iter_size_hint, 8));
562 let capacity = iter_size_hint.checked_mul(value_size).ok_or_else(|| {
563 ArrowError::InvalidArgumentError(format!(
564 "FixedSizeBinaryArray error: value size {value_size} * len hint {iter_size_hint} exceeds usize"
565 ))
566 })?;
567 let mut buffer = MutableBuffer::new(capacity);
568
569 iter.try_for_each(|item| -> Result<(), ArrowError> {
570 if byte == 0 {
572 null_buf.push(0u8);
573 byte = 8;
574 }
575 byte -= 1;
576
577 if let Some(slice) = item {
578 let slice = slice.as_ref();
579 if value_size != slice.len() {
580 return Err(ArrowError::InvalidArgumentError(format!(
581 "Nested array size mismatch: one is {}, and the other is {}",
582 value_length,
583 slice.len()
584 )));
585 }
586
587 bit_util::set_bit(null_buf.as_slice_mut(), len);
588 buffer.extend_from_slice(slice);
589 } else {
590 buffer.extend_zeros(value_size);
591 }
592
593 len += 1;
594
595 Ok(())
596 })?;
597
598 let nulls = NullBuffer::from_unsliced_buffer(null_buf, len);
599
600 Ok(Self {
601 data_type: DataType::FixedSizeBinary(value_length),
602 value_data: buffer.into(),
603 nulls,
604 len,
605 value_size,
606 })
607 }
608
609 pub fn try_from_iter<T, U>(mut iter: T) -> Result<Self, ArrowError>
627 where
628 T: Iterator<Item = U>,
629 U: AsRef<[u8]>,
630 {
631 let mut len = 0;
632 let mut value_size = None;
633 let iter_size_hint = iter.size_hint().0;
634 let mut buffer = MutableBuffer::new(0);
635
636 iter.try_for_each(|item| -> Result<(), ArrowError> {
637 let slice = item.as_ref();
638 if let Some(value_size) = value_size {
639 if value_size != slice.len() {
640 return Err(ArrowError::InvalidArgumentError(format!(
641 "Nested array size mismatch: one is {value_size}, and the other is {}",
642 slice.len()
643 )));
644 }
645 } else {
646 let len = slice.len();
647 value_size = Some(len);
648 if let Some(capacity) = iter_size_hint.checked_mul(len) {
649 buffer
650 .try_reserve(capacity)
651 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
652 }
653 }
654
655 buffer
656 .try_extend_from_slice(slice)
657 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
658
659 len += 1;
660
661 Ok(())
662 })?;
663
664 if len == 0 {
665 return Err(ArrowError::InvalidArgumentError(
666 "Input iterable argument has no data".to_owned(),
667 ));
668 }
669
670 let value_size = value_size.unwrap_or(0);
671 let value_length = value_size.try_into().map_err(|_| {
672 ArrowError::InvalidArgumentError(format!(
673 "FixedSizeBinaryArray value length exceeds i32, got {value_size}"
674 ))
675 })?;
676 Ok(Self {
677 data_type: DataType::FixedSizeBinary(value_length),
678 value_data: buffer.into(),
679 nulls: None,
680 value_size,
681 len,
682 })
683 }
684
685 pub fn iter(&self) -> FixedSizeBinaryIter<'_> {
687 FixedSizeBinaryIter::new(self)
688 }
689}
690
691impl From<ArrayData> for FixedSizeBinaryArray {
692 fn from(data: ArrayData) -> Self {
693 let (data_type, len, nulls, offset, buffers, _child_data) = data.into_parts();
694
695 assert_eq!(
696 buffers.len(),
697 1,
698 "FixedSizeBinaryArray data should contain 1 buffer only (values)"
699 );
700 let DataType::FixedSizeBinary(value_length) = data_type else {
701 panic!("Expected data type to be FixedSizeBinary")
702 };
703
704 let value_size = value_length
705 .to_usize()
706 .expect("FixedSizeBinaryArray value length must be non-negative");
707 let value_data = buffers[0].slice_with_length(
708 offset.checked_mul(value_size).expect("offset overflow"),
709 len.checked_mul(value_size).expect("length overflow"),
710 );
711
712 Self {
713 data_type,
714 value_data,
715 nulls,
716 len,
717 value_size,
718 }
719 }
720}
721
722impl From<FixedSizeBinaryArray> for ArrayData {
723 fn from(array: FixedSizeBinaryArray) -> Self {
724 let builder = ArrayDataBuilder::new(array.data_type)
725 .len(array.len)
726 .buffers(vec![array.value_data])
727 .nulls(array.nulls);
728
729 unsafe { builder.build_unchecked() }
730 }
731}
732
733impl From<FixedSizeListArray> for FixedSizeBinaryArray {
735 fn from(v: FixedSizeListArray) -> Self {
736 let value_len = v.value_length();
737 let v = v.into_data();
738 assert_eq!(
739 v.child_data().len(),
740 1,
741 "FixedSizeBinaryArray can only be created from list array of u8 values \
742 (i.e. FixedSizeList<PrimitiveArray<u8>>)."
743 );
744 let child_data = &v.child_data()[0];
745
746 assert_eq!(
747 child_data.child_data().len(),
748 0,
749 "FixedSizeBinaryArray can only be created from list array of u8 values \
750 (i.e. FixedSizeList<PrimitiveArray<u8>>)."
751 );
752 assert_eq!(
753 child_data.data_type(),
754 &DataType::UInt8,
755 "FixedSizeBinaryArray can only be created from FixedSizeList<u8> arrays, mismatched data types."
756 );
757 assert_eq!(
758 child_data.null_count(),
759 0,
760 "The child array cannot contain null values."
761 );
762
763 let builder = ArrayData::builder(DataType::FixedSizeBinary(value_len))
764 .len(v.len())
765 .offset(v.offset())
766 .add_buffer(child_data.buffers()[0].slice(child_data.offset()))
767 .nulls(v.nulls().cloned());
768
769 let data = unsafe { builder.build_unchecked() };
770 Self::from(data)
771 }
772}
773
774impl TryFrom<Vec<Option<&[u8]>>> for FixedSizeBinaryArray {
775 type Error = ArrowError;
776
777 fn try_from(v: Vec<Option<&[u8]>>) -> Result<Self, Self::Error> {
778 #[expect(deprecated)]
779 Self::try_from_sparse_iter(v.into_iter())
780 }
781}
782
783impl TryFrom<Vec<&[u8]>> for FixedSizeBinaryArray {
784 type Error = ArrowError;
785
786 fn try_from(v: Vec<&[u8]>) -> Result<Self, Self::Error> {
787 Self::try_from_iter(v.into_iter())
788 }
789}
790
791impl<const N: usize> TryFrom<Vec<Option<&[u8; N]>>> for FixedSizeBinaryArray {
792 type Error = ArrowError;
793
794 fn try_from(v: Vec<Option<&[u8; N]>>) -> Result<Self, Self::Error> {
795 let size = N.try_into().map_err(|_| {
796 ArrowError::InvalidArgumentError(format!(
797 "FixedSizeBinaryArray value length exceeds i32, got {N}"
798 ))
799 })?;
800 Self::try_from_sparse_iter_with_size(v.into_iter(), size)
801 }
802}
803
804impl<const N: usize> TryFrom<Vec<&[u8; N]>> for FixedSizeBinaryArray {
805 type Error = ArrowError;
806
807 fn try_from(v: Vec<&[u8; N]>) -> Result<Self, Self::Error> {
808 Self::try_from_iter(v.into_iter())
809 }
810}
811
812impl std::fmt::Debug for FixedSizeBinaryArray {
813 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
814 write!(f, "FixedSizeBinaryArray<{}>\n[\n", self.value_length())?;
815 print_long_array(self, f, &mut |index, f| {
816 std::fmt::Debug::fmt(&self.value(index), f)
817 })?;
818 write!(f, "]")
819 }
820}
821
822unsafe impl Array for FixedSizeBinaryArray {
824 fn as_any(&self) -> &dyn Any {
825 self
826 }
827
828 fn to_data(&self) -> ArrayData {
829 self.clone().into()
830 }
831
832 fn into_data(self) -> ArrayData {
833 self.into()
834 }
835
836 fn data_type(&self) -> &DataType {
837 &self.data_type
838 }
839
840 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
841 Arc::new(self.slice(offset, length))
842 }
843
844 fn len(&self) -> usize {
845 self.len
846 }
847
848 fn is_empty(&self) -> bool {
849 self.len == 0
850 }
851
852 fn shrink_to_fit(&mut self) {
853 self.value_data.shrink_to_fit();
854 if let Some(nulls) = &mut self.nulls {
855 nulls.shrink_to_fit();
856 }
857 }
858
859 fn offset(&self) -> usize {
860 0
863 }
864
865 fn nulls(&self) -> Option<&NullBuffer> {
866 self.nulls.as_ref()
867 }
868
869 fn logical_null_count(&self) -> usize {
870 self.null_count()
872 }
873
874 fn get_buffer_memory_size(&self) -> usize {
875 let mut sum = self.value_data.capacity();
876 if let Some(n) = &self.nulls {
877 sum += n.buffer().capacity();
878 }
879 sum
880 }
881
882 fn get_array_memory_size(&self) -> usize {
883 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
884 }
885
886 #[cfg(feature = "pool")]
887 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
888 self.value_data.claim(pool);
889 if let Some(nulls) = &self.nulls {
890 nulls.claim(pool);
891 }
892 }
893}
894
895impl<'a> ArrayAccessor for &'a FixedSizeBinaryArray {
896 type Item = &'a [u8];
897
898 fn value(&self, index: usize) -> Self::Item {
899 FixedSizeBinaryArray::value(self, index)
900 }
901
902 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
903 unsafe { FixedSizeBinaryArray::value_unchecked(self, index) }
904 }
905}
906
907impl<'a> IntoIterator for &'a FixedSizeBinaryArray {
908 type Item = Option<&'a [u8]>;
909 type IntoIter = FixedSizeBinaryIter<'a>;
910
911 fn into_iter(self) -> Self::IntoIter {
912 FixedSizeBinaryIter::<'a>::new(self)
913 }
914}
915
916#[cfg(test)]
917mod tests {
918 use super::*;
919 use crate::RecordBatch;
920 use arrow_schema::{Field, Schema};
921
922 #[test]
923 fn test_fixed_size_binary_array() {
924 let values = b"hellotherearrow";
925
926 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
927 .len(3)
928 .add_buffer(Buffer::from(values))
929 .build()
930 .unwrap();
931 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
932 assert_eq!(3, fixed_size_binary_array.len());
933 assert_eq!(0, fixed_size_binary_array.null_count());
934 assert_eq!(
935 [b'h', b'e', b'l', b'l', b'o'],
936 fixed_size_binary_array.value(0)
937 );
938 assert_eq!(
939 [b't', b'h', b'e', b'r', b'e'],
940 fixed_size_binary_array.value(1)
941 );
942 assert_eq!(
943 [b'a', b'r', b'r', b'o', b'w'],
944 fixed_size_binary_array.value(2)
945 );
946 assert_eq!(5, fixed_size_binary_array.value_length());
947 for i in 0..3 {
948 assert!(fixed_size_binary_array.is_valid(i));
949 assert!(!fixed_size_binary_array.is_null(i));
950 }
951
952 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
954 .len(2)
955 .offset(1)
956 .add_buffer(Buffer::from(values))
957 .build()
958 .unwrap();
959 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
960 assert_eq!(
961 [b't', b'h', b'e', b'r', b'e'],
962 fixed_size_binary_array.value(0)
963 );
964 assert_eq!(
965 [b'a', b'r', b'r', b'o', b'w'],
966 fixed_size_binary_array.value(1)
967 );
968 assert_eq!(2, fixed_size_binary_array.len());
969 assert_eq!(5, fixed_size_binary_array.value_length());
970 }
971
972 #[test]
973 fn test_fixed_size_binary_array_from_fixed_size_list_array() {
974 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
975 let values_data = ArrayData::builder(DataType::UInt8)
976 .len(12)
977 .offset(2)
978 .add_buffer(Buffer::from_slice_ref(values))
979 .build()
980 .unwrap();
981 let array_data = unsafe {
983 ArrayData::builder(DataType::FixedSizeList(
984 Arc::new(Field::new_list_field(DataType::UInt8, false)),
985 4,
986 ))
987 .len(2)
988 .offset(1)
989 .add_child_data(values_data)
990 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101])))
991 .build_unchecked()
992 };
993 let list_array = FixedSizeListArray::from(array_data);
994 let binary_array = FixedSizeBinaryArray::from(list_array);
995
996 assert_eq!(2, binary_array.len());
997 assert_eq!(1, binary_array.null_count());
998 assert!(binary_array.is_null(0));
999 assert!(binary_array.is_valid(1));
1000 assert_eq!(&[10, 11, 12, 13], binary_array.value(1));
1001 }
1002
1003 #[test]
1004 #[should_panic(
1005 expected = "FixedSizeBinaryArray can only be created from FixedSizeList<u8> arrays"
1006 )]
1007 #[cfg(not(feature = "force_validate"))]
1010 fn test_fixed_size_binary_array_from_incorrect_fixed_size_list_array() {
1011 let values: [u32; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
1012 let values_data = ArrayData::builder(DataType::UInt32)
1013 .len(12)
1014 .add_buffer(Buffer::from_slice_ref(values))
1015 .build()
1016 .unwrap();
1017
1018 let array_data = unsafe {
1019 ArrayData::builder(DataType::FixedSizeList(
1020 Arc::new(Field::new_list_field(DataType::Binary, false)),
1021 4,
1022 ))
1023 .len(3)
1024 .add_child_data(values_data)
1025 .build_unchecked()
1026 };
1027 let list_array = FixedSizeListArray::from(array_data);
1028 drop(FixedSizeBinaryArray::from(list_array));
1029 }
1030
1031 #[test]
1032 #[cfg(not(feature = "force_validate"))]
1035 #[should_panic(expected = "The child array cannot contain null values.")]
1036 fn test_fixed_size_binary_array_from_fixed_size_list_array_with_child_nulls_failed() {
1037 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
1038 let values_data = ArrayData::builder(DataType::UInt8)
1039 .len(12)
1040 .add_buffer(Buffer::from_slice_ref(values))
1041 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101010101010])))
1042 .build()
1043 .unwrap();
1044
1045 let array_data = unsafe {
1046 ArrayData::builder(DataType::FixedSizeList(
1047 Arc::new(Field::new_list_field(DataType::UInt8, false)),
1048 4,
1049 ))
1050 .len(3)
1051 .add_child_data(values_data)
1052 .build_unchecked()
1053 };
1054 let list_array = FixedSizeListArray::from(array_data);
1055 drop(FixedSizeBinaryArray::from(list_array));
1056 }
1057
1058 #[test]
1059 fn test_fixed_size_binary_array_fmt_debug() {
1060 let values = b"hellotherearrow";
1061
1062 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
1063 .len(3)
1064 .add_buffer(Buffer::from(values))
1065 .build()
1066 .unwrap();
1067 let arr = FixedSizeBinaryArray::from(array_data);
1068 assert_eq!(
1069 "FixedSizeBinaryArray<5>\n[\n [104, 101, 108, 108, 111],\n [116, 104, 101, 114, 101],\n [97, 114, 114, 111, 119],\n]",
1070 format!("{arr:?}")
1071 );
1072 }
1073
1074 #[test]
1075 fn test_fixed_size_binary_array_from_iter() {
1076 let input_arg = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
1077 let arr = FixedSizeBinaryArray::try_from_iter(input_arg.into_iter()).unwrap();
1078
1079 assert_eq!(2, arr.value_length());
1080 assert_eq!(3, arr.len())
1081 }
1082
1083 #[test]
1084 fn test_all_none_fixed_size_binary_array_from_sparse_iter() {
1085 let none_option: Option<[u8; 32]> = None;
1086 let input_arg = vec![none_option, none_option, none_option];
1087 #[expect(deprecated)]
1088 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.into_iter()).unwrap();
1089 assert_eq!(0, arr.value_length());
1090 assert_eq!(3, arr.len())
1091 }
1092
1093 #[test]
1094 fn test_fixed_size_binary_array_from_sparse_iter() {
1095 let input_arg = vec![
1096 None,
1097 Some(vec![7, 8]),
1098 Some(vec![9, 10]),
1099 None,
1100 Some(vec![13, 14]),
1101 ];
1102 #[expect(deprecated)]
1103 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.iter().cloned()).unwrap();
1104 assert_eq!(2, arr.value_length());
1105 assert_eq!(5, arr.len());
1106
1107 let arr =
1108 FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 2).unwrap();
1109 assert_eq!(2, arr.value_length());
1110 assert_eq!(5, arr.len());
1111 }
1112
1113 #[test]
1114 fn test_fixed_size_binary_array_from_sparse_iter_with_size_all_none() {
1115 let input_arg = vec![None, None, None, None, None] as Vec<Option<Vec<u8>>>;
1116
1117 let arr = FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 16)
1118 .unwrap();
1119 assert_eq!(16, arr.value_length());
1120 assert_eq!(5, arr.len())
1121 }
1122
1123 #[test]
1124 fn test_fixed_size_binary_array_from_vec() {
1125 let values = vec![b"one".as_slice(), b"two", b"six", b"ten"];
1126 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1127 assert_eq!(array.len(), 4);
1128 assert_eq!(array.null_count(), 0);
1129 assert_eq!(array.logical_null_count(), 0);
1130 assert_eq!(array.value(0), b"one");
1131 assert_eq!(array.value(1), b"two");
1132 assert_eq!(array.value(2), b"six");
1133 assert_eq!(array.value(3), b"ten");
1134 assert!(!array.is_null(0));
1135 assert!(!array.is_null(1));
1136 assert!(!array.is_null(2));
1137 assert!(!array.is_null(3));
1138 }
1139
1140 #[test]
1141 fn test_fixed_size_binary_array_from_vec_incorrect_length() {
1142 let values = vec![b"one".as_slice(), b"two", b"three", b"four"];
1143 assert!(FixedSizeBinaryArray::try_from(values).is_err());
1144 }
1145
1146 #[test]
1147 fn test_fixed_size_binary_array_from_opt_vec() {
1148 let values = vec![
1149 Some(b"one".as_slice()),
1150 Some(b"two"),
1151 None,
1152 Some(b"six"),
1153 Some(b"ten"),
1154 ];
1155 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1156 assert_eq!(array.len(), 5);
1157 assert_eq!(array.value(0), b"one");
1158 assert_eq!(array.value(1), b"two");
1159 assert_eq!(array.value(3), b"six");
1160 assert_eq!(array.value(4), b"ten");
1161 assert!(!array.is_null(0));
1162 assert!(!array.is_null(1));
1163 assert!(array.is_null(2));
1164 assert!(!array.is_null(3));
1165 assert!(!array.is_null(4));
1166 }
1167
1168 #[test]
1169 fn test_fixed_size_binary_array_from_opt_vec_incorrect_length() {
1170 let values = vec![
1171 Some(b"one".as_slice()),
1172 Some(b"two"),
1173 None,
1174 Some(b"three"),
1175 Some(b"four"),
1176 ];
1177 assert!(FixedSizeBinaryArray::try_from(values).is_err());
1178 }
1179
1180 #[test]
1181 fn fixed_size_binary_array_all_null() {
1182 let data = vec![None] as Vec<Option<String>>;
1183 let array =
1184 FixedSizeBinaryArray::try_from_sparse_iter_with_size(data.into_iter(), 0).unwrap();
1185 array
1186 .into_data()
1187 .validate_full()
1188 .expect("All null array has valid array data");
1189 }
1190
1191 #[test]
1192 fn fixed_size_binary_array_all_null_in_batch_with_schema() {
1194 let schema = Schema::new(vec![Field::new("a", DataType::FixedSizeBinary(2), true)]);
1195
1196 let none_option: Option<[u8; 2]> = None;
1197 let item = FixedSizeBinaryArray::try_from_sparse_iter_with_size(
1198 vec![none_option, none_option, none_option].into_iter(),
1199 2,
1200 )
1201 .unwrap();
1202
1203 RecordBatch::try_new(Arc::new(schema), vec![Arc::new(item)]).unwrap();
1205 }
1206
1207 #[test]
1208 #[should_panic(
1209 expected = "Trying to access an element at index 4 from a FixedSizeBinaryArray of length 3"
1210 )]
1211 fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
1212 let values = vec![Some(b"one".as_slice()), Some(b"two"), None];
1213 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1214
1215 array.value(4);
1216 }
1217
1218 #[test]
1219 fn test_constructors() {
1220 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1221 let a = FixedSizeBinaryArray::new(2, buffer.clone(), None);
1222 assert_eq!(a.len(), 5);
1223
1224 let nulls = NullBuffer::new_null(5);
1225 FixedSizeBinaryArray::new(2, buffer.clone(), Some(nulls));
1226
1227 let null_array = FixedSizeBinaryArray::new_null(4, 3);
1228 assert_eq!(null_array.len(), 3);
1229 assert_eq!(null_array.values().len(), 12);
1230
1231 let a = FixedSizeBinaryArray::new(3, buffer.clone(), None);
1232 assert_eq!(a.len(), 3);
1233
1234 let nulls = NullBuffer::new_null(3);
1235 FixedSizeBinaryArray::new(3, buffer.clone(), Some(nulls));
1236
1237 let err = FixedSizeBinaryArray::try_new(-1, buffer.clone(), None).unwrap_err();
1238
1239 assert_eq!(
1240 err.to_string(),
1241 "Invalid argument error: Value length cannot be negative, got -1"
1242 );
1243
1244 let nulls = NullBuffer::new_null(3);
1245 let err = FixedSizeBinaryArray::try_new(2, buffer.clone(), Some(nulls)).unwrap_err();
1246 assert_eq!(
1247 err.to_string(),
1248 "Invalid argument error: Incorrect length of null buffer for FixedSizeBinaryArray, expected 5 got 3"
1249 );
1250
1251 let zero_sized = FixedSizeBinaryArray::new(0, Buffer::default(), None);
1252 assert_eq!(zero_sized.len(), 0);
1253 assert_eq!(zero_sized.null_count(), 0);
1254 assert_eq!(zero_sized.values().len(), 0);
1255
1256 let nulls = NullBuffer::new_null(3);
1257 let zero_sized_with_nulls = FixedSizeBinaryArray::new(0, Buffer::default(), Some(nulls));
1258 assert_eq!(zero_sized_with_nulls.len(), 3);
1259 assert_eq!(zero_sized_with_nulls.null_count(), 3);
1260 assert_eq!(zero_sized_with_nulls.values().len(), 0);
1261
1262 let zero_sized_with_non_empty_buffer_err =
1263 FixedSizeBinaryArray::try_new(0, buffer, None).unwrap_err();
1264 assert_eq!(
1265 zero_sized_with_non_empty_buffer_err.to_string(),
1266 "Invalid argument error: Buffer cannot have non-zero length if the value length is zero"
1267 );
1268 }
1269
1270 #[test]
1271 fn test_try_new_with_len() {
1272 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1273
1274 let a = FixedSizeBinaryArray::try_new_with_len(2, buffer.clone(), None, 5).unwrap();
1275 assert_eq!(a.len(), 5);
1276
1277 let nulls = NullBuffer::new_null(5);
1278 let a = FixedSizeBinaryArray::try_new_with_len(2, buffer, Some(nulls), 5).unwrap();
1279 assert_eq!(a.len(), 5);
1280 assert_eq!(a.null_count(), 5);
1281
1282 let a = FixedSizeBinaryArray::try_new_with_len(2, Buffer::default(), None, 0).unwrap();
1283 assert_eq!(a.len(), 0);
1284 }
1285
1286 #[test]
1287 fn test_try_new_with_len_zero_width() {
1288 let a = FixedSizeBinaryArray::try_new_with_len(0, Buffer::default(), None, 5).unwrap();
1290 assert_eq!(a.len(), 5);
1291 assert_eq!(a.null_count(), 0);
1292 assert_eq!(a.values().len(), 0);
1293
1294 let nulls = NullBuffer::new_null(3);
1295 let a =
1296 FixedSizeBinaryArray::try_new_with_len(0, Buffer::default(), Some(nulls), 3).unwrap();
1297 assert_eq!(a.len(), 3);
1298 assert_eq!(a.null_count(), 3);
1299 }
1300
1301 #[test]
1302 fn test_try_new_with_len_negative_value_length() {
1303 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1304 let err = FixedSizeBinaryArray::try_new_with_len(-1, buffer, None, 5).unwrap_err();
1305 assert_eq!(
1306 err.to_string(),
1307 "Invalid argument error: Value length cannot be negative, got -1"
1308 );
1309 }
1310
1311 #[test]
1312 fn test_try_new_with_len_incorrect_null_buffer_length() {
1313 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1314 let nulls = NullBuffer::new_null(3);
1315 let err = FixedSizeBinaryArray::try_new_with_len(2, buffer, Some(nulls), 5).unwrap_err();
1316 assert_eq!(
1317 err.to_string(),
1318 "Invalid argument error: Incorrect length of null buffer for FixedSizeBinaryArray, expected 5 got 3"
1319 );
1320 }
1321
1322 #[test]
1323 fn test_try_new_with_len_incorrect_values_buffer_length() {
1324 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1325 let err = FixedSizeBinaryArray::try_new_with_len(2, buffer, None, 3).unwrap_err();
1326 assert_eq!(
1327 err.to_string(),
1328 "Invalid argument error: Incorrect length of values buffer for FixedSizeBinaryArray, expected 3 got 5"
1329 );
1330 }
1331
1332 #[test]
1333 fn test_try_new_with_len_zero_width_non_empty_buffer() {
1334 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1335 let err = FixedSizeBinaryArray::try_new_with_len(0, buffer, None, 5).unwrap_err();
1336 assert_eq!(
1337 err.to_string(),
1338 "Invalid argument error: Buffer cannot have non-zero length if the value length is zero"
1339 );
1340 }
1341}