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