1use crate::filter::{SlicesIterator, prep_null_mask_filter};
21use arrow_array::cast::AsArray;
22use arrow_array::types::{
23 BinaryType, BinaryViewType, ByteArrayType, ByteViewType, LargeBinaryType, LargeUtf8Type,
24 StringViewType, Utf8Type,
25};
26use arrow_array::*;
27use arrow_buffer::{
28 ArrowNativeType, BooleanBuffer, Buffer, MutableBuffer, NullBuffer, OffsetBuffer, ScalarBuffer,
29 ToByteSlice,
30};
31use arrow_data::transform::MutableArrayData;
32use arrow_data::{ArrayData, ByteView};
33use arrow_schema::{ArrowError, DataType};
34use std::fmt::{Debug, Formatter};
35use std::hash::Hash;
36use std::marker::PhantomData;
37use std::ops::Not;
38use std::sync::{Arc, OnceLock};
39
40pub fn zip(
100 mask: &BooleanArray,
101 truthy: &dyn Datum,
102 falsy: &dyn Datum,
103) -> Result<ArrayRef, ArrowError> {
104 let (truthy_array, truthy_is_scalar) = truthy.get();
105 let (falsy_array, falsy_is_scalar) = falsy.get();
106
107 if falsy_is_scalar && truthy_is_scalar {
108 let zipper = ScalarZipper::try_new(truthy, falsy)?;
109 return zipper.zip_impl.create_output(mask);
110 }
111
112 let truthy = truthy_array;
113 let falsy = falsy_array;
114
115 if truthy.data_type() != falsy.data_type() {
116 return Err(ArrowError::InvalidArgumentError(
117 "arguments need to have the same data type".into(),
118 ));
119 }
120
121 if truthy_is_scalar && truthy.len() != 1 {
122 return Err(ArrowError::InvalidArgumentError(
123 "scalar arrays must have 1 element".into(),
124 ));
125 }
126 if !truthy_is_scalar && truthy.len() != mask.len() {
127 return Err(ArrowError::InvalidArgumentError(
128 "all arrays should have the same length".into(),
129 ));
130 }
131 if falsy_is_scalar && falsy.len() != 1 {
132 return Err(ArrowError::InvalidArgumentError(
133 "scalar arrays must have 1 element".into(),
134 ));
135 }
136 if !falsy_is_scalar && falsy.len() != mask.len() {
137 return Err(ArrowError::InvalidArgumentError(
138 "all arrays should have the same length".into(),
139 ));
140 }
141
142 let falsy = falsy.to_data();
143 let truthy = truthy.to_data();
144
145 zip_impl(mask, &truthy, truthy_is_scalar, &falsy, falsy_is_scalar)
146}
147
148fn count_true_runs(mask: &BooleanBuffer) -> usize {
149 let mut slices = 0;
150 let mut previous = 0;
151 for chunk in mask.bit_chunks().iter_padded() {
152 let starts = chunk & !((chunk << 1) | previous);
153 slices += starts.count_ones() as usize;
154 previous = chunk >> 63;
155 }
156 slices
157}
158
159fn should_use_interleave(mask: &BooleanBuffer) -> bool {
160 const MIN_LEN: usize = 1024;
161
162 mask.len() >= MIN_LEN && count_true_runs(mask) > mask.len() / 8
166}
167
168fn interleave_arrays(
169 mask: &BooleanBuffer,
170 truthy: &ArrayData,
171 falsy: &ArrayData,
172) -> Result<ArrayRef, ArrowError> {
173 let truthy = make_array(truthy.clone());
174 let falsy = make_array(falsy.clone());
175 let indices: Vec<_> = mask
176 .iter()
177 .enumerate()
178 .map(|(idx, selected)| (usize::from(!selected), idx))
179 .collect();
180 crate::interleave::interleave(&[truthy.as_ref(), falsy.as_ref()], &indices)
181}
182
183fn zip_impl(
184 mask: &BooleanArray,
185 truthy: &ArrayData,
186 truthy_is_scalar: bool,
187 falsy: &ArrayData,
188 falsy_is_scalar: bool,
189) -> Result<ArrayRef, ArrowError> {
190 let mask_buffer = maybe_prep_null_mask_filter(mask);
191 if !truthy_is_scalar && !falsy_is_scalar && should_use_interleave(&mask_buffer) {
192 return interleave_arrays(&mask_buffer, truthy, falsy);
193 }
194
195 let mut mutable = MutableArrayData::new(vec![truthy, falsy], false, truthy.len());
196
197 let mut filled = 0;
202
203 for (start, end) in SlicesIterator::from(&mask_buffer) {
204 if start > filled {
206 if falsy_is_scalar {
207 for _ in filled..start {
208 mutable.try_extend(1, 0, 1)?;
210 }
211 } else {
212 mutable.try_extend(1, filled, start)?;
213 }
214 }
215 if truthy_is_scalar {
217 for _ in start..end {
218 mutable.try_extend(0, 0, 1)?;
220 }
221 } else {
222 mutable.try_extend(0, start, end)?;
223 }
224 filled = end;
225 }
226 if filled < mask.len() {
228 if falsy_is_scalar {
229 for _ in filled..mask.len() {
230 mutable.try_extend(1, 0, 1)?;
232 }
233 } else {
234 mutable.try_extend(1, filled, mask.len())?;
235 }
236 }
237
238 let data = mutable.freeze();
239 Ok(make_array(data))
240}
241
242#[derive(Debug, Clone)]
264pub struct ScalarZipper {
265 zip_impl: Arc<dyn ZipImpl>,
266}
267
268impl ScalarZipper {
269 pub fn try_new(truthy: &dyn Datum, falsy: &dyn Datum) -> Result<Self, ArrowError> {
277 let (truthy, truthy_is_scalar) = truthy.get();
278 let (falsy, falsy_is_scalar) = falsy.get();
279
280 if truthy.data_type() != falsy.data_type() {
281 return Err(ArrowError::InvalidArgumentError(
282 "arguments need to have the same data type".into(),
283 ));
284 }
285
286 if !truthy_is_scalar {
287 return Err(ArrowError::InvalidArgumentError(
288 "only scalar arrays are supported".into(),
289 ));
290 }
291
292 if !falsy_is_scalar {
293 return Err(ArrowError::InvalidArgumentError(
294 "only scalar arrays are supported".into(),
295 ));
296 }
297
298 if truthy.len() != 1 {
299 return Err(ArrowError::InvalidArgumentError(
300 "scalar arrays must have 1 element".into(),
301 ));
302 }
303 if falsy.len() != 1 {
304 return Err(ArrowError::InvalidArgumentError(
305 "scalar arrays must have 1 element".into(),
306 ));
307 }
308
309 macro_rules! primitive_size_helper {
310 ($t:ty) => {
311 Arc::new(PrimitiveScalarImpl::<$t>::new(truthy, falsy)) as Arc<dyn ZipImpl>
312 };
313 }
314
315 let zip_impl = downcast_primitive! {
316 truthy.data_type() => (primitive_size_helper),
317 DataType::Utf8 => {
318 Arc::new(BytesScalarImpl::<Utf8Type>::new(truthy, falsy)) as Arc<dyn ZipImpl>
319 },
320 DataType::LargeUtf8 => {
321 Arc::new(BytesScalarImpl::<LargeUtf8Type>::new(truthy, falsy)) as Arc<dyn ZipImpl>
322 },
323 DataType::Binary => {
324 Arc::new(BytesScalarImpl::<BinaryType>::new(truthy, falsy)) as Arc<dyn ZipImpl>
325 },
326 DataType::LargeBinary => {
327 Arc::new(BytesScalarImpl::<LargeBinaryType>::new(truthy, falsy)) as Arc<dyn ZipImpl>
328 },
329 DataType::Utf8View => {
330 Arc::new(ByteViewScalarImpl::<StringViewType>::new(truthy, falsy)) as Arc<dyn ZipImpl>
331 },
332 DataType::BinaryView => {
333 Arc::new(ByteViewScalarImpl::<BinaryViewType>::new(truthy, falsy)) as Arc<dyn ZipImpl>
334 },
335 _ => {
336 Arc::new(FallbackImpl::new(truthy, falsy)) as Arc<dyn ZipImpl>
337 },
338 };
339
340 Ok(Self { zip_impl })
341 }
342
343 pub fn zip(&self, mask: &BooleanArray) -> Result<ArrayRef, ArrowError> {
346 self.zip_impl.create_output(mask)
347 }
348}
349
350trait ZipImpl: Debug + Send + Sync {
352 fn create_output(&self, input: &BooleanArray) -> Result<ArrayRef, ArrowError>;
354}
355
356#[derive(Debug, PartialEq)]
357struct FallbackImpl {
358 truthy: ArrayData,
359 falsy: ArrayData,
360}
361
362impl FallbackImpl {
363 fn new(left: &dyn Array, right: &dyn Array) -> Self {
364 Self {
365 truthy: left.to_data(),
366 falsy: right.to_data(),
367 }
368 }
369}
370
371impl ZipImpl for FallbackImpl {
372 fn create_output(&self, predicate: &BooleanArray) -> Result<ArrayRef, ArrowError> {
373 zip_impl(predicate, &self.truthy, true, &self.falsy, true)
374 }
375}
376
377struct PrimitiveScalarImpl<T: ArrowPrimitiveType> {
378 data_type: DataType,
379 truthy: Option<T::Native>,
380 falsy: Option<T::Native>,
381}
382
383impl<T: ArrowPrimitiveType> Debug for PrimitiveScalarImpl<T> {
384 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
385 f.debug_struct("PrimitiveScalarImpl")
386 .field("data_type", &self.data_type)
387 .field("truthy", &self.truthy)
388 .field("falsy", &self.falsy)
389 .finish()
390 }
391}
392
393impl<T: ArrowPrimitiveType> PrimitiveScalarImpl<T> {
394 fn new(truthy: &dyn Array, falsy: &dyn Array) -> Self {
395 Self {
396 data_type: truthy.data_type().clone(),
397 truthy: Self::get_value_from_scalar(truthy),
398 falsy: Self::get_value_from_scalar(falsy),
399 }
400 }
401
402 fn get_value_from_scalar(scalar: &dyn Array) -> Option<T::Native> {
403 if scalar.is_null(0) {
404 None
405 } else {
406 let value = scalar.as_primitive::<T>().value(0);
407
408 Some(value)
409 }
410 }
411
412 fn get_scalar_and_null_buffer_for_single_non_nullable(
416 predicate: BooleanBuffer,
417 value: T::Native,
418 ) -> (Vec<T::Native>, Option<NullBuffer>) {
419 let result_len = predicate.len();
420 let nulls = NullBuffer::new(predicate);
421 let scalars = vec![value; result_len];
422
423 (scalars, Some(nulls))
424 }
425}
426
427impl<T: ArrowPrimitiveType> ZipImpl for PrimitiveScalarImpl<T> {
428 fn create_output(&self, predicate: &BooleanArray) -> Result<ArrayRef, ArrowError> {
429 let result_len = predicate.len();
430 let predicate = maybe_prep_null_mask_filter(predicate);
432
433 let (scalars, nulls): (Vec<T::Native>, Option<NullBuffer>) = match (self.truthy, self.falsy)
434 {
435 (Some(truthy_val), Some(falsy_val)) => {
436 let scalars: Vec<T::Native> = predicate
437 .iter()
438 .map(|b| if b { truthy_val } else { falsy_val })
439 .collect();
440
441 (scalars, None)
442 }
443 (Some(truthy_val), None) => {
444 Self::get_scalar_and_null_buffer_for_single_non_nullable(predicate, truthy_val)
448 }
449 (None, Some(falsy_val)) => {
450 let predicate = predicate.not();
455
456 Self::get_scalar_and_null_buffer_for_single_non_nullable(predicate, falsy_val)
457 }
458 (None, None) => {
459 let nulls = NullBuffer::new_null(result_len);
461 let scalars = vec![T::default_value(); result_len];
462
463 (scalars, Some(nulls))
464 }
465 };
466
467 let scalars = ScalarBuffer::<T::Native>::from(scalars);
468 let output = PrimitiveArray::<T>::try_new(scalars, nulls)?;
469
470 let output = output.with_data_type(self.data_type.clone());
472
473 Ok(Arc::new(output))
474 }
475}
476
477#[derive(PartialEq, Hash)]
478struct BytesScalarImpl<T: ByteArrayType> {
479 truthy: Option<Vec<u8>>,
480 falsy: Option<Vec<u8>>,
481 phantom: PhantomData<T>,
482}
483
484impl<T: ByteArrayType> Debug for BytesScalarImpl<T> {
485 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
486 f.debug_struct("BytesScalarImpl")
487 .field("truthy", &self.truthy)
488 .field("falsy", &self.falsy)
489 .finish()
490 }
491}
492
493impl<T: ByteArrayType> BytesScalarImpl<T> {
494 fn new(truthy_value: &dyn Array, falsy_value: &dyn Array) -> Self {
495 Self {
496 truthy: Self::get_value_from_scalar(truthy_value),
497 falsy: Self::get_value_from_scalar(falsy_value),
498 phantom: PhantomData,
499 }
500 }
501
502 fn get_value_from_scalar(scalar: &dyn Array) -> Option<Vec<u8>> {
503 if scalar.is_null(0) {
504 None
505 } else {
506 let bytes: &[u8] = scalar.as_bytes::<T>().value(0).as_ref();
507
508 Some(bytes.to_vec())
509 }
510 }
511
512 #[expect(clippy::type_complexity)]
516 fn get_scalar_and_null_buffer_for_single_non_nullable(
517 predicate: BooleanBuffer,
518 value: &[u8],
519 ) -> Result<(Buffer, OffsetBuffer<T::Offset>, Option<NullBuffer>), ArrowError> {
520 let value_length = value.len();
521
522 let number_of_true = predicate.count_set_bits();
523
524 if number_of_true == 0 {
526 let nulls = NullBuffer::new_null(predicate.len());
528
529 return Ok((
530 Buffer::from(&[]),
532 OffsetBuffer::<T::Offset>::new_zeroed(predicate.len()),
534 Some(nulls),
535 ));
536 }
537
538 let offsets = OffsetBuffer::<T::Offset>::from_lengths(
539 predicate.iter().map(|b| if b { value_length } else { 0 }),
540 );
541
542 let mut bytes = MutableBuffer::with_capacity(0);
543 bytes
544 .try_repeat_slice_n_times(value, number_of_true)
545 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
546
547 let bytes = Buffer::from(bytes);
548
549 let nulls = NullBuffer::new(predicate);
552
553 Ok((bytes, offsets, Some(nulls)))
554 }
555
556 fn get_bytes_and_offset_for_all_same_value(
559 number_of_values: usize,
560 value: &[u8],
561 ) -> Result<(Buffer, OffsetBuffer<T::Offset>), ArrowError> {
562 let value_length = value.len();
563
564 let offsets =
565 OffsetBuffer::<T::Offset>::from_repeated_length(value_length, number_of_values);
566
567 let mut bytes = MutableBuffer::with_capacity(0);
568 bytes
569 .try_repeat_slice_n_times(value, number_of_values)
570 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
571 let bytes = Buffer::from(bytes);
572
573 Ok((bytes, offsets))
574 }
575
576 fn create_output_on_non_nulls(
577 predicate: &BooleanBuffer,
578 truthy_val: &[u8],
579 falsy_val: &[u8],
580 ) -> Result<(Buffer, OffsetBuffer<<T as ByteArrayType>::Offset>), ArrowError> {
581 let true_count = predicate.count_set_bits();
582
583 match true_count {
584 0 => {
585 return Self::get_bytes_and_offset_for_all_same_value(predicate.len(), falsy_val);
587 }
588 n if n == predicate.len() => {
589 return Self::get_bytes_and_offset_for_all_same_value(predicate.len(), truthy_val);
591 }
592
593 _ => {
594 }
596 }
597
598 let total_number_of_bytes = true_count
599 .checked_mul(truthy_val.len())
600 .and_then(|truthy_bytes| {
601 let falsy_bytes = (predicate.len() - true_count).checked_mul(falsy_val.len())?;
602 truthy_bytes.checked_add(falsy_bytes)
603 })
604 .ok_or_else(|| ArrowError::MemoryError("zip output size overflow".to_string()))?;
605 T::Offset::from_usize(total_number_of_bytes)
606 .ok_or(ArrowError::OffsetOverflowError(total_number_of_bytes))?;
607 let mut mutable = MutableBuffer::with_capacity(total_number_of_bytes);
608 let mut offsets = Vec::<T::Offset>::with_capacity(predicate.len() + 1);
609 offsets.push(T::Offset::usize_as(0));
610 let mut current_offset: usize = 0;
611
612 let mut filled = 0;
614
615 let truthy_len = truthy_val.len();
616 let falsy_len = falsy_val.len();
617
618 SlicesIterator::from(predicate).try_for_each(|(start, end)| -> Result<(), ArrowError> {
620 if start > filled {
622 let false_repeat_count = start - filled;
623 mutable
625 .try_repeat_slice_n_times(falsy_val, false_repeat_count)
626 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
627
628 let start_offset = current_offset;
629 current_offset += falsy_len * false_repeat_count;
630 offsets.extend(
631 (1..=false_repeat_count)
632 .map(|index| T::Offset::usize_as(start_offset + index * falsy_len)),
633 );
634 }
635
636 let true_repeat_count = end - start;
637 mutable
639 .try_repeat_slice_n_times(truthy_val, true_repeat_count)
640 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
641
642 let start_offset = current_offset;
643 current_offset += truthy_len * true_repeat_count;
644 offsets.extend(
645 (1..=true_repeat_count)
646 .map(|index| T::Offset::usize_as(start_offset + index * truthy_len)),
647 );
648 filled = end;
649 Ok(())
650 })?;
651 if filled < predicate.len() {
653 let false_repeat_count = predicate.len() - filled;
654 mutable
656 .try_repeat_slice_n_times(falsy_val, false_repeat_count)
657 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
658
659 let start_offset = current_offset;
660 current_offset += falsy_len * false_repeat_count;
661 offsets.extend(
662 (1..=false_repeat_count)
663 .map(|index| T::Offset::usize_as(start_offset + index * falsy_len)),
664 );
665 }
666
667 debug_assert_eq!(current_offset, total_number_of_bytes);
668 let offsets = unsafe { OffsetBuffer::new_unchecked(offsets.into()) };
670 Ok((mutable.into(), offsets))
671 }
672}
673
674impl<T: ByteArrayType> ZipImpl for BytesScalarImpl<T> {
675 fn create_output(&self, predicate: &BooleanArray) -> Result<ArrayRef, ArrowError> {
676 let result_len = predicate.len();
677 let predicate = maybe_prep_null_mask_filter(predicate);
679
680 let (bytes, offsets, nulls): (Buffer, OffsetBuffer<T::Offset>, Option<NullBuffer>) =
681 match (self.truthy.as_deref(), self.falsy.as_deref()) {
682 (Some(truthy_val), Some(falsy_val)) => {
683 let (bytes, offsets) =
684 Self::create_output_on_non_nulls(&predicate, truthy_val, falsy_val)?;
685
686 (bytes, offsets, None)
687 }
688 (Some(truthy_val), None) => {
689 Self::get_scalar_and_null_buffer_for_single_non_nullable(predicate, truthy_val)?
690 }
691 (None, Some(falsy_val)) => {
692 let predicate = predicate.not();
697 Self::get_scalar_and_null_buffer_for_single_non_nullable(predicate, falsy_val)?
698 }
699 (None, None) => {
700 let nulls = NullBuffer::new_null(result_len);
702
703 (
704 Buffer::from(&[]),
706 OffsetBuffer::<T::Offset>::new_zeroed(predicate.len()),
708 Some(nulls),
709 )
710 }
711 };
712
713 let output = unsafe {
714 GenericByteArray::<T>::new_unchecked(offsets, bytes, nulls)
717 };
718
719 Ok(Arc::new(output))
720 }
721}
722
723fn maybe_prep_null_mask_filter(predicate: &BooleanArray) -> BooleanBuffer {
724 if predicate.null_count() == 0 {
726 predicate.values().clone()
727 } else {
728 let cleaned = prep_null_mask_filter(predicate);
729 let (boolean_buffer, _) = cleaned.into_parts();
730 boolean_buffer
731 }
732}
733
734struct ByteViewScalarImpl<T: ByteViewType> {
735 truthy_view: Option<u128>,
736 truthy_buffers: Arc<[Buffer]>,
737 falsy_view: Option<u128>,
738 falsy_buffers: Arc<[Buffer]>,
739 phantom: PhantomData<T>,
740}
741
742static EMPTY_ARC: OnceLock<Arc<[Buffer]>> = OnceLock::new();
743fn empty_arc_buffers() -> Arc<[Buffer]> {
744 Arc::clone(EMPTY_ARC.get_or_init(|| Arc::new([])))
745}
746
747impl<T: ByteViewType> ByteViewScalarImpl<T> {
748 fn new(truthy: &dyn Array, falsy: &dyn Array) -> Self {
749 let (truthy_view, truthy_buffers) = Self::get_value_from_scalar(truthy);
750 let (falsy_view, falsy_buffers) = Self::get_value_from_scalar(falsy);
751 Self {
752 truthy_view,
753 truthy_buffers,
754 falsy_view,
755 falsy_buffers,
756 phantom: PhantomData,
757 }
758 }
759
760 fn get_value_from_scalar(scalar: &dyn Array) -> (Option<u128>, Arc<[Buffer]>) {
761 if scalar.is_null(0) {
762 (None, empty_arc_buffers())
763 } else {
764 let (views, buffers, _) = scalar.as_byte_view::<T>().clone().into_parts();
765 (views.first().copied(), buffers)
766 }
767 }
768
769 fn get_views_for_single_non_nullable(
770 predicate: BooleanBuffer,
771 value: u128,
772 buffers: Arc<[Buffer]>,
773 ) -> (ScalarBuffer<u128>, Arc<[Buffer]>, Option<NullBuffer>) {
774 let number_of_true = predicate.count_set_bits();
775 let number_of_values = predicate.len();
776
777 if number_of_true == 0 {
779 return (
781 vec![0; number_of_values].into(),
782 empty_arc_buffers(),
783 Some(NullBuffer::new_null(number_of_values)),
784 );
785 }
786 let bytes = vec![value; number_of_values];
787
788 let nulls = NullBuffer::new(predicate);
791 (bytes.into(), buffers, Some(nulls))
792 }
793
794 #[expect(clippy::type_complexity)]
795 fn get_views_for_non_nullable(
796 predicate: BooleanBuffer,
797 result_len: usize,
798 truthy_view: u128,
799 truthy_buffers: Arc<[Buffer]>,
800 falsy_view: u128,
801 falsy_buffers: Arc<[Buffer]>,
802 ) -> Result<(ScalarBuffer<u128>, Arc<[Buffer]>, Option<NullBuffer>), ArrowError> {
803 let true_count = predicate.count_set_bits();
804 match true_count {
805 0 => {
806 Ok((vec![falsy_view; result_len].into(), falsy_buffers, None))
808 }
809 n if n == predicate.len() => {
810 Ok((vec![truthy_view; result_len].into(), truthy_buffers, None))
812 }
813 _ => {
814 let true_count = predicate.count_set_bits();
815 let mut buffers: Vec<Buffer> = truthy_buffers.to_vec();
816
817 let view_falsy = if falsy_buffers.is_empty() {
821 falsy_view
822 } else {
823 let byte_view_falsy = ByteView::from(falsy_view);
824 let new_index_falsy_buffers =
825 buffers.len() as u32 + byte_view_falsy.buffer_index;
826 buffers.extend(falsy_buffers.iter().cloned());
827 let byte_view_falsy =
828 byte_view_falsy.with_buffer_index(new_index_falsy_buffers);
829 byte_view_falsy.as_u128()
830 };
831
832 let total_number_of_bytes = true_count * 16 + (predicate.len() - true_count) * 16;
833 let mut mutable = MutableBuffer::new(total_number_of_bytes);
834 let mut filled = 0;
835
836 SlicesIterator::from(&predicate).try_for_each(
837 |(start, end)| -> Result<(), ArrowError> {
838 if start > filled {
839 let false_repeat_count = start - filled;
840 mutable
841 .try_repeat_slice_n_times(
842 view_falsy.to_byte_slice(),
843 false_repeat_count,
844 )
845 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
846 }
847 let true_repeat_count = end - start;
848 mutable
849 .try_repeat_slice_n_times(
850 truthy_view.to_byte_slice(),
851 true_repeat_count,
852 )
853 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
854 filled = end;
855 Ok(())
856 },
857 )?;
858
859 if filled < predicate.len() {
860 let false_repeat_count = predicate.len() - filled;
861 mutable
862 .try_repeat_slice_n_times(view_falsy.to_byte_slice(), false_repeat_count)
863 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
864 }
865
866 let bytes = Buffer::from(mutable);
867 Ok((bytes.into(), buffers.into(), None))
868 }
869 }
870 }
871}
872
873impl<T: ByteViewType> Debug for ByteViewScalarImpl<T> {
874 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
875 f.debug_struct("ByteViewScalarImpl")
876 .field("truthy", &self.truthy_view)
877 .field("falsy", &self.falsy_view)
878 .finish()
879 }
880}
881
882impl<T: ByteViewType> ZipImpl for ByteViewScalarImpl<T> {
883 fn create_output(&self, predicate: &BooleanArray) -> Result<ArrayRef, ArrowError> {
884 let result_len = predicate.len();
885 let predicate = maybe_prep_null_mask_filter(predicate);
887
888 let (views, buffers, nulls) = match (self.truthy_view, self.falsy_view) {
889 (Some(truthy), Some(falsy)) => Self::get_views_for_non_nullable(
890 predicate,
891 result_len,
892 truthy,
893 Arc::clone(&self.truthy_buffers),
894 falsy,
895 Arc::clone(&self.falsy_buffers),
896 )?,
897 (Some(truthy), None) => Self::get_views_for_single_non_nullable(
898 predicate,
899 truthy,
900 Arc::clone(&self.truthy_buffers),
901 ),
902 (None, Some(falsy)) => {
903 let predicate = predicate.not();
904 Self::get_views_for_single_non_nullable(
905 predicate,
906 falsy,
907 Arc::clone(&self.falsy_buffers),
908 )
909 }
910 (None, None) => {
911 (
913 vec![0; result_len].into(),
914 empty_arc_buffers(),
915 Some(NullBuffer::new_null(result_len)),
916 )
917 }
918 };
919
920 let result = unsafe { GenericByteViewArray::<T>::new_unchecked(views, buffers, nulls) };
921 Ok(Arc::new(result))
922 }
923}
924
925#[cfg(test)]
926mod test {
927 use super::*;
928 use arrow_array::types::Int32Type;
929
930 #[test]
931 fn test_count_true_runs() {
932 let assert_runs = |values: &[bool], expected| {
933 let mask: BooleanBuffer = values.iter().copied().collect();
934 assert_eq!(count_true_runs(&mask), expected, "mask: {values:?}");
935 };
936
937 assert_runs(&[], 0);
938 assert_runs(&[false, false, false], 0);
939 assert_runs(&[true, true, true], 1);
940 assert_runs(&[true, false, true, true, false, true], 3);
941
942 let mut values = vec![false; 130];
944 values[0] = true;
945 values[63..66].fill(true);
946 values[128..].fill(true);
947 assert_runs(&values, 3);
948
949 let mut offset_values = vec![false; 135];
951 offset_values[3..133].copy_from_slice(&values);
952 let offset_mask: BooleanBuffer = offset_values.into_iter().collect();
953 assert_eq!(count_true_runs(&offset_mask.slice(3, 130)), 3);
954 }
955
956 #[test]
957 fn test_should_use_interleave() {
958 let short: BooleanBuffer = (0..64).map(|i| i % 2 == 0).collect();
959 assert!(!should_use_interleave(&short));
960
961 let fragmented: BooleanBuffer = (0..8192).map(|i| i % 2 == 0).collect();
962 assert!(should_use_interleave(&fragmented));
963
964 let long_runs: BooleanBuffer = (0..8192).map(|i| i < 4096).collect();
965 assert!(!should_use_interleave(&long_runs));
966
967 let sparse: BooleanBuffer = (0..8192).map(|i| i % 10 == 0).collect();
968 assert!(!should_use_interleave(&sparse));
969
970 let dense: BooleanBuffer = (0..8192).map(|i| i % 10 != 0).collect();
971 assert!(!should_use_interleave(&dense));
972
973 let fragmented_head: BooleanBuffer = (0..8192).map(|i| i < 256 && i % 2 == 0).collect();
974 assert!(!should_use_interleave(&fragmented_head));
975
976 let fragmented_edges: BooleanBuffer = (0..8192)
977 .map(|i| !(256..7936).contains(&i) && i % 2 == 0)
978 .collect();
979 assert!(!should_use_interleave(&fragmented_edges));
980
981 let offset: BooleanBuffer = (0..8195).map(|i| i >= 3 && i % 2 == 1).collect();
983 assert!(should_use_interleave(&offset.slice(3, 8192)));
984 }
985
986 #[test]
987 fn test_interleave_arrays() {
988 let mask = BooleanArray::from(vec![Some(true), None, Some(true), Some(false)]);
989 let mask = maybe_prep_null_mask_filter(&mask);
990 let truthy = Int32Array::from(vec![Some(1), None, Some(3), Some(4)]).to_data();
991 let falsy = Int32Array::from(vec![Some(10), Some(20), None, Some(40)]).to_data();
992 let expected = Int32Array::from(vec![Some(1), Some(20), Some(3), Some(40)]);
993
994 let actual = interleave_arrays(&mask, &truthy, &falsy).unwrap();
995 assert_eq!(actual.as_primitive::<Int32Type>(), &expected);
996 }
997
998 #[test]
999 fn test_zip_fragmented_array_mask() {
1000 let mask: BooleanArray = (0..8192)
1001 .map(|i| match i % 3 {
1002 0 => Some(true),
1003 1 => Some(false),
1004 _ => None,
1005 })
1006 .collect();
1007 let truthy: Int32Array = (0..8192).map(|i| (i % 7 != 0).then_some(i)).collect();
1008 let falsy: Int32Array = (0..8192).map(|i| (i % 11 != 0).then_some(-i)).collect();
1009 let expected: Int32Array = (0..8192)
1010 .map(|i| {
1011 let array = if i % 3 == 0 { &truthy } else { &falsy };
1012 array.is_valid(i).then(|| array.value(i))
1013 })
1014 .collect();
1015
1016 let actual = zip(&mask, &truthy, &falsy).unwrap();
1017 assert_eq!(actual.as_primitive::<Int32Type>(), &expected);
1018 }
1019
1020 #[test]
1021 fn test_zip_kernel_one() {
1022 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1023 let b = Int32Array::from(vec![None, Some(3), Some(6), Some(7), Some(3)]);
1024 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1025 let out = zip(&mask, &a, &b).unwrap();
1026 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1027 let expected = Int32Array::from(vec![Some(5), None, Some(6), Some(7), Some(1)]);
1028 assert_eq!(actual, &expected);
1029 }
1030
1031 #[test]
1032 fn test_zip_kernel_two() {
1033 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1034 let b = Int32Array::from(vec![None, Some(3), Some(6), Some(7), Some(3)]);
1035 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1036 let out = zip(&mask, &a, &b).unwrap();
1037 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1038 let expected = Int32Array::from(vec![None, Some(3), Some(7), None, Some(3)]);
1039 assert_eq!(actual, &expected);
1040 }
1041
1042 #[test]
1043 fn test_zip_kernel_scalar_falsy_1() {
1044 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1045
1046 let fallback = Scalar::new(Int32Array::from_value(42, 1));
1047
1048 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1049 let out = zip(&mask, &a, &fallback).unwrap();
1050 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1051 let expected = Int32Array::from(vec![Some(5), None, Some(42), Some(42), Some(1)]);
1052 assert_eq!(actual, &expected);
1053 }
1054
1055 #[test]
1056 fn test_zip_kernel_scalar_falsy_2() {
1057 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1058
1059 let fallback = Scalar::new(Int32Array::from_value(42, 1));
1060
1061 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1062 let out = zip(&mask, &a, &fallback).unwrap();
1063 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1064 let expected = Int32Array::from(vec![Some(42), Some(42), Some(7), None, Some(42)]);
1065 assert_eq!(actual, &expected);
1066 }
1067
1068 #[test]
1069 fn test_zip_kernel_scalar_truthy_1() {
1070 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1071
1072 let fallback = Scalar::new(Int32Array::from_value(42, 1));
1073
1074 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1075 let out = zip(&mask, &fallback, &a).unwrap();
1076 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1077 let expected = Int32Array::from(vec![Some(42), Some(42), Some(7), None, Some(42)]);
1078 assert_eq!(actual, &expected);
1079 }
1080
1081 #[test]
1082 fn test_zip_kernel_scalar_truthy_2() {
1083 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
1084
1085 let fallback = Scalar::new(Int32Array::from_value(42, 1));
1086
1087 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1088 let out = zip(&mask, &fallback, &a).unwrap();
1089 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1090 let expected = Int32Array::from(vec![Some(5), None, Some(42), Some(42), Some(1)]);
1091 assert_eq!(actual, &expected);
1092 }
1093
1094 #[test]
1095 fn test_zip_kernel_scalar_both_mask_ends_with_true() {
1096 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1097 let scalar_falsy = Scalar::new(Int32Array::from_value(123, 1));
1098
1099 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1100 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1101 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1102 let expected = Int32Array::from(vec![Some(42), Some(42), Some(123), Some(123), Some(42)]);
1103 assert_eq!(actual, &expected);
1104 }
1105
1106 #[test]
1107 fn test_zip_kernel_scalar_both_mask_ends_with_false() {
1108 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1109 let scalar_falsy = Scalar::new(Int32Array::from_value(123, 1));
1110
1111 let mask = BooleanArray::from(vec![true, true, false, true, false, false]);
1112 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1113 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1114 let expected = Int32Array::from(vec![
1115 Some(42),
1116 Some(42),
1117 Some(123),
1118 Some(42),
1119 Some(123),
1120 Some(123),
1121 ]);
1122 assert_eq!(actual, &expected);
1123 }
1124
1125 #[test]
1126 fn test_zip_kernel_primitive_scalar_none_1() {
1127 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1128 let scalar_falsy = Scalar::new(Int32Array::new_null(1));
1129
1130 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1131 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1132 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1133 let expected = Int32Array::from(vec![Some(42), Some(42), None, None, Some(42)]);
1134 assert_eq!(actual, &expected);
1135 }
1136
1137 #[test]
1138 fn test_zip_kernel_primitive_scalar_none_2() {
1139 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1140 let scalar_falsy = Scalar::new(Int32Array::new_null(1));
1141
1142 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1143 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1144 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1145 let expected = Int32Array::from(vec![None, None, Some(42), Some(42), None]);
1146 assert_eq!(actual, &expected);
1147 }
1148
1149 #[test]
1150 fn test_zip_kernel_primitive_scalar_both_null() {
1151 let scalar_truthy = Scalar::new(Int32Array::new_null(1));
1152 let scalar_falsy = Scalar::new(Int32Array::new_null(1));
1153
1154 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1155 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1156 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1157 let expected = Int32Array::from(vec![None, None, None, None, None]);
1158 assert_eq!(actual, &expected);
1159 }
1160
1161 #[test]
1162 fn test_zip_primitive_array_with_nulls_is_mask_should_be_treated_as_false() {
1163 let truthy = Int32Array::from_iter_values(vec![1, 2, 3, 4, 5, 6]);
1164 let falsy = Int32Array::from_iter_values(vec![7, 8, 9, 10, 11, 12]);
1165
1166 let mask = {
1167 let booleans = BooleanBuffer::from(vec![true, true, false, true, false, false]);
1168 let nulls = NullBuffer::from(vec![
1169 true, true, true,
1170 false, true, true,
1172 ]);
1173 BooleanArray::new(booleans, Some(nulls))
1174 };
1175 let out = zip(&mask, &truthy, &falsy).unwrap();
1176 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1177 let expected = Int32Array::from(vec![
1178 Some(1),
1179 Some(2),
1180 Some(9),
1181 Some(10), Some(11),
1183 Some(12),
1184 ]);
1185 assert_eq!(actual, &expected);
1186 }
1187
1188 #[test]
1189 fn test_zip_kernel_primitive_scalar_with_boolean_array_mask_with_nulls_should_be_treated_as_false()
1190 {
1191 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1192 let scalar_falsy = Scalar::new(Int32Array::from_value(123, 1));
1193
1194 let mask = {
1195 let booleans = BooleanBuffer::from(vec![true, true, false, true, false, false]);
1196 let nulls = NullBuffer::from(vec![
1197 true, true, true,
1198 false, true, true,
1200 ]);
1201 BooleanArray::new(booleans, Some(nulls))
1202 };
1203 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1204 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
1205 let expected = Int32Array::from(vec![
1206 Some(42),
1207 Some(42),
1208 Some(123),
1209 Some(123), Some(123),
1211 Some(123),
1212 ]);
1213 assert_eq!(actual, &expected);
1214 }
1215
1216 #[test]
1217 fn test_zip_string_array_with_nulls_is_mask_should_be_treated_as_false() {
1218 let truthy = StringArray::from_iter_values(vec!["1", "2", "3", "4", "5", "6"]);
1219 let falsy = StringArray::from_iter_values(vec!["7", "8", "9", "10", "11", "12"]);
1220
1221 let mask = {
1222 let booleans = BooleanBuffer::from(vec![true, true, false, true, false, false]);
1223 let nulls = NullBuffer::from(vec![
1224 true, true, true,
1225 false, true, true,
1227 ]);
1228 BooleanArray::new(booleans, Some(nulls))
1229 };
1230 let out = zip(&mask, &truthy, &falsy).unwrap();
1231 let actual = out.as_string::<i32>();
1232 let expected = StringArray::from_iter_values(vec![
1233 "1", "2", "9", "10", "11", "12",
1235 ]);
1236 assert_eq!(actual, &expected);
1237 }
1238
1239 #[test]
1240 fn test_zip_kernel_large_string_scalar_with_boolean_array_mask_with_nulls_should_be_treated_as_false()
1241 {
1242 let scalar_truthy = Scalar::new(LargeStringArray::from_iter_values(["test"]));
1243 let scalar_falsy = Scalar::new(LargeStringArray::from_iter_values(["something else"]));
1244
1245 let mask = {
1246 let booleans = BooleanBuffer::from(vec![true, true, false, true, false, false]);
1247 let nulls = NullBuffer::from(vec![
1248 true, true, true,
1249 false, true, true,
1251 ]);
1252 BooleanArray::new(booleans, Some(nulls))
1253 };
1254 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1255 let actual = out.as_any().downcast_ref::<LargeStringArray>().unwrap();
1256 let expected = LargeStringArray::from_iter(vec![
1257 Some("test"),
1258 Some("test"),
1259 Some("something else"),
1260 Some("something else"), Some("something else"),
1262 Some("something else"),
1263 ]);
1264 assert_eq!(actual, &expected);
1265 }
1266
1267 #[test]
1268 fn test_zip_kernel_bytes_scalar_none_1() {
1269 let scalar_truthy = Scalar::new(StringArray::from_iter_values(["hello"]));
1270 let scalar_falsy = Scalar::new(StringArray::new_null(1));
1271
1272 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1273 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1274 let actual = out.as_any().downcast_ref::<StringArray>().unwrap();
1275 let expected = StringArray::from_iter(vec![
1276 Some("hello"),
1277 Some("hello"),
1278 None,
1279 None,
1280 Some("hello"),
1281 ]);
1282 assert_eq!(actual, &expected);
1283 }
1284
1285 #[test]
1286 fn test_zip_kernel_bytes_scalar_none_2() {
1287 let scalar_truthy = Scalar::new(StringArray::new_null(1));
1288 let scalar_falsy = Scalar::new(StringArray::from_iter_values(["hello"]));
1289
1290 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1291 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1292 let actual = out.as_any().downcast_ref::<StringArray>().unwrap();
1293 let expected = StringArray::from_iter(vec![None, None, Some("hello"), Some("hello"), None]);
1294 assert_eq!(actual, &expected);
1295 }
1296
1297 #[test]
1298 fn test_zip_kernel_bytes_scalar_both() {
1299 let scalar_truthy = Scalar::new(StringArray::from_iter_values(["test"]));
1300 let scalar_falsy = Scalar::new(StringArray::from_iter_values(["something else"]));
1301
1302 let mask = BooleanArray::from(vec![true, true, false, true, false, false]);
1304 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1305 let actual = out.as_any().downcast_ref::<StringArray>().unwrap();
1306 let expected = StringArray::from_iter(vec![
1307 Some("test"),
1308 Some("test"),
1309 Some("something else"),
1310 Some("test"),
1311 Some("something else"),
1312 Some("something else"),
1313 ]);
1314 assert_eq!(actual, &expected);
1315 }
1316
1317 #[test]
1318 fn test_zip_scalar_bytes_offset_overflow() {
1319 let value = vec![0_u8; 65_536];
1322 let large = Scalar::new(BinaryArray::from_iter_values([value.as_slice()]));
1323 let empty = Scalar::new(BinaryArray::from_iter_values([b"".as_slice()]));
1324 let mask = BooleanArray::from_iter((0..65_536).map(|i| Some(i % 2 == 0)));
1325
1326 for (truthy, falsy) in [(&large, &empty), (&empty, &large)] {
1327 assert!(matches!(
1328 zip(&mask, truthy, falsy),
1329 Err(ArrowError::OffsetOverflowError(2_147_483_648))
1330 ));
1331 }
1332 }
1333
1334 #[test]
1335 fn test_zip_scalar_bytes_only_taking_one_side() {
1336 let mask_len = 5;
1337 let all_true_mask = BooleanArray::from(vec![true; mask_len]);
1338 let all_false_mask = BooleanArray::from(vec![false; mask_len]);
1339
1340 let null_scalar = Scalar::new(StringArray::new_null(1));
1341 let non_null_scalar_1 = Scalar::new(StringArray::from_iter_values(["test"]));
1342 let non_null_scalar_2 = Scalar::new(StringArray::from_iter_values(["something else"]));
1343
1344 {
1345 let out = zip(&all_true_mask, &null_scalar, &non_null_scalar_1).unwrap();
1348 let actual = out.as_string::<i32>();
1349 let expected = StringArray::from_iter(std::iter::repeat_n(None::<&str>, mask_len));
1350 assert_eq!(actual, &expected);
1351 }
1352
1353 {
1354 let out = zip(&all_false_mask, &null_scalar, &non_null_scalar_1).unwrap();
1357 let actual = out.as_string::<i32>();
1358 let expected = StringArray::from_iter(std::iter::repeat_n(Some("test"), mask_len));
1359 assert_eq!(actual, &expected);
1360 }
1361
1362 {
1363 let out = zip(&all_true_mask, &non_null_scalar_1, &null_scalar).unwrap();
1366 let actual = out.as_string::<i32>();
1367 let expected = StringArray::from_iter(std::iter::repeat_n(Some("test"), mask_len));
1368 assert_eq!(actual, &expected);
1369 }
1370
1371 {
1372 let out = zip(&all_false_mask, &non_null_scalar_1, &null_scalar).unwrap();
1375 let actual = out.as_string::<i32>();
1376 let expected = StringArray::from_iter(std::iter::repeat_n(None::<&str>, mask_len));
1377 assert_eq!(actual, &expected);
1378 }
1379
1380 {
1381 let out = zip(&all_true_mask, &non_null_scalar_1, &non_null_scalar_2).unwrap();
1384 let actual = out.as_string::<i32>();
1385 let expected = StringArray::from_iter(std::iter::repeat_n(Some("test"), mask_len));
1386 assert_eq!(actual, &expected);
1387 }
1388
1389 {
1390 let out = zip(&all_false_mask, &non_null_scalar_1, &non_null_scalar_2).unwrap();
1393 let actual = out.as_string::<i32>();
1394 let expected =
1395 StringArray::from_iter(std::iter::repeat_n(Some("something else"), mask_len));
1396 assert_eq!(actual, &expected);
1397 }
1398
1399 {
1400 let mask = BooleanArray::from(vec![true, false, true, false, true]);
1403 let out = zip(&mask, &null_scalar, &null_scalar).unwrap();
1404 let actual = out.as_string::<i32>();
1405 let expected = StringArray::from_iter(std::iter::repeat_n(None::<&str>, mask_len));
1406 assert_eq!(actual, &expected);
1407 }
1408 }
1409
1410 #[test]
1411 fn test_scalar_zipper() {
1412 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
1413 let scalar_falsy = Scalar::new(Int32Array::from_value(123, 1));
1414
1415 let mask = BooleanArray::from(vec![false, false, true, true, false]);
1416
1417 let scalar_zipper = ScalarZipper::try_new(&scalar_truthy, &scalar_falsy).unwrap();
1418 let out = scalar_zipper.zip(&mask).unwrap();
1419 let actual = out.as_primitive::<Int32Type>();
1420 let expected = Int32Array::from(vec![Some(123), Some(123), Some(42), Some(42), Some(123)]);
1421 assert_eq!(actual, &expected);
1422
1423 let mask = BooleanArray::from(vec![true, false, true]);
1425 let out = scalar_zipper.zip(&mask).unwrap();
1426 let actual = out.as_primitive::<Int32Type>();
1427 let expected = Int32Array::from(vec![Some(42), Some(123), Some(42)]);
1428 assert_eq!(actual, &expected);
1429 }
1430
1431 #[test]
1432 fn test_zip_kernel_scalar_strings() {
1433 let scalar_truthy = Scalar::new(StringArray::from(vec!["hello"]));
1434 let scalar_falsy = Scalar::new(StringArray::from(vec!["world"]));
1435
1436 let mask = BooleanArray::from(vec![true, false, true, false, true]);
1437 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1438 let actual = out.as_string::<i32>();
1439 let expected = StringArray::from(vec![
1440 Some("hello"),
1441 Some("world"),
1442 Some("hello"),
1443 Some("world"),
1444 Some("hello"),
1445 ]);
1446 assert_eq!(actual, &expected);
1447 }
1448
1449 #[test]
1450 fn test_zip_kernel_scalar_binary() {
1451 let truthy_bytes: &[u8] = b"\xFF\xFE\xFD";
1452 let falsy_bytes: &[u8] = b"world";
1453 let scalar_truthy = Scalar::new(BinaryArray::from_iter_values(
1454 vec![truthy_bytes],
1456 ));
1457 let scalar_falsy = Scalar::new(BinaryArray::from_iter_values(vec![falsy_bytes]));
1458
1459 let mask = BooleanArray::from(vec![true, false, true, false, true]);
1460 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1461 let actual = out.as_binary::<i32>();
1462 let expected = BinaryArray::from(vec![
1463 Some(truthy_bytes),
1464 Some(falsy_bytes),
1465 Some(truthy_bytes),
1466 Some(falsy_bytes),
1467 Some(truthy_bytes),
1468 ]);
1469 assert_eq!(actual, &expected);
1470 }
1471
1472 #[test]
1473 fn test_zip_kernel_scalar_large_binary() {
1474 let truthy_bytes: &[u8] = b"hey";
1475 let falsy_bytes: &[u8] = b"world";
1476 let scalar_truthy = Scalar::new(LargeBinaryArray::from_iter_values(vec![truthy_bytes]));
1477 let scalar_falsy = Scalar::new(LargeBinaryArray::from_iter_values(vec![falsy_bytes]));
1478
1479 let mask = BooleanArray::from(vec![true, false, true, false, true]);
1480 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1481 let actual = out.as_binary::<i64>();
1482 let expected = LargeBinaryArray::from(vec![
1483 Some(truthy_bytes),
1484 Some(falsy_bytes),
1485 Some(truthy_bytes),
1486 Some(falsy_bytes),
1487 Some(truthy_bytes),
1488 ]);
1489 assert_eq!(actual, &expected);
1490 }
1491
1492 #[test]
1494 fn test_zip_decimal_with_custom_precision_and_scale() {
1495 let arr = Decimal128Array::from_iter_values([12345, 456, 7890, -123223423432432])
1496 .with_precision_and_scale(20, 2)
1497 .unwrap();
1498
1499 let arr: ArrayRef = Arc::new(arr);
1500
1501 let scalar_1 = Scalar::new(arr.slice(0, 1));
1502 let scalar_2 = Scalar::new(arr.slice(1, 1));
1503 let null_scalar = Scalar::new(new_null_array(arr.data_type(), 1));
1504 let array_1: ArrayRef = arr.slice(0, 2);
1505 let array_2: ArrayRef = arr.slice(2, 2);
1506
1507 test_zip_output_data_types_for_input(scalar_1, scalar_2, null_scalar, array_1, array_2);
1508 }
1509
1510 #[test]
1512 fn test_zip_timestamp_with_timezone() {
1513 let arr = TimestampSecondArray::from(vec![0, 1000, 2000, 4000])
1514 .with_timezone("+01:00".to_string());
1515
1516 let arr: ArrayRef = Arc::new(arr);
1517
1518 let scalar_1 = Scalar::new(arr.slice(0, 1));
1519 let scalar_2 = Scalar::new(arr.slice(1, 1));
1520 let null_scalar = Scalar::new(new_null_array(arr.data_type(), 1));
1521 let array_1: ArrayRef = arr.slice(0, 2);
1522 let array_2: ArrayRef = arr.slice(2, 2);
1523
1524 test_zip_output_data_types_for_input(scalar_1, scalar_2, null_scalar, array_1, array_2);
1525 }
1526
1527 fn test_zip_output_data_types_for_input(
1528 scalar_1: Scalar<ArrayRef>,
1529 scalar_2: Scalar<ArrayRef>,
1530 null_scalar: Scalar<ArrayRef>,
1531 array_1: ArrayRef,
1532 array_2: ArrayRef,
1533 ) {
1534 test_zip_output_data_type(&scalar_1, &scalar_2, 10);
1536
1537 test_zip_output_data_type(&null_scalar, &scalar_1, 10);
1539 test_zip_output_data_type(&scalar_1, &null_scalar, 10);
1540
1541 test_zip_output_data_type(&array_1.as_ref(), &scalar_1, array_1.len());
1543 test_zip_output_data_type(&scalar_1, &array_1.as_ref(), array_1.len());
1544
1545 test_zip_output_data_type(&array_1.as_ref(), &null_scalar, array_1.len());
1547
1548 test_zip_output_data_type(&null_scalar, &array_1.as_ref(), array_1.len());
1549
1550 test_zip_output_data_type(&array_1.as_ref(), &array_2.as_ref(), array_1.len());
1552 }
1553
1554 fn test_zip_output_data_type(truthy: &dyn Datum, falsy: &dyn Datum, mask_length: usize) {
1555 let expected_data_type = truthy.get().0.data_type().clone();
1556 assert_eq!(&expected_data_type, falsy.get().0.data_type());
1557
1558 let mask_all_true = BooleanArray::from(vec![true; mask_length]);
1560 let mask_all_false = BooleanArray::from(vec![false; mask_length]);
1561 let mask_some_true_and_false =
1562 BooleanArray::from((0..mask_length).map(|i| i % 2 == 0).collect::<Vec<bool>>());
1563
1564 for mask in [&mask_all_true, &mask_all_false, &mask_some_true_and_false] {
1565 let out = zip(mask, truthy, falsy).unwrap();
1566 assert_eq!(out.data_type(), &expected_data_type);
1567 }
1568 }
1569
1570 #[test]
1571 fn zip_scalar_fallback_impl() {
1572 let truthy_list_item_scalar = Some(vec![Some(1), None, Some(3)]);
1573 let truthy_list_array_scalar =
1574 Scalar::new(ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
1575 truthy_list_item_scalar.clone(),
1576 ]));
1577 let falsy_list_item_scalar = Some(vec![None, Some(2), Some(4)]);
1578 let falsy_list_array_scalar =
1579 Scalar::new(ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
1580 falsy_list_item_scalar.clone(),
1581 ]));
1582 let mask = BooleanArray::from(vec![true, false, true, false, false, true, false]);
1583 let out = zip(&mask, &truthy_list_array_scalar, &falsy_list_array_scalar).unwrap();
1584 let actual = out.as_list::<i32>();
1585
1586 let expected = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
1587 truthy_list_item_scalar.clone(),
1588 falsy_list_item_scalar.clone(),
1589 truthy_list_item_scalar.clone(),
1590 falsy_list_item_scalar.clone(),
1591 falsy_list_item_scalar.clone(),
1592 truthy_list_item_scalar.clone(),
1593 falsy_list_item_scalar.clone(),
1594 ]);
1595 assert_eq!(actual, &expected);
1596 }
1597
1598 #[test]
1599 fn test_zip_kernel_scalar_strings_array_view() {
1600 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["hello"]));
1601 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["world"]));
1602
1603 let mask = BooleanArray::from(vec![true, false, true, false]);
1604 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1605 let actual = out.as_string_view();
1606 let expected = StringViewArray::from(vec![
1607 Some("hello"),
1608 Some("world"),
1609 Some("hello"),
1610 Some("world"),
1611 ]);
1612 assert_eq!(actual, &expected);
1613 }
1614
1615 #[test]
1616 fn test_zip_kernel_scalar_binary_array_view() {
1617 let scalar_truthy = Scalar::new(BinaryViewArray::from_iter_values(vec![b"hello"]));
1618 let scalar_falsy = Scalar::new(BinaryViewArray::from_iter_values(vec![b"world"]));
1619
1620 let mask = BooleanArray::from(vec![true, false]);
1621 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1622 let actual = out.as_byte_view();
1623 let expected = BinaryViewArray::from_iter_values(vec![b"hello", b"world"]);
1624 assert_eq!(actual, &expected);
1625 }
1626
1627 #[test]
1628 fn test_zip_kernel_scalar_strings_array_view_with_nulls() {
1629 let scalar_truthy = Scalar::new(StringViewArray::from_iter_values(["hello"]));
1630 let scalar_falsy = Scalar::new(StringViewArray::new_null(1));
1631
1632 let mask = BooleanArray::from(vec![true, true, false, false, true]);
1633 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1634 let actual = out.as_any().downcast_ref::<StringViewArray>().unwrap();
1635 let expected = StringViewArray::from_iter(vec![
1636 Some("hello"),
1637 Some("hello"),
1638 None,
1639 None,
1640 Some("hello"),
1641 ]);
1642 assert_eq!(actual, &expected);
1643 }
1644
1645 #[test]
1646 fn test_zip_kernel_scalar_strings_array_view_all_true_null() {
1647 let scalar_truthy = Scalar::new(StringViewArray::new_null(1));
1648 let scalar_falsy = Scalar::new(StringViewArray::new_null(1));
1649 let mask = BooleanArray::from(vec![true, true]);
1650 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1651 let actual = out.as_any().downcast_ref::<StringViewArray>().unwrap();
1652 let expected = StringViewArray::from_iter(vec![None::<String>, None]);
1653 assert_eq!(actual, &expected);
1654 }
1655
1656 #[test]
1657 fn test_zip_kernel_scalar_strings_array_view_all_false_null() {
1658 let scalar_truthy = Scalar::new(StringViewArray::new_null(1));
1659 let scalar_falsy = Scalar::new(StringViewArray::new_null(1));
1660 let mask = BooleanArray::from(vec![false, false]);
1661 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1662 let actual = out.as_any().downcast_ref::<StringViewArray>().unwrap();
1663 let expected = StringViewArray::from_iter(vec![None::<String>, None]);
1664 assert_eq!(actual, &expected);
1665 }
1666
1667 #[test]
1668 fn test_zip_kernel_scalar_string_array_view_all_true() {
1669 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["hello"]));
1670 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["world"]));
1671
1672 let mask = BooleanArray::from(vec![true, true]);
1673 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1674 let actual = out.as_string_view();
1675 let expected = StringViewArray::from(vec![Some("hello"), Some("hello")]);
1676 assert_eq!(actual, &expected);
1677 }
1678
1679 #[test]
1680 fn test_zip_kernel_scalar_string_array_view_all_false() {
1681 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["hello"]));
1682 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["world"]));
1683
1684 let mask = BooleanArray::from(vec![false, false]);
1685 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1686 let actual = out.as_string_view();
1687 let expected = StringViewArray::from(vec![Some("world"), Some("world")]);
1688 assert_eq!(actual, &expected);
1689 }
1690
1691 #[test]
1692 fn test_zip_kernel_scalar_strings_large_strings() {
1693 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["longer than 12 bytes"]));
1694 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["another longer than 12 bytes"]));
1695
1696 let mask = BooleanArray::from(vec![true, false]);
1697 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1698 let actual = out.as_string_view();
1699 let expected = StringViewArray::from(vec![
1700 Some("longer than 12 bytes"),
1701 Some("another longer than 12 bytes"),
1702 ]);
1703 assert_eq!(actual, &expected);
1704 }
1705
1706 #[test]
1707 fn test_zip_kernel_scalar_strings_array_view_large_short_strings() {
1708 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["hello"]));
1709 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["longer than 12 bytes"]));
1710
1711 let mask = BooleanArray::from(vec![true, false, true, false]);
1712 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1713 let actual = out.as_string_view();
1714 let expected = StringViewArray::from(vec![
1715 Some("hello"),
1716 Some("longer than 12 bytes"),
1717 Some("hello"),
1718 Some("longer than 12 bytes"),
1719 ]);
1720 assert_eq!(actual, &expected);
1721 }
1722 #[test]
1723 fn test_zip_kernel_scalar_strings_array_view_large_all_true() {
1724 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["longer than 12 bytes"]));
1725 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["another longer than 12 bytes"]));
1726
1727 let mask = BooleanArray::from(vec![true, true]);
1728 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1729 let actual = out.as_string_view();
1730 let expected = StringViewArray::from(vec![
1731 Some("longer than 12 bytes"),
1732 Some("longer than 12 bytes"),
1733 ]);
1734 assert_eq!(actual, &expected);
1735 }
1736
1737 #[test]
1738 fn test_zip_kernel_scalar_strings_array_view_large_all_false() {
1739 let scalar_truthy = Scalar::new(StringViewArray::from(vec!["longer than 12 bytes"]));
1740 let scalar_falsy = Scalar::new(StringViewArray::from(vec!["another longer than 12 bytes"]));
1741
1742 let mask = BooleanArray::from(vec![false, false]);
1743 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
1744 let actual = out.as_string_view();
1745 let expected = StringViewArray::from(vec![
1746 Some("another longer than 12 bytes"),
1747 Some("another longer than 12 bytes"),
1748 ]);
1749 assert_eq!(actual, &expected);
1750 }
1751}