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 value_length = match data_type {
701 DataType::FixedSizeBinary(len) => len,
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 N.try_into()
797 .map_err(|_| {
798 ArrowError::InvalidArgumentError(format!(
799 "FixedSizeBinaryArray value length exceeds i32, got {N}"
800 ))
801 })
802 .and_then(|x| Self::try_from_sparse_iter_with_size(v.into_iter(), x))
803 }
804}
805
806impl<const N: usize> TryFrom<Vec<&[u8; N]>> for FixedSizeBinaryArray {
807 type Error = ArrowError;
808
809 fn try_from(v: Vec<&[u8; N]>) -> Result<Self, Self::Error> {
810 Self::try_from_iter(v.into_iter())
811 }
812}
813
814impl std::fmt::Debug for FixedSizeBinaryArray {
815 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
816 write!(f, "FixedSizeBinaryArray<{}>\n[\n", self.value_length())?;
817 print_long_array(self, f, |array, index, f| {
818 std::fmt::Debug::fmt(&array.value(index), f)
819 })?;
820 write!(f, "]")
821 }
822}
823
824unsafe impl Array for FixedSizeBinaryArray {
826 fn as_any(&self) -> &dyn Any {
827 self
828 }
829
830 fn to_data(&self) -> ArrayData {
831 self.clone().into()
832 }
833
834 fn into_data(self) -> ArrayData {
835 self.into()
836 }
837
838 fn data_type(&self) -> &DataType {
839 &self.data_type
840 }
841
842 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
843 Arc::new(self.slice(offset, length))
844 }
845
846 fn len(&self) -> usize {
847 self.len
848 }
849
850 fn is_empty(&self) -> bool {
851 self.len == 0
852 }
853
854 fn shrink_to_fit(&mut self) {
855 self.value_data.shrink_to_fit();
856 if let Some(nulls) = &mut self.nulls {
857 nulls.shrink_to_fit();
858 }
859 }
860
861 fn offset(&self) -> usize {
862 0
865 }
866
867 fn nulls(&self) -> Option<&NullBuffer> {
868 self.nulls.as_ref()
869 }
870
871 fn logical_null_count(&self) -> usize {
872 self.null_count()
874 }
875
876 fn get_buffer_memory_size(&self) -> usize {
877 let mut sum = self.value_data.capacity();
878 if let Some(n) = &self.nulls {
879 sum += n.buffer().capacity();
880 }
881 sum
882 }
883
884 fn get_array_memory_size(&self) -> usize {
885 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
886 }
887
888 #[cfg(feature = "pool")]
889 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
890 self.value_data.claim(pool);
891 if let Some(nulls) = &self.nulls {
892 nulls.claim(pool);
893 }
894 }
895}
896
897impl<'a> ArrayAccessor for &'a FixedSizeBinaryArray {
898 type Item = &'a [u8];
899
900 fn value(&self, index: usize) -> Self::Item {
901 FixedSizeBinaryArray::value(self, index)
902 }
903
904 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
905 unsafe { FixedSizeBinaryArray::value_unchecked(self, index) }
906 }
907}
908
909impl<'a> IntoIterator for &'a FixedSizeBinaryArray {
910 type Item = Option<&'a [u8]>;
911 type IntoIter = FixedSizeBinaryIter<'a>;
912
913 fn into_iter(self) -> Self::IntoIter {
914 FixedSizeBinaryIter::<'a>::new(self)
915 }
916}
917
918#[cfg(test)]
919mod tests {
920 use super::*;
921 use crate::RecordBatch;
922 use arrow_schema::{Field, Schema};
923
924 #[test]
925 fn test_fixed_size_binary_array() {
926 let values = b"hellotherearrow";
927
928 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
929 .len(3)
930 .add_buffer(Buffer::from(values))
931 .build()
932 .unwrap();
933 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
934 assert_eq!(3, fixed_size_binary_array.len());
935 assert_eq!(0, fixed_size_binary_array.null_count());
936 assert_eq!(
937 [b'h', b'e', b'l', b'l', b'o'],
938 fixed_size_binary_array.value(0)
939 );
940 assert_eq!(
941 [b't', b'h', b'e', b'r', b'e'],
942 fixed_size_binary_array.value(1)
943 );
944 assert_eq!(
945 [b'a', b'r', b'r', b'o', b'w'],
946 fixed_size_binary_array.value(2)
947 );
948 assert_eq!(5, fixed_size_binary_array.value_length());
949 for i in 0..3 {
950 assert!(fixed_size_binary_array.is_valid(i));
951 assert!(!fixed_size_binary_array.is_null(i));
952 }
953
954 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
956 .len(2)
957 .offset(1)
958 .add_buffer(Buffer::from(values))
959 .build()
960 .unwrap();
961 let fixed_size_binary_array = FixedSizeBinaryArray::from(array_data);
962 assert_eq!(
963 [b't', b'h', b'e', b'r', b'e'],
964 fixed_size_binary_array.value(0)
965 );
966 assert_eq!(
967 [b'a', b'r', b'r', b'o', b'w'],
968 fixed_size_binary_array.value(1)
969 );
970 assert_eq!(2, fixed_size_binary_array.len());
971 assert_eq!(5, fixed_size_binary_array.value_length());
972 }
973
974 #[test]
975 fn test_fixed_size_binary_array_from_fixed_size_list_array() {
976 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
977 let values_data = ArrayData::builder(DataType::UInt8)
978 .len(12)
979 .offset(2)
980 .add_buffer(Buffer::from_slice_ref(values))
981 .build()
982 .unwrap();
983 let array_data = unsafe {
985 ArrayData::builder(DataType::FixedSizeList(
986 Arc::new(Field::new_list_field(DataType::UInt8, false)),
987 4,
988 ))
989 .len(2)
990 .offset(1)
991 .add_child_data(values_data)
992 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101])))
993 .build_unchecked()
994 };
995 let list_array = FixedSizeListArray::from(array_data);
996 let binary_array = FixedSizeBinaryArray::from(list_array);
997
998 assert_eq!(2, binary_array.len());
999 assert_eq!(1, binary_array.null_count());
1000 assert!(binary_array.is_null(0));
1001 assert!(binary_array.is_valid(1));
1002 assert_eq!(&[10, 11, 12, 13], binary_array.value(1));
1003 }
1004
1005 #[test]
1006 #[should_panic(
1007 expected = "FixedSizeBinaryArray can only be created from FixedSizeList<u8> arrays"
1008 )]
1009 #[cfg(not(feature = "force_validate"))]
1012 fn test_fixed_size_binary_array_from_incorrect_fixed_size_list_array() {
1013 let values: [u32; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
1014 let values_data = ArrayData::builder(DataType::UInt32)
1015 .len(12)
1016 .add_buffer(Buffer::from_slice_ref(values))
1017 .build()
1018 .unwrap();
1019
1020 let array_data = unsafe {
1021 ArrayData::builder(DataType::FixedSizeList(
1022 Arc::new(Field::new_list_field(DataType::Binary, false)),
1023 4,
1024 ))
1025 .len(3)
1026 .add_child_data(values_data)
1027 .build_unchecked()
1028 };
1029 let list_array = FixedSizeListArray::from(array_data);
1030 drop(FixedSizeBinaryArray::from(list_array));
1031 }
1032
1033 #[test]
1034 #[should_panic(expected = "The child array cannot contain null values.")]
1035 fn test_fixed_size_binary_array_from_fixed_size_list_array_with_child_nulls_failed() {
1036 let values = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
1037 let values_data = ArrayData::builder(DataType::UInt8)
1038 .len(12)
1039 .add_buffer(Buffer::from_slice_ref(values))
1040 .null_bit_buffer(Some(Buffer::from_slice_ref([0b101010101010])))
1041 .build()
1042 .unwrap();
1043
1044 let array_data = unsafe {
1045 ArrayData::builder(DataType::FixedSizeList(
1046 Arc::new(Field::new_list_field(DataType::UInt8, false)),
1047 4,
1048 ))
1049 .len(3)
1050 .add_child_data(values_data)
1051 .build_unchecked()
1052 };
1053 let list_array = FixedSizeListArray::from(array_data);
1054 drop(FixedSizeBinaryArray::from(list_array));
1055 }
1056
1057 #[test]
1058 fn test_fixed_size_binary_array_fmt_debug() {
1059 let values = b"hellotherearrow";
1060
1061 let array_data = ArrayData::builder(DataType::FixedSizeBinary(5))
1062 .len(3)
1063 .add_buffer(Buffer::from(values))
1064 .build()
1065 .unwrap();
1066 let arr = FixedSizeBinaryArray::from(array_data);
1067 assert_eq!(
1068 "FixedSizeBinaryArray<5>\n[\n [104, 101, 108, 108, 111],\n [116, 104, 101, 114, 101],\n [97, 114, 114, 111, 119],\n]",
1069 format!("{arr:?}")
1070 );
1071 }
1072
1073 #[test]
1074 fn test_fixed_size_binary_array_from_iter() {
1075 let input_arg = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
1076 let arr = FixedSizeBinaryArray::try_from_iter(input_arg.into_iter()).unwrap();
1077
1078 assert_eq!(2, arr.value_length());
1079 assert_eq!(3, arr.len())
1080 }
1081
1082 #[test]
1083 fn test_all_none_fixed_size_binary_array_from_sparse_iter() {
1084 let none_option: Option<[u8; 32]> = None;
1085 let input_arg = vec![none_option, none_option, none_option];
1086 #[expect(deprecated)]
1087 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.into_iter()).unwrap();
1088 assert_eq!(0, arr.value_length());
1089 assert_eq!(3, arr.len())
1090 }
1091
1092 #[test]
1093 fn test_fixed_size_binary_array_from_sparse_iter() {
1094 let input_arg = vec![
1095 None,
1096 Some(vec![7, 8]),
1097 Some(vec![9, 10]),
1098 None,
1099 Some(vec![13, 14]),
1100 ];
1101 #[expect(deprecated)]
1102 let arr = FixedSizeBinaryArray::try_from_sparse_iter(input_arg.iter().cloned()).unwrap();
1103 assert_eq!(2, arr.value_length());
1104 assert_eq!(5, arr.len());
1105
1106 let arr =
1107 FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 2).unwrap();
1108 assert_eq!(2, arr.value_length());
1109 assert_eq!(5, arr.len());
1110 }
1111
1112 #[test]
1113 fn test_fixed_size_binary_array_from_sparse_iter_with_size_all_none() {
1114 let input_arg = vec![None, None, None, None, None] as Vec<Option<Vec<u8>>>;
1115
1116 let arr = FixedSizeBinaryArray::try_from_sparse_iter_with_size(input_arg.into_iter(), 16)
1117 .unwrap();
1118 assert_eq!(16, arr.value_length());
1119 assert_eq!(5, arr.len())
1120 }
1121
1122 #[test]
1123 fn test_fixed_size_binary_array_from_vec() {
1124 let values = vec!["one".as_bytes(), b"two", b"six", b"ten"];
1125 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1126 assert_eq!(array.len(), 4);
1127 assert_eq!(array.null_count(), 0);
1128 assert_eq!(array.logical_null_count(), 0);
1129 assert_eq!(array.value(0), b"one");
1130 assert_eq!(array.value(1), b"two");
1131 assert_eq!(array.value(2), b"six");
1132 assert_eq!(array.value(3), b"ten");
1133 assert!(!array.is_null(0));
1134 assert!(!array.is_null(1));
1135 assert!(!array.is_null(2));
1136 assert!(!array.is_null(3));
1137 }
1138
1139 #[test]
1140 fn test_fixed_size_binary_array_from_vec_incorrect_length() {
1141 let values = vec!["one".as_bytes(), b"two", b"three", b"four"];
1142 assert!(FixedSizeBinaryArray::try_from(values).is_err());
1143 }
1144
1145 #[test]
1146 fn test_fixed_size_binary_array_from_opt_vec() {
1147 let values = vec![
1148 Some("one".as_bytes()),
1149 Some(b"two"),
1150 None,
1151 Some(b"six"),
1152 Some(b"ten"),
1153 ];
1154 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1155 assert_eq!(array.len(), 5);
1156 assert_eq!(array.value(0), b"one");
1157 assert_eq!(array.value(1), b"two");
1158 assert_eq!(array.value(3), b"six");
1159 assert_eq!(array.value(4), b"ten");
1160 assert!(!array.is_null(0));
1161 assert!(!array.is_null(1));
1162 assert!(array.is_null(2));
1163 assert!(!array.is_null(3));
1164 assert!(!array.is_null(4));
1165 }
1166
1167 #[test]
1168 fn test_fixed_size_binary_array_from_opt_vec_incorrect_length() {
1169 let values = vec![
1170 Some("one".as_bytes()),
1171 Some(b"two"),
1172 None,
1173 Some(b"three"),
1174 Some(b"four"),
1175 ];
1176 assert!(FixedSizeBinaryArray::try_from(values).is_err());
1177 }
1178
1179 #[test]
1180 fn fixed_size_binary_array_all_null() {
1181 let data = vec![None] as Vec<Option<String>>;
1182 let array =
1183 FixedSizeBinaryArray::try_from_sparse_iter_with_size(data.into_iter(), 0).unwrap();
1184 array
1185 .into_data()
1186 .validate_full()
1187 .expect("All null array has valid array data");
1188 }
1189
1190 #[test]
1191 fn fixed_size_binary_array_all_null_in_batch_with_schema() {
1193 let schema = Schema::new(vec![Field::new("a", DataType::FixedSizeBinary(2), true)]);
1194
1195 let none_option: Option<[u8; 2]> = None;
1196 let item = FixedSizeBinaryArray::try_from_sparse_iter_with_size(
1197 vec![none_option, none_option, none_option].into_iter(),
1198 2,
1199 )
1200 .unwrap();
1201
1202 RecordBatch::try_new(Arc::new(schema), vec![Arc::new(item)]).unwrap();
1204 }
1205
1206 #[test]
1207 #[should_panic(
1208 expected = "Trying to access an element at index 4 from a FixedSizeBinaryArray of length 3"
1209 )]
1210 fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
1211 let values = vec![Some("one".as_bytes()), Some(b"two"), None];
1212 let array = FixedSizeBinaryArray::try_from(values).unwrap();
1213
1214 array.value(4);
1215 }
1216
1217 #[test]
1218 fn test_constructors() {
1219 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1220 let a = FixedSizeBinaryArray::new(2, buffer.clone(), None);
1221 assert_eq!(a.len(), 5);
1222
1223 let nulls = NullBuffer::new_null(5);
1224 FixedSizeBinaryArray::new(2, buffer.clone(), Some(nulls));
1225
1226 let null_array = FixedSizeBinaryArray::new_null(4, 3);
1227 assert_eq!(null_array.len(), 3);
1228 assert_eq!(null_array.values().len(), 12);
1229
1230 let a = FixedSizeBinaryArray::new(3, buffer.clone(), None);
1231 assert_eq!(a.len(), 3);
1232
1233 let nulls = NullBuffer::new_null(3);
1234 FixedSizeBinaryArray::new(3, buffer.clone(), Some(nulls));
1235
1236 let err = FixedSizeBinaryArray::try_new(-1, buffer.clone(), None).unwrap_err();
1237
1238 assert_eq!(
1239 err.to_string(),
1240 "Invalid argument error: Value length cannot be negative, got -1"
1241 );
1242
1243 let nulls = NullBuffer::new_null(3);
1244 let err = FixedSizeBinaryArray::try_new(2, buffer.clone(), Some(nulls)).unwrap_err();
1245 assert_eq!(
1246 err.to_string(),
1247 "Invalid argument error: Incorrect length of null buffer for FixedSizeBinaryArray, expected 5 got 3"
1248 );
1249
1250 let zero_sized = FixedSizeBinaryArray::new(0, Buffer::default(), None);
1251 assert_eq!(zero_sized.len(), 0);
1252 assert_eq!(zero_sized.null_count(), 0);
1253 assert_eq!(zero_sized.values().len(), 0);
1254
1255 let nulls = NullBuffer::new_null(3);
1256 let zero_sized_with_nulls = FixedSizeBinaryArray::new(0, Buffer::default(), Some(nulls));
1257 assert_eq!(zero_sized_with_nulls.len(), 3);
1258 assert_eq!(zero_sized_with_nulls.null_count(), 3);
1259 assert_eq!(zero_sized_with_nulls.values().len(), 0);
1260
1261 let zero_sized_with_non_empty_buffer_err =
1262 FixedSizeBinaryArray::try_new(0, buffer, None).unwrap_err();
1263 assert_eq!(
1264 zero_sized_with_non_empty_buffer_err.to_string(),
1265 "Invalid argument error: Buffer cannot have non-zero length if the value length is zero"
1266 );
1267 }
1268
1269 #[test]
1270 fn test_try_new_with_len() {
1271 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1272
1273 let a = FixedSizeBinaryArray::try_new_with_len(2, buffer.clone(), None, 5).unwrap();
1274 assert_eq!(a.len(), 5);
1275
1276 let nulls = NullBuffer::new_null(5);
1277 let a = FixedSizeBinaryArray::try_new_with_len(2, buffer, Some(nulls), 5).unwrap();
1278 assert_eq!(a.len(), 5);
1279 assert_eq!(a.null_count(), 5);
1280
1281 let a = FixedSizeBinaryArray::try_new_with_len(2, Buffer::default(), None, 0).unwrap();
1282 assert_eq!(a.len(), 0);
1283 }
1284
1285 #[test]
1286 fn test_try_new_with_len_zero_width() {
1287 let a = FixedSizeBinaryArray::try_new_with_len(0, Buffer::default(), None, 5).unwrap();
1289 assert_eq!(a.len(), 5);
1290 assert_eq!(a.null_count(), 0);
1291 assert_eq!(a.values().len(), 0);
1292
1293 let nulls = NullBuffer::new_null(3);
1294 let a =
1295 FixedSizeBinaryArray::try_new_with_len(0, Buffer::default(), Some(nulls), 3).unwrap();
1296 assert_eq!(a.len(), 3);
1297 assert_eq!(a.null_count(), 3);
1298 }
1299
1300 #[test]
1301 fn test_try_new_with_len_negative_value_length() {
1302 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1303 let err = FixedSizeBinaryArray::try_new_with_len(-1, buffer, None, 5).unwrap_err();
1304 assert_eq!(
1305 err.to_string(),
1306 "Invalid argument error: Value length cannot be negative, got -1"
1307 );
1308 }
1309
1310 #[test]
1311 fn test_try_new_with_len_incorrect_null_buffer_length() {
1312 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1313 let nulls = NullBuffer::new_null(3);
1314 let err = FixedSizeBinaryArray::try_new_with_len(2, buffer, Some(nulls), 5).unwrap_err();
1315 assert_eq!(
1316 err.to_string(),
1317 "Invalid argument error: Incorrect length of null buffer for FixedSizeBinaryArray, expected 5 got 3"
1318 );
1319 }
1320
1321 #[test]
1322 fn test_try_new_with_len_incorrect_values_buffer_length() {
1323 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1324 let err = FixedSizeBinaryArray::try_new_with_len(2, buffer, None, 3).unwrap_err();
1325 assert_eq!(
1326 err.to_string(),
1327 "Invalid argument error: Incorrect length of values buffer for FixedSizeBinaryArray, expected 3 got 5"
1328 );
1329 }
1330
1331 #[test]
1332 fn test_try_new_with_len_zero_width_non_empty_buffer() {
1333 let buffer = Buffer::from_vec(vec![0_u8; 10]);
1334 let err = FixedSizeBinaryArray::try_new_with_len(0, buffer, None, 5).unwrap_err();
1335 assert_eq!(
1336 err.to_string(),
1337 "Invalid argument error: Buffer cannot have non-zero length if the value length is zero"
1338 );
1339 }
1340}