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