1use std::fmt::Display;
5use std::fmt::Formatter;
6use std::mem::size_of;
7use std::sync::Arc;
8
9use smallvec::smallvec;
10use vortex_buffer::Alignment;
11use vortex_buffer::Buffer;
12use vortex_buffer::BufferAllocatorRef;
13use vortex_buffer::ByteBuffer;
14use vortex_error::VortexExpect;
15use vortex_error::VortexResult;
16use vortex_error::vortex_bail;
17use vortex_error::vortex_ensure;
18use vortex_error::vortex_ensure_eq;
19use vortex_error::vortex_err;
20use vortex_error::vortex_panic;
21use vortex_mask::AllOr;
22use vortex_mask::Mask;
23
24use crate::ArrayRef;
25use crate::ArraySlots;
26use crate::ExecutionCtx;
27use crate::array::Array;
28use crate::array::ArrayParts;
29use crate::array::TypedArrayRef;
30use crate::array::child_to_validity;
31use crate::array::validity_to_child;
32use crate::array_slots;
33use crate::arrays::VarBinView;
34use crate::arrays::varbinview::BinaryView;
35use crate::arrays::varbinview::ResolvedViews;
36use crate::buffer::BufferHandle;
37use crate::builders::ArrayBuilder;
38use crate::builders::VarBinViewBuilder;
39use crate::dtype::DType;
40use crate::dtype::Nullability;
41use crate::validity::Validity;
42
43#[array_slots(VarBinView)]
44pub struct VarBinViewSlots {
45 #[slot(0)]
47 pub validity: Option<ArrayRef>,
48}
49
50#[derive(Clone, Debug)]
110pub struct VarBinViewData {
111 pub(super) buffers: Arc<[BufferHandle]>,
112 pub(super) views: BufferHandle,
113}
114
115impl Display for VarBinViewData {
116 fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
117 Ok(())
118 }
119}
120
121pub struct VarBinViewDataParts {
122 pub dtype: DType,
123 pub buffers: Arc<[BufferHandle]>,
124 pub views: BufferHandle,
125 pub validity: Validity,
126}
127
128fn for_each_invalid_range(mask: &Mask, len: usize, mut f: impl FnMut(usize, usize)) {
130 match mask.bit_buffer() {
131 AllOr::All => {}
132 AllOr::None => f(0, len),
133 AllOr::Some(buffer) => {
134 let mut prev = 0;
135 for (start, end) in buffer.set_slices() {
136 if start > prev {
137 f(prev, start);
138 }
139 prev = end;
140 }
141 if prev < len {
142 f(prev, len);
143 }
144 }
145 }
146}
147
148fn try_for_each_valid(
150 mask: &Mask,
151 mut f: impl FnMut(usize) -> VortexResult<()>,
152) -> VortexResult<()> {
153 match mask.bit_buffer() {
154 AllOr::All => (0..mask.len()).try_for_each(f),
155 AllOr::None => Ok(()),
156 AllOr::Some(buffer) => buffer.set_indices().try_for_each(&mut f),
157 }
158}
159
160fn is_inlined_ascii(view: &BinaryView) -> bool {
162 const HIGH_BITS: u128 = u128::from_le_bytes([0x80; 16]);
163
164 let data_bits = ((1u128 << (8 * view.len())) - 1) << 32;
166 view.as_u128() & data_bits & HIGH_BITS == 0
167}
168
169fn is_char_boundary(byte: u8) -> bool {
171 byte & 0b1100_0000 != 0b1000_0000
173}
174
175impl VarBinViewData {
176 fn dtype_parts(dtype: &DType) -> VortexResult<(bool, Nullability)> {
177 match dtype {
178 DType::Utf8(nullability) => Ok((true, *nullability)),
179 DType::Binary(nullability) => Ok((false, *nullability)),
180 _ => vortex_bail!(InvalidArgument: "invalid DType {dtype} for `VarBinViewArray`"),
181 }
182 }
183
184 pub(super) fn make_slots(validity: &Validity, len: usize) -> ArraySlots {
186 smallvec![validity_to_child(validity, len)]
187 }
188
189 pub fn new(
196 views: Buffer<BinaryView>,
197 buffers: Arc<[ByteBuffer]>,
198 dtype: DType,
199 validity: Validity,
200 ctx: &mut ExecutionCtx,
201 ) -> Self {
202 Self::try_new(views, buffers, dtype, validity, ctx)
203 .vortex_expect("VarBinViewArray construction failed")
204 }
205
206 pub fn new_handle(
213 views: BufferHandle,
214 buffers: Arc<[BufferHandle]>,
215 dtype: DType,
216 validity: Validity,
217 ) -> Self {
218 Self::try_new_handle(views, buffers, dtype, validity)
219 .vortex_expect("VarbinViewArray construction failed")
220 }
221
222 pub fn try_new(
231 views: Buffer<BinaryView>,
232 buffers: Arc<[ByteBuffer]>,
233 dtype: DType,
234 validity: Validity,
235 ctx: &mut ExecutionCtx,
236 ) -> VortexResult<Self> {
237 let views = Self::validate_and_fix(views, &buffers, &dtype, &validity, ctx)?;
238
239 Ok(unsafe { Self::new_unchecked(views, buffers, dtype, validity) })
241 }
242
243 pub fn try_new_handle(
252 views: BufferHandle,
253 buffers: Arc<[BufferHandle]>,
254 dtype: DType,
255 validity: Validity,
256 ) -> VortexResult<Self> {
257 let views_nbytes = views.len();
258 vortex_ensure!(
259 views_nbytes.is_multiple_of(size_of::<BinaryView>()),
260 "Expected views buffer length ({views_nbytes}) to be a multiple of {}",
261 size_of::<BinaryView>()
262 );
263
264 if let Some(host) = views.as_host_opt() {
266 vortex_ensure!(
267 host.is_aligned(Alignment::of::<BinaryView>()),
268 "Views on host must be 16 byte aligned"
269 );
270 }
271
272 Ok(unsafe { Self::new_handle_unchecked(views, buffers, dtype, validity) })
274 }
275
276 pub unsafe fn new_unchecked(
306 views: Buffer<BinaryView>,
307 buffers: Arc<[ByteBuffer]>,
308 dtype: DType,
309 validity: Validity,
310 ) -> Self {
311 let handles: Vec<BufferHandle> = buffers
312 .iter()
313 .cloned()
314 .map(BufferHandle::new_host)
315 .collect();
316
317 let handles = Arc::from(handles);
318 let view_handle = BufferHandle::new_host(views.into_byte_buffer());
319 unsafe { Self::new_handle_unchecked(view_handle, handles, dtype, validity) }
320 }
321
322 pub unsafe fn new_handle_unchecked(
328 views: BufferHandle,
329 buffers: Arc<[BufferHandle]>,
330 dtype: DType,
331 _validity: Validity,
332 ) -> Self {
333 let _ =
334 Self::dtype_parts(&dtype).vortex_expect("VarBinViewArray dtype must be utf8 or binary");
335 Self { buffers, views }
336 }
337
338 pub fn validate(
343 views: &Buffer<BinaryView>,
344 buffers: &Arc<[ByteBuffer]>,
345 dtype: &DType,
346 validity: &Validity,
347 ctx: &mut ExecutionCtx,
348 ) -> VortexResult<()> {
349 let check_utf8 = Self::check_nullability(dtype, validity)?;
350 let mask = validity.execute_mask(views.len(), ctx)?;
351 Self::validate_views(views, &mask, buffers, check_utf8)
352 }
353
354 pub(crate) fn validate_and_fix(
356 views: Buffer<BinaryView>,
357 buffers: &Arc<[ByteBuffer]>,
358 dtype: &DType,
359 validity: &Validity,
360 ctx: &mut ExecutionCtx,
361 ) -> VortexResult<Buffer<BinaryView>> {
362 let check_utf8 = Self::check_nullability(dtype, validity)?;
363 let mask = validity.execute_mask(views.len(), ctx)?;
364
365 let views = match (mask.bit_buffer(), views.try_into_mut()) {
368 (AllOr::Some(bits), Ok(mut views)) => {
369 let buffers_utf8 = Self::buffers_utf8(&mask, buffers, check_utf8);
370 let buffers_utf8 = buffers_utf8.as_deref();
371 let empty = BinaryView::empty_view();
372 let slice = views.as_mut_slice();
373 for (idx, (view, valid)) in slice.iter_mut().zip(bits.iter()).enumerate() {
374 if valid {
375 Self::validate_view(idx, view, buffers, buffers_utf8)?;
376 } else {
377 *view = empty;
378 }
379 }
380 return Ok(views.freeze());
381 }
382 (_, Ok(views)) => views.freeze(),
383 (_, Err(views)) => views,
384 };
385
386 Self::validate_views(&views, &mask, buffers, check_utf8)?;
387 Ok(Self::replace_null_views(views, &mask))
388 }
389
390 fn check_nullability(dtype: &DType, validity: &Validity) -> VortexResult<bool> {
391 let (is_utf8, nullability) = Self::dtype_parts(dtype)?;
392 vortex_ensure_eq!(
393 validity.nullability(),
394 nullability,
395 InvalidArgument: "validity nullability is incompatible with dtype nullability",
396 );
397 Ok(is_utf8)
398 }
399
400 fn replace_null_views(views: Buffer<BinaryView>, mask: &Mask) -> Buffer<BinaryView> {
403 if mask.all_true() {
404 return views;
405 }
406
407 let empty = BinaryView::empty_view();
408 let len = views.len();
409
410 let mut views = match views.try_into_mut() {
411 Ok(views) => views,
412 Err(views) => {
413 let mut needs_replace = false;
414 for_each_invalid_range(mask, len, |start, end| {
415 needs_replace |= views[start..end].iter().any(|view| *view != empty);
416 });
417 if !needs_replace {
418 return views;
419 }
420 views.into_mut()
421 }
422 };
423
424 let slice = views.as_mut_slice();
425 for_each_invalid_range(mask, len, |start, end| slice[start..end].fill(empty));
426 views.freeze()
427 }
428
429 fn validate_views(
440 views: &[BinaryView],
441 mask: &Mask,
442 buffers: &[ByteBuffer],
443 check_utf8: bool,
444 ) -> VortexResult<()> {
445 let buffers_utf8 = Self::buffers_utf8(mask, buffers, check_utf8);
446 let buffers_utf8 = buffers_utf8.as_deref();
447
448 try_for_each_valid(mask, |idx| {
449 Self::validate_view(idx, &views[idx], buffers, buffers_utf8)
450 })
451 }
452
453 const PER_VIEW_UTF8_COST: usize = 64;
455
456 fn buffers_utf8(mask: &Mask, buffers: &[ByteBuffer], check_utf8: bool) -> Option<Vec<bool>> {
463 if !check_utf8 {
464 return None;
465 }
466
467 let mut budget = mask.true_count().saturating_mul(Self::PER_VIEW_UTF8_COST);
468
469 Some(
470 buffers
471 .iter()
472 .map(|buf| {
473 if buf.len() > budget {
474 return false;
475 }
476
477 budget -= buf.len();
478 simdutf8::basic::from_utf8(buf).is_ok()
479 })
480 .collect(),
481 )
482 }
483
484 fn validate_view(
489 idx: usize,
490 view: &BinaryView,
491 buffers: &[ByteBuffer],
492 buffers_utf8: Option<&[bool]>,
493 ) -> VortexResult<()> {
494 if view.is_inlined() {
495 if buffers_utf8.is_some() && !is_inlined_ascii(view) {
496 let bytes = view.as_inlined().value();
497 vortex_ensure!(
498 simdutf8::basic::from_utf8(bytes).is_ok(),
499 InvalidArgument: "view at index {idx}: inlined bytes failed utf-8 validation"
500 );
501 }
502 return Ok(());
503 }
504
505 let view = view.as_view();
506 let buf_index = view.buffer_index as usize;
507 let start_offset = view.offset as usize;
508 let end_offset = start_offset.saturating_add(view.size as usize);
509
510 let buf = buffers.get(buf_index).ok_or_else(||
511 vortex_err!(InvalidArgument: "view at index {idx} references invalid buffer: {buf_index} out of bounds for VarBinViewData with {} buffers",
512 buffers.len()))?;
513
514 vortex_ensure!(
515 start_offset < buf.len(),
516 InvalidArgument: "start offset {start_offset} out of bounds for buffer {buf_index} with size {}",
517 buf.len(),
518 );
519
520 vortex_ensure!(
521 end_offset <= buf.len(),
522 InvalidArgument: "end offset {end_offset} out of bounds for buffer {buf_index} with size {}",
523 buf.len(),
524 );
525
526 vortex_ensure!(
528 view.prefix == buf[start_offset..start_offset + 4],
529 InvalidArgument: "VarBinView prefix does not match full string"
530 );
531
532 let Some(buffers_utf8) = buffers_utf8 else {
533 return Ok(());
534 };
535
536 let valid_utf8 = if buffers_utf8[buf_index] {
537 is_char_boundary(buf[start_offset])
538 && (end_offset == buf.len() || is_char_boundary(buf[end_offset]))
539 } else {
540 simdutf8::basic::from_utf8(&buf[start_offset..end_offset]).is_ok()
541 };
542
543 vortex_ensure!(
544 valid_utf8,
545 InvalidArgument: "view at index {idx}: outlined bytes fails utf-8 validation"
546 );
547
548 Ok(())
549 }
550
551 pub fn len(&self) -> usize {
553 self.views.len() / size_of::<BinaryView>()
554 }
555
556 pub fn is_empty(&self) -> bool {
558 self.len() == 0
559 }
560
561 #[inline]
567 pub fn views(&self) -> &[BinaryView] {
568 let host_views = self.views.as_host();
569 let len = host_views.len() / size_of::<BinaryView>();
570
571 unsafe { std::slice::from_raw_parts(host_views.as_ptr().cast(), len) }
573 }
574
575 pub fn views_handle(&self) -> &BufferHandle {
577 &self.views
578 }
579
580 #[inline]
584 pub fn bytes_at(&self, index: usize) -> ByteBuffer {
585 let views = self.views();
586 let view = &views[index];
587 if !view.is_inlined() {
589 let view_ref = view.as_view();
590 self.buffer(view_ref.buffer_index as usize)
591 .slice(view_ref.as_range())
592 } else {
593 self.views_handle()
595 .as_host()
596 .clone()
597 .into_byte_buffer()
598 .slice_ref(view.as_inlined().value())
599 }
600 }
601
602 #[inline]
609 pub fn buffer(&self, idx: usize) -> &ByteBuffer {
610 if idx >= self.data_buffers().len() {
611 vortex_panic!(
612 "{idx} buffer index out of bounds, there are {} buffers",
613 self.data_buffers().len()
614 );
615 }
616 self.buffers[idx].as_host()
617 }
618
619 #[inline]
621 pub fn data_buffers(&self) -> &Arc<[BufferHandle]> {
622 &self.buffers
623 }
624
625 #[expect(
627 clippy::same_name_method,
628 reason = "intentionally named from_iter like Iterator::from_iter"
629 )]
630 pub fn from_iter<T: AsRef<[u8]>, I: IntoIterator<Item = Option<T>>>(
631 iter: I,
632 dtype: DType,
633 ) -> Self {
634 let iter = iter.into_iter();
635 let mut builder = VarBinViewBuilder::with_capacity_in(
636 dtype,
637 iter.size_hint().0,
638 BufferAllocatorRef::statically_allocated(),
639 );
640
641 for item in iter {
642 match item {
643 None => builder.append_null(),
644 Some(v) => builder.append_value(v),
645 }
646 }
647
648 builder.finish_into_varbinview().into_data()
649 }
650
651 pub fn from_iter_str<T: AsRef<str>, I: IntoIterator<Item = T>>(iter: I) -> Self {
652 let iter = iter.into_iter();
653 let mut builder = VarBinViewBuilder::with_capacity_in(
654 DType::Utf8(Nullability::NonNullable),
655 iter.size_hint().0,
656 BufferAllocatorRef::statically_allocated(),
657 );
658
659 for item in iter {
660 builder.append_value(item.as_ref());
661 }
662
663 builder.finish_into_varbinview().into_data()
664 }
665
666 pub fn from_iter_nullable_str<T: AsRef<str>, I: IntoIterator<Item = Option<T>>>(
667 iter: I,
668 ) -> Self {
669 let iter = iter.into_iter();
670 let mut builder = VarBinViewBuilder::with_capacity_in(
671 DType::Utf8(Nullability::Nullable),
672 iter.size_hint().0,
673 BufferAllocatorRef::statically_allocated(),
674 );
675
676 for item in iter {
677 match item {
678 None => builder.append_null(),
679 Some(v) => builder.append_value(v.as_ref()),
680 }
681 }
682
683 builder.finish_into_varbinview().into_data()
684 }
685
686 pub fn from_iter_bin<T: AsRef<[u8]>, I: IntoIterator<Item = T>>(iter: I) -> Self {
687 let iter = iter.into_iter();
688 let mut builder = VarBinViewBuilder::with_capacity_in(
689 DType::Binary(Nullability::NonNullable),
690 iter.size_hint().0,
691 BufferAllocatorRef::statically_allocated(),
692 );
693
694 for item in iter {
695 builder.append_value(item.as_ref());
696 }
697
698 builder.finish_into_varbinview().into_data()
699 }
700
701 pub fn from_iter_nullable_bin<T: AsRef<[u8]>, I: IntoIterator<Item = Option<T>>>(
702 iter: I,
703 ) -> Self {
704 let iter = iter.into_iter();
705 let mut builder = VarBinViewBuilder::with_capacity_in(
706 DType::Binary(Nullability::Nullable),
707 iter.size_hint().0,
708 BufferAllocatorRef::statically_allocated(),
709 );
710
711 for item in iter {
712 match item {
713 None => builder.append_null(),
714 Some(v) => builder.append_value(v.as_ref()),
715 }
716 }
717
718 builder.finish_into_varbinview().into_data()
719 }
720}
721
722pub trait VarBinViewArrayExt: TypedArrayRef<VarBinView> {
723 fn dtype_parts(&self) -> (bool, Nullability) {
724 match self.dtype() {
725 DType::Utf8(nullability) => (true, *nullability),
726 DType::Binary(nullability) => (false, *nullability),
727 _ => unreachable!("VarBinViewArrayExt requires a utf8 or binary dtype"),
728 }
729 }
730
731 fn varbinview_validity(&self) -> Validity {
732 child_to_validity(
733 self.slots()[VarBinViewSlots::VALIDITY].as_ref(),
734 self.dtype_parts().1,
735 )
736 }
737}
738impl<T: TypedArrayRef<VarBinView>> VarBinViewArrayExt for T {}
739
740impl Array<VarBinView> {
741 pub fn resolved_views(&self) -> ResolvedViews<'_> {
743 ResolvedViews::new(self)
744 }
745
746 #[inline]
747 fn from_prevalidated_data(dtype: DType, data: VarBinViewData, slots: ArraySlots) -> Self {
748 let len = data.len();
749 unsafe { Array::from_parts_unchecked(ArrayParts::new(VarBinView, dtype, len, data, slots)) }
750 }
751
752 #[expect(
754 clippy::same_name_method,
755 reason = "intentionally named from_iter like Iterator::from_iter"
756 )]
757 pub fn from_iter<T: AsRef<[u8]>, I: IntoIterator<Item = Option<T>>>(
758 iter: I,
759 dtype: DType,
760 ) -> Self {
761 let iter = iter.into_iter();
762 let mut builder = VarBinViewBuilder::with_capacity_in(
763 dtype,
764 iter.size_hint().0,
765 BufferAllocatorRef::statically_allocated(),
766 );
767 for value in iter {
768 match value {
769 Some(value) => builder.append_value(value),
770 None => builder.append_null(),
771 }
772 }
773 builder.finish_into_varbinview()
774 }
775
776 pub fn from_iter_str<T: AsRef<str>, I: IntoIterator<Item = T>>(iter: I) -> Self {
777 let iter = iter.into_iter();
778 let mut builder = VarBinViewBuilder::with_capacity_in(
779 DType::Utf8(Nullability::NonNullable),
780 iter.size_hint().0,
781 BufferAllocatorRef::statically_allocated(),
782 );
783 for value in iter {
784 builder.append_value(value.as_ref());
785 }
786 builder.finish_into_varbinview()
787 }
788
789 pub fn from_iter_nullable_str<T: AsRef<str>, I: IntoIterator<Item = Option<T>>>(
790 iter: I,
791 ) -> Self {
792 let iter = iter.into_iter();
793 let mut builder = VarBinViewBuilder::with_capacity_in(
794 DType::Utf8(Nullability::Nullable),
795 iter.size_hint().0,
796 BufferAllocatorRef::statically_allocated(),
797 );
798 for value in iter {
799 match value {
800 Some(value) => builder.append_value(value.as_ref()),
801 None => builder.append_null(),
802 }
803 }
804 builder.finish_into_varbinview()
805 }
806
807 pub fn from_iter_bin<T: AsRef<[u8]>, I: IntoIterator<Item = T>>(iter: I) -> Self {
808 let iter = iter.into_iter();
809 let mut builder = VarBinViewBuilder::with_capacity_in(
810 DType::Binary(Nullability::NonNullable),
811 iter.size_hint().0,
812 BufferAllocatorRef::statically_allocated(),
813 );
814 for value in iter {
815 builder.append_value(value.as_ref());
816 }
817 builder.finish_into_varbinview()
818 }
819
820 pub fn from_iter_nullable_bin<T: AsRef<[u8]>, I: IntoIterator<Item = Option<T>>>(
821 iter: I,
822 ) -> Self {
823 let iter = iter.into_iter();
824 let mut builder = VarBinViewBuilder::with_capacity_in(
825 DType::Binary(Nullability::Nullable),
826 iter.size_hint().0,
827 BufferAllocatorRef::statically_allocated(),
828 );
829 for value in iter {
830 match value {
831 Some(value) => builder.append_value(value.as_ref()),
832 None => builder.append_null(),
833 }
834 }
835 builder.finish_into_varbinview()
836 }
837
838 pub fn try_new(
840 views: Buffer<BinaryView>,
841 buffers: Arc<[ByteBuffer]>,
842 dtype: DType,
843 validity: Validity,
844 ctx: &mut ExecutionCtx,
845 ) -> VortexResult<Self> {
846 let data = VarBinViewData::try_new(views, buffers, dtype.clone(), validity.clone(), ctx)?;
847 let slots = VarBinViewData::make_slots(&validity, data.len());
848 Ok(Self::from_prevalidated_data(dtype, data, slots))
849 }
850
851 pub unsafe fn new_unchecked(
857 views: Buffer<BinaryView>,
858 buffers: Arc<[ByteBuffer]>,
859 dtype: DType,
860 validity: Validity,
861 ) -> Self {
862 let data = unsafe {
863 VarBinViewData::new_unchecked(views, buffers, dtype.clone(), validity.clone())
864 };
865 let slots = VarBinViewData::make_slots(&validity, data.len());
866 Self::from_prevalidated_data(dtype, data, slots)
867 }
868
869 pub fn new_handle(
871 views: BufferHandle,
872 buffers: Arc<[BufferHandle]>,
873 dtype: DType,
874 validity: Validity,
875 ) -> Self {
876 let data = VarBinViewData::new_handle(views, buffers, dtype.clone(), validity.clone());
877 let slots = VarBinViewData::make_slots(&validity, data.len());
878 Self::from_prevalidated_data(dtype, data, slots)
879 }
880
881 pub unsafe fn new_handle_unchecked(
887 views: BufferHandle,
888 buffers: Arc<[BufferHandle]>,
889 dtype: DType,
890 validity: Validity,
891 ) -> Self {
892 let data = unsafe {
893 VarBinViewData::new_handle_unchecked(views, buffers, dtype.clone(), validity.clone())
894 };
895 let slots = VarBinViewData::make_slots(&validity, data.len());
896 Self::from_prevalidated_data(dtype, data, slots)
897 }
898
899 pub fn into_data_parts(self) -> VarBinViewDataParts {
900 let dtype = self.dtype().clone();
901 let validity = self.varbinview_validity();
902 let data = self.into_data();
903 VarBinViewDataParts {
904 dtype,
905 buffers: data.buffers,
906 views: data.views,
907 validity,
908 }
909 }
910}
911
912impl<'a> FromIterator<Option<&'a [u8]>> for VarBinViewData {
913 fn from_iter<T: IntoIterator<Item = Option<&'a [u8]>>>(iter: T) -> Self {
914 Self::from_iter_nullable_bin(iter)
915 }
916}
917
918impl FromIterator<Option<Vec<u8>>> for VarBinViewData {
919 fn from_iter<T: IntoIterator<Item = Option<Vec<u8>>>>(iter: T) -> Self {
920 Self::from_iter_nullable_bin(iter)
921 }
922}
923
924impl FromIterator<Option<String>> for VarBinViewData {
925 fn from_iter<T: IntoIterator<Item = Option<String>>>(iter: T) -> Self {
926 Self::from_iter_nullable_str(iter)
927 }
928}
929
930impl<'a> FromIterator<Option<&'a str>> for VarBinViewData {
931 fn from_iter<T: IntoIterator<Item = Option<&'a str>>>(iter: T) -> Self {
932 Self::from_iter_nullable_str(iter)
933 }
934}
935
936impl<'a> FromIterator<Option<&'a [u8]>> for Array<VarBinView> {
939 fn from_iter<T: IntoIterator<Item = Option<&'a [u8]>>>(iter: T) -> Self {
940 Self::from_iter(iter, DType::Binary(Nullability::Nullable))
941 }
942}
943
944impl FromIterator<Option<Vec<u8>>> for Array<VarBinView> {
945 fn from_iter<T: IntoIterator<Item = Option<Vec<u8>>>>(iter: T) -> Self {
946 Self::from_iter(iter, DType::Binary(Nullability::Nullable))
947 }
948}
949
950impl FromIterator<Option<String>> for Array<VarBinView> {
951 fn from_iter<T: IntoIterator<Item = Option<String>>>(iter: T) -> Self {
952 Self::from_iter_nullable_str(iter)
953 }
954}
955
956impl<'a> FromIterator<Option<&'a str>> for Array<VarBinView> {
957 fn from_iter<T: IntoIterator<Item = Option<&'a str>>>(iter: T) -> Self {
958 Self::from_iter_nullable_str(iter)
959 }
960}