Skip to main content

arrow_select/
take.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines take kernel for [Array]
19
20use std::fmt::Display;
21use std::mem::ManuallyDrop;
22use std::sync::Arc;
23
24use arrow_array::builder::{BufferBuilder, UInt32Builder};
25use arrow_array::cast::AsArray;
26use arrow_array::types::*;
27use arrow_array::*;
28use arrow_buffer::{
29    ArrowNativeType, BooleanBuffer, Buffer, MutableBuffer, NullBuffer, OffsetBuffer, RunEndBuffer,
30    ScalarBuffer, bit_util,
31};
32use arrow_cmp::make_comparator;
33use arrow_data::transform::MutableArrayData;
34use arrow_schema::{ArrowError, DataType, FieldRef, SortOptions, UnionMode};
35
36use num_traits::Zero;
37
38/// Take elements by index from [Array], creating a new [Array] from those indexes.
39///
40/// ```text
41/// ┌─────────────────┐      ┌─────────┐                              ┌─────────────────┐
42/// │        A        │      │    0    │                              │        A        │
43/// ├─────────────────┤      ├─────────┤                              ├─────────────────┤
44/// │        D        │      │    2    │                              │        B        │
45/// ├─────────────────┤      ├─────────┤   take(values, indices)      ├─────────────────┤
46/// │        B        │      │    3    │ ─────────────────────────▶   │        C        │
47/// ├─────────────────┤      ├─────────┤                              ├─────────────────┤
48/// │        C        │      │    1    │                              │        D        │
49/// ├─────────────────┤      └─────────┘                              └─────────────────┘
50/// │        E        │
51/// └─────────────────┘
52///    values array          indices array                              result
53/// ```
54///
55/// For selecting values by index from multiple arrays see [`crate::interleave`]
56///
57/// Note that this kernel, similar to other kernels in this crate,
58/// will avoid allocating where not necessary. Consequently
59/// the returned array may share buffers with the inputs
60///
61/// # Errors
62/// This function errors whenever:
63/// * An index cannot be casted to `usize` (typically 32 bit architectures)
64/// * An index is out of bounds and `options` is set to check bounds.
65///
66/// # Panics
67///
68/// When `options` is not set to check bounds, taking indexes after `len` will panic.
69///
70/// # See also
71/// * [`BatchCoalescer`]: to filter multiple [`RecordBatch`] and coalesce
72///   the results into a single array.
73///
74/// [`BatchCoalescer`]: crate::coalesce::BatchCoalescer
75///
76/// # Examples
77/// ```
78/// # use arrow_array::{StringArray, UInt32Array, cast::AsArray};
79/// # use arrow_select::take::take;
80/// let values = StringArray::from(vec!["zero", "one", "two"]);
81///
82/// // Take items at index 2, and 1:
83/// let indices = UInt32Array::from(vec![2, 1]);
84/// let taken = take(&values, &indices, None).unwrap();
85/// let taken = taken.as_string::<i32>();
86///
87/// assert_eq!(*taken, StringArray::from(vec!["two", "one"]));
88/// ```
89pub fn take(
90    values: &dyn Array,
91    indices: &dyn Array,
92    options: Option<TakeOptions>,
93) -> Result<ArrayRef, ArrowError> {
94    let options = options.unwrap_or_default();
95    downcast_integer_array!(
96        indices => {
97            if options.check_bounds {
98                check_bounds(values.len(), indices)?;
99            }
100            let indices = indices.to_indices();
101            take_impl(values, &indices)
102        },
103        d => Err(ArrowError::InvalidArgumentError(format!("Take only supported for integers, got {d:?}")))
104    )
105}
106
107/// For each [ArrayRef] in the [`Vec<ArrayRef>`], take elements by index and create a new
108/// [`Vec<ArrayRef>`] from those indices.
109///
110/// ```text
111/// ┌────────┬────────┐
112/// │        │        │           ┌────────┐                                ┌────────┬────────┐
113/// │   A    │   1    │           │        │                                │        │        │
114/// ├────────┼────────┤           │   0    │                                │   A    │   1    │
115/// │        │        │           ├────────┤                                ├────────┼────────┤
116/// │   D    │   4    │           │        │                                │        │        │
117/// ├────────┼────────┤           │   2    │  take_arrays(values,indices)   │   B    │   2    │
118/// │        │        │           ├────────┤                                ├────────┼────────┤
119/// │   B    │   2    │           │        │  ───────────────────────────►  │        │        │
120/// ├────────┼────────┤           │   3    │                                │   C    │   3    │
121/// │        │        │           ├────────┤                                ├────────┼────────┤
122/// │   C    │   3    │           │        │                                │        │        │
123/// ├────────┼────────┤           │   1    │                                │   D    │   4    │
124/// │        │        │           └────────┘                                └────────┼────────┘
125/// │   E    │   5    │
126/// └────────┴────────┘
127///    values arrays             indices array                                      result
128/// ```
129///
130/// # Errors
131/// This function errors whenever:
132/// * An index cannot be casted to `usize` (typically 32 bit architectures)
133/// * An index is out of bounds and `options` is set to check bounds.
134///
135/// # Panics
136///
137/// When `options` is not set to check bounds, taking indexes after `len` will panic.
138///
139/// # Examples
140/// ```
141/// # use std::sync::Arc;
142/// # use arrow_array::{StringArray, UInt32Array, cast::AsArray};
143/// # use arrow_select::take::{take, take_arrays};
144/// let string_values = Arc::new(StringArray::from(vec!["zero", "one", "two"]));
145/// let values = Arc::new(UInt32Array::from(vec![0, 1, 2]));
146///
147/// // Take items at index 2, and 1:
148/// let indices = UInt32Array::from(vec![2, 1]);
149/// let taken_arrays = take_arrays(&[string_values, values], &indices, None).unwrap();
150/// let taken_string = taken_arrays[0].as_string::<i32>();
151/// assert_eq!(*taken_string, StringArray::from(vec!["two", "one"]));
152/// let taken_values = taken_arrays[1].as_primitive();
153/// assert_eq!(*taken_values, UInt32Array::from(vec![2, 1]));
154/// ```
155pub fn take_arrays(
156    arrays: &[ArrayRef],
157    indices: &dyn Array,
158    options: Option<TakeOptions>,
159) -> Result<Vec<ArrayRef>, ArrowError> {
160    arrays
161        .iter()
162        .map(|array| take(array.as_ref(), indices, options.clone()))
163        .collect()
164}
165
166/// Verifies that the non-null values of `indices` are all `< len`
167fn check_bounds<T: ArrowPrimitiveType>(
168    len: usize,
169    indices: &PrimitiveArray<T>,
170) -> Result<(), ArrowError>
171where
172    T::Native: Display,
173{
174    let len = match T::Native::from_usize(len) {
175        Some(len) => len,
176        None => {
177            if T::DATA_TYPE.is_integer() {
178                // the biggest representable value for T::Native is lower than len, e.g: u8::MAX < 512, no need to check bounds
179                return Ok(());
180            } else {
181                return Err(ArrowError::ComputeError("Cast to usize failed".to_string()));
182            }
183        }
184    };
185
186    if indices.null_count() > 0 {
187        indices.iter().flatten().try_for_each(|index| {
188            if index >= len {
189                return Err(ArrowError::ComputeError(format!(
190                    "Array index out of bounds, cannot get item at index {index} from {len} entries"
191                )));
192            }
193            Ok(())
194        })
195    } else {
196        let in_bounds = indices.values().iter().fold(true, |in_bounds, &i| {
197            in_bounds & (i >= T::Native::ZERO) & (i < len)
198        });
199
200        if !in_bounds {
201            for &index in indices.values() {
202                if index < T::Native::ZERO || index >= len {
203                    return Err(ArrowError::ComputeError(format!(
204                        "Array index out of bounds, cannot get item at index {index} from {len} entries"
205                    )));
206                }
207            }
208        }
209
210        Ok(())
211    }
212}
213
214#[inline(never)]
215fn take_impl<IndexType: ArrowPrimitiveType>(
216    values: &dyn Array,
217    indices: &PrimitiveArray<IndexType>,
218) -> Result<ArrayRef, ArrowError> {
219    if indices.is_empty() {
220        return Ok(new_empty_array(values.data_type()));
221    }
222    downcast_primitive_array! {
223        values => Ok(Arc::new(take_primitive(values, indices)?)),
224        DataType::Boolean => {
225            let values = values.as_any().downcast_ref::<BooleanArray>().unwrap();
226            Ok(Arc::new(take_boolean(values, indices)))
227        }
228        DataType::Utf8 => {
229            Ok(Arc::new(take_bytes(values.as_string::<i32>(), indices)?))
230        }
231        DataType::LargeUtf8 => {
232            Ok(Arc::new(take_bytes(values.as_string::<i64>(), indices)?))
233        }
234        DataType::Utf8View => {
235            Ok(Arc::new(take_byte_view(values.as_string_view(), indices)?))
236        }
237        DataType::List(_) => {
238            Ok(Arc::new(take_list::<_, Int32Type>(values.as_list(), indices)?))
239        }
240        DataType::LargeList(_) => {
241            Ok(Arc::new(take_list::<_, Int64Type>(values.as_list(), indices)?))
242        }
243        DataType::ListView(_) => {
244            Ok(Arc::new(take_list_view::<_, Int32Type>(values.as_list_view(), indices)?))
245        }
246        DataType::LargeListView(_) => {
247            Ok(Arc::new(take_list_view::<_, Int64Type>(values.as_list_view(), indices)?))
248        }
249        DataType::FixedSizeList(_, length) => {
250            let values = values
251                .as_any()
252                .downcast_ref::<FixedSizeListArray>()
253                .unwrap();
254            Ok(Arc::new(take_fixed_size_list(
255                values,
256                indices,
257                *length as u32,
258            )?))
259        }
260        DataType::Map(field, ordered) => {
261            let list_arr = ListArray::from(values.as_map().clone());
262            let list_data = take_list::<_, Int32Type>(&list_arr, indices)?;
263            let (_, offsets, entries, nulls) = list_data.into_parts();
264            let entries = entries.as_struct().clone();
265            Ok(Arc::new(MapArray::try_new(
266                field.clone(),
267                offsets,
268                entries,
269                nulls,
270                *ordered,
271            )?))
272        }
273        DataType::Struct(fields) => {
274            let array: &StructArray = values.as_struct();
275            let arrays  = array
276                .columns()
277                .iter()
278                .map(|a| take_impl(a.as_ref(), indices))
279                .collect::<Result<Vec<ArrayRef>, _>>()?;
280            let fields: Vec<(FieldRef, ArrayRef)> =
281                fields.iter().cloned().zip(arrays).collect();
282
283            // Create the null bit buffer.
284            let is_valid: Buffer = indices
285                .iter()
286                .map(|index| {
287                    if let Some(index) = index {
288                        array.is_valid(index.to_usize().unwrap())
289                    } else {
290                        false
291                    }
292                })
293                .collect();
294
295            if fields.is_empty() {
296                let nulls = NullBuffer::new(BooleanBuffer::new(is_valid, 0, indices.len()));
297                Ok(Arc::new(StructArray::new_empty_fields(indices.len(), Some(nulls))))
298            } else {
299                Ok(Arc::new(StructArray::from((fields, is_valid))) as ArrayRef)
300            }
301        }
302        DataType::Dictionary(_, _) => downcast_dictionary_array! {
303            values => Ok(Arc::new(take_dict(values, indices)?)),
304            t => unimplemented!("Take not supported for dictionary type {:?}", t)
305        }
306        DataType::RunEndEncoded(_, _) => downcast_run_array! {
307            values => Ok(Arc::new(take_run(values, indices)?)),
308            t => unimplemented!("Take not supported for run type {:?}", t)
309        }
310        DataType::Binary => {
311            Ok(Arc::new(take_bytes(values.as_binary::<i32>(), indices)?))
312        }
313        DataType::LargeBinary => {
314            Ok(Arc::new(take_bytes(values.as_binary::<i64>(), indices)?))
315        }
316        DataType::BinaryView => {
317            Ok(Arc::new(take_byte_view(values.as_binary_view(), indices)?))
318        }
319        DataType::FixedSizeBinary(size) => {
320            let values = values
321                .as_any()
322                .downcast_ref::<FixedSizeBinaryArray>()
323                .unwrap();
324            Ok(Arc::new(take_fixed_size_binary(values, indices, *size)?))
325        }
326        DataType::Null => {
327            // Take applied to a null array produces a null array.
328            if values.len() >= indices.len() {
329                // If the existing null array is as big as the indices, we can use a slice of it
330                // to avoid allocating a new null array.
331                Ok(values.slice(0, indices.len()))
332            } else {
333                // If the existing null array isn't big enough, create a new one.
334                Ok(new_null_array(&DataType::Null, indices.len()))
335            }
336        }
337        DataType::Union(fields, UnionMode::Sparse) => {
338            let mut children = Vec::with_capacity(fields.len());
339            let values = values.as_any().downcast_ref::<UnionArray>().unwrap();
340            let type_ids = take_native(values.type_ids(), indices);
341            for (type_id, _field) in fields.iter() {
342                let values = values.child(type_id);
343                let values = take_impl(values, indices)?;
344                children.push(values);
345            }
346            let array = UnionArray::try_new(fields.clone(), type_ids, None, children)?;
347            Ok(Arc::new(array))
348        }
349        DataType::Union(fields, UnionMode::Dense) => {
350            let values = values.as_any().downcast_ref::<UnionArray>().unwrap();
351
352            let type_ids = <PrimitiveArray<Int8Type>>::try_new(take_native(values.type_ids(), indices), None)?;
353            let offsets = <PrimitiveArray<Int32Type>>::try_new(take_native(values.offsets().unwrap(), indices), None)?;
354
355            let children = fields.iter()
356                .map(|(field_type_id, _)| {
357                    let mask = BooleanArray::from_unary(&type_ids, |value_type_id| value_type_id == field_type_id);
358
359                    let indices = crate::filter::filter(&offsets, &mask)?;
360
361                    let values = values.child(field_type_id);
362
363                    take_impl(values, indices.as_primitive::<Int32Type>())
364                })
365                .collect::<Result<_, _>>()?;
366
367            let mut child_offsets = [0; 128];
368
369            let offsets = type_ids.values()
370                .iter()
371                .map(|&i| {
372                    let offset = child_offsets[i as usize];
373
374                    child_offsets[i as usize] += 1;
375
376                    offset
377                })
378                .collect();
379
380            let (_, type_ids, _) = type_ids.into_parts();
381
382            let array = UnionArray::try_new(fields.clone(), type_ids, Some(offsets), children)?;
383
384            Ok(Arc::new(array))
385        }
386        t => unimplemented!("Take not supported for data type {:?}", t)
387    }
388}
389
390/// Options that define how `take` should behave
391#[derive(Clone, Debug, Default)]
392pub struct TakeOptions {
393    /// Perform bounds check before taking indices from values.
394    /// If enabled, an `ArrowError` is returned if the indices are out of bounds.
395    /// If not enabled, and indices exceed bounds, the kernel will panic.
396    pub check_bounds: bool,
397}
398
399/// `take` implementation for all primitive arrays
400///
401/// This checks if an `indices` slot is populated, and gets the value from `values`
402///  as the populated index.
403/// If the `indices` slot is null, a null value is returned.
404/// For example, given:
405///     values:  [1, 2, 3, null, 5]
406///     indices: [0, null, 4, 3]
407/// The result is: [1 (slot 0), null (null slot), 5 (slot 4), null (slot 3)]
408fn take_primitive<T, I>(
409    values: &PrimitiveArray<T>,
410    indices: &PrimitiveArray<I>,
411) -> Result<PrimitiveArray<T>, ArrowError>
412where
413    T: ArrowPrimitiveType,
414    I: ArrowPrimitiveType,
415{
416    let values_buf = take_native(values.values(), indices);
417    let nulls = take_nulls(values.nulls(), indices);
418    Ok(PrimitiveArray::try_new(values_buf, nulls)?.with_data_type(values.data_type().clone()))
419}
420
421#[inline(never)]
422fn take_nulls<I: ArrowPrimitiveType>(
423    values: Option<&NullBuffer>,
424    indices: &PrimitiveArray<I>,
425) -> Option<NullBuffer> {
426    match values.filter(|n| n.null_count() > 0) {
427        Some(n) => NullBuffer::from_unsliced_buffer(
428            take_bits(n.inner(), indices).into_inner(),
429            indices.len(),
430        ),
431        None => indices.nulls().cloned(),
432    }
433}
434
435#[inline(never)]
436fn take_native<T: ArrowNativeType, I: ArrowPrimitiveType>(
437    values: &[T],
438    indices: &PrimitiveArray<I>,
439) -> ScalarBuffer<T> {
440    match indices.nulls().filter(|n| n.null_count() > 0) {
441        Some(n) => indices
442            .values()
443            .iter()
444            .enumerate()
445            .map(|(idx, index)| match values.get(index.as_usize()) {
446                Some(v) => *v,
447                // SAFETY: idx<indices.len()
448                None => match unsafe { n.inner().value_unchecked(idx) } {
449                    false => T::default(),
450                    true => panic!("Out-of-bounds index {index:?}"),
451                },
452            })
453            .collect(),
454        None => indices
455            .values()
456            .iter()
457            .map(|index| values[index.as_usize()])
458            .collect(),
459    }
460}
461
462#[inline(never)]
463fn take_bits<I: ArrowPrimitiveType>(
464    values: &BooleanBuffer,
465    indices: &PrimitiveArray<I>,
466) -> BooleanBuffer {
467    let len = indices.len();
468
469    match indices.nulls().filter(|n| n.null_count() > 0) {
470        Some(nulls) => {
471            let mut output_buffer = MutableBuffer::new_null(len);
472            let output_slice = output_buffer.as_slice_mut();
473            nulls.valid_indices().for_each(|idx| {
474                // SAFETY: idx is a valid index in indices.nulls() --> idx<indices.len()
475                if values.value(unsafe { indices.value_unchecked(idx).as_usize() }) {
476                    // SAFETY: MutableBuffer was created with space for indices.len() bit, and idx < indices.len()
477                    unsafe { bit_util::set_bit_raw(output_slice.as_mut_ptr(), idx) };
478                }
479            });
480            BooleanBuffer::new(output_buffer.into(), 0, len)
481        }
482        None => {
483            BooleanBuffer::collect_bool(len, |idx: usize| {
484                // SAFETY: idx<indices.len()
485                values.value(unsafe { indices.value_unchecked(idx).as_usize() })
486            })
487        }
488    }
489}
490
491/// `take` implementation for boolean arrays
492fn take_boolean<IndexType: ArrowPrimitiveType>(
493    values: &BooleanArray,
494    indices: &PrimitiveArray<IndexType>,
495) -> BooleanArray {
496    let val_buf = take_bits(values.values(), indices);
497    let null_buf = take_nulls(values.nulls(), indices);
498    BooleanArray::new(val_buf, null_buf)
499}
500
501/// `take` implementation for string arrays
502fn take_bytes<T: ByteArrayType, IndexType: ArrowPrimitiveType>(
503    array: &GenericByteArray<T>,
504    indices: &PrimitiveArray<IndexType>,
505) -> Result<GenericByteArray<T>, ArrowError> {
506    let mut values: Vec<u8> = Vec::new();
507    let mut offsets = Vec::with_capacity(indices.len() + 1);
508    offsets.push(T::Offset::default());
509
510    let input_offsets = array.value_offsets();
511    let mut capacity = 0;
512    let nulls = take_nulls(array.nulls(), indices);
513
514    // Branch on output nulls — `None` means every output slot is valid.
515    match nulls.as_ref().filter(|n| n.null_count() > 0) {
516        // Fast path: no nulls in output, every index is valid.
517        None => {
518            for index in indices.values() {
519                let index = index.as_usize();
520                let start = input_offsets[index].as_usize();
521                let end = input_offsets[index + 1].as_usize();
522                capacity += end - start;
523                offsets.push(
524                    T::Offset::from_usize(capacity)
525                        .ok_or_else(|| ArrowError::OffsetOverflowError(capacity))?,
526                );
527            }
528
529            values.reserve(capacity);
530
531            let dst = values.spare_capacity_mut();
532            debug_assert!(dst.len() >= capacity);
533            let mut offset = 0;
534
535            for index in indices.values() {
536                // SAFETY: in-bounds proven by the first loop's bounds-checked offset access.
537                // dst asserted above to include the required capacity.
538                unsafe {
539                    let data: &[u8] = array.value_unchecked(index.as_usize()).as_ref();
540                    std::ptr::copy_nonoverlapping(
541                        data.as_ptr(),
542                        dst.get_unchecked_mut(offset..).as_mut_ptr().cast::<u8>(),
543                        data.len(),
544                    );
545                    offset += data.len();
546                }
547            }
548
549            // SAFETY: wrote exactly `capacity` bytes above; reserved on line above.
550            unsafe {
551                values.set_len(capacity);
552            }
553        }
554        // Nullable path: only process valid (non-null) output positions.
555        Some(output_nulls) => {
556            let mut source_ranges = Vec::with_capacity(indices.len() - output_nulls.null_count());
557            let mut last_filled = 0;
558
559            // Pre-fill offsets; we overwrite valid positions below.
560            offsets.resize(indices.len() + 1, T::Offset::default());
561
562            // Pass 1: find all valid ranges that need to be copied.
563            for i in output_nulls.valid_indices() {
564                let current_offset = T::Offset::from_usize(capacity)
565                    .ok_or_else(|| ArrowError::OffsetOverflowError(capacity))?;
566                // Fill offsets for skipped null slots so they get zero-length ranges.
567                if last_filled < i {
568                    offsets[last_filled + 1..=i].fill(current_offset);
569                }
570
571                // SAFETY: `i` comes from a validity bitmap over `indices`, so it is in-bounds.
572                let index = unsafe { indices.value_unchecked(i) }.as_usize();
573                let start = input_offsets[index].as_usize();
574                let end = input_offsets[index + 1].as_usize();
575                capacity += end - start;
576                offsets[i + 1] = T::Offset::from_usize(capacity)
577                    .ok_or_else(|| ArrowError::OffsetOverflowError(capacity))?;
578
579                source_ranges.push((start, end));
580                last_filled = i + 1;
581            }
582
583            // Fill trailing null offsets after the last valid position.
584            let final_offset = T::Offset::from_usize(capacity)
585                .ok_or_else(|| ArrowError::OffsetOverflowError(capacity))?;
586            offsets[last_filled + 1..].fill(final_offset);
587            // Pass 2: copy byte data for all collected ranges.
588            values.reserve(capacity);
589            debug_assert_eq!(
590                source_ranges.iter().map(|(s, e)| e - s).sum::<usize>(),
591                capacity,
592                "capacity must equal total bytes across all ranges"
593            );
594
595            let src = array.value_data();
596            let src = src.as_ptr();
597            let dst = values.spare_capacity_mut();
598            debug_assert!(dst.len() >= capacity);
599
600            let mut offset = 0;
601
602            for (start, end) in source_ranges {
603                let value_len = end - start;
604                // SAFETY: caller guarantees each (start, end) is in-bounds of `src`.
605                // `dst` asserted above to include the required capacity.
606                // The regions don't overlap (src is input, dst is a fresh allocation).
607                unsafe {
608                    std::ptr::copy_nonoverlapping(
609                        src.add(start),
610                        dst.get_unchecked_mut(offset..).as_mut_ptr().cast::<u8>(),
611                        value_len,
612                    );
613                    offset += value_len;
614                }
615            }
616            // SAFETY: caller guarantees `capacity` == total bytes across all ranges,
617            // so the loop above wrote exactly `capacity` bytes.
618            unsafe { values.set_len(capacity) };
619        }
620    };
621
622    // SAFETY: offsets are monotonically increasing and in-bounds of `values`,
623    // and `nulls` (if present) has length == `indices.len()`.
624    let array = unsafe {
625        let offsets = OffsetBuffer::new_unchecked(offsets.into());
626        GenericByteArray::<T>::new_unchecked(offsets, values.into(), nulls)
627    };
628
629    Ok(array)
630}
631
632/// `take` implementation for byte view arrays
633fn take_byte_view<T: ByteViewType, IndexType: ArrowPrimitiveType>(
634    array: &GenericByteViewArray<T>,
635    indices: &PrimitiveArray<IndexType>,
636) -> Result<GenericByteViewArray<T>, ArrowError> {
637    let new_views = take_native(array.views(), indices);
638    let new_nulls = take_nulls(array.nulls(), indices);
639    // Safety:  array.views was valid, and take_native copies only valid values, and verifies bounds
640    Ok(unsafe {
641        GenericByteViewArray::new_unchecked(new_views, array.data_buffers().to_vec(), new_nulls)
642    })
643}
644
645/// `take` implementation for list arrays
646///
647/// Copies the selected list entries' child slices into a new child array
648/// via `MutableArrayData`, then reconstructs a list array with new offsets
649fn take_list<IndexType, OffsetType>(
650    values: &GenericListArray<OffsetType::Native>,
651    indices: &PrimitiveArray<IndexType>,
652) -> Result<GenericListArray<OffsetType::Native>, ArrowError>
653where
654    IndexType: ArrowPrimitiveType,
655    OffsetType: ArrowPrimitiveType,
656    OffsetType::Native: OffsetSizeTrait,
657    PrimitiveArray<OffsetType>: From<Vec<OffsetType::Native>>,
658{
659    let list_offsets = values.value_offsets();
660    let child_data = values.values().to_data();
661    let nulls = take_nulls(values.nulls(), indices);
662
663    let mut new_offsets = Vec::with_capacity(indices.len() + 1);
664    new_offsets.push(OffsetType::Native::zero());
665
666    let use_nulls = child_data.null_count() > 0;
667
668    let capacity = child_data
669        .len()
670        .checked_div(values.len())
671        .map(|v| v * indices.len())
672        .unwrap_or_default();
673
674    let mut array_data = MutableArrayData::new(vec![&child_data], use_nulls, capacity);
675
676    match nulls.as_ref().filter(|n| n.null_count() > 0) {
677        None => {
678            for index in indices.values() {
679                let ix = index.as_usize();
680                let start = list_offsets[ix].as_usize();
681                let end = list_offsets[ix + 1].as_usize();
682                array_data.try_extend(0, start, end)?;
683                new_offsets.push(OffsetType::Native::from_usize(array_data.len()).unwrap());
684            }
685        }
686        Some(output_nulls) => {
687            assert_eq!(output_nulls.len(), indices.len());
688
689            let mut last_filled = 0;
690            for i in output_nulls.valid_indices() {
691                let current = OffsetType::Native::from_usize(array_data.len()).unwrap();
692                // Filling offsets for the null values between the two valid indices
693                if last_filled < i {
694                    new_offsets.extend(std::iter::repeat_n(current, i - last_filled));
695                }
696
697                // SAFETY: `i` comes from validity bitmap over `indices`, so in-bounds.
698                let ix = unsafe { indices.value_unchecked(i) }.as_usize();
699                let start = list_offsets[ix].as_usize();
700                let end = list_offsets[ix + 1].as_usize();
701                array_data.try_extend(0, start, end)?;
702                new_offsets.push(OffsetType::Native::from_usize(array_data.len()).unwrap());
703                last_filled = i + 1;
704            }
705
706            // Filling offsets for null values at the end
707            let final_offset = OffsetType::Native::from_usize(array_data.len()).unwrap();
708            new_offsets.extend(std::iter::repeat_n(
709                final_offset,
710                indices.len() - last_filled,
711            ));
712        }
713    };
714
715    assert_eq!(
716        new_offsets.len(),
717        indices.len() + 1,
718        "New offsets was filled under/over the expected capacity"
719    );
720
721    let field = match values.data_type() {
722        DataType::List(field) | DataType::LargeList(field) => field.clone(),
723        d => unreachable!("take_list called with non-list data type {d}"),
724    };
725    // SAFETY: `new_offsets` is constructed to be monotonically increasing above
726    let offsets = unsafe { OffsetBuffer::new_unchecked(ScalarBuffer::from(new_offsets)) };
727    let child = make_array(array_data.freeze());
728
729    GenericListArray::<OffsetType::Native>::try_new(field, offsets, child, nulls)
730}
731
732fn take_list_view<IndexType, OffsetType>(
733    values: &GenericListViewArray<OffsetType::Native>,
734    indices: &PrimitiveArray<IndexType>,
735) -> Result<GenericListViewArray<OffsetType::Native>, ArrowError>
736where
737    IndexType: ArrowPrimitiveType,
738    OffsetType: ArrowPrimitiveType,
739    OffsetType::Native: OffsetSizeTrait,
740{
741    let taken_offsets = take_native(values.offsets(), indices);
742    let taken_sizes = take_native(values.sizes(), indices);
743    let nulls = take_nulls(values.nulls(), indices);
744
745    let field = match values.data_type() {
746        DataType::ListView(field) | DataType::LargeListView(field) => field.clone(),
747        d => unreachable!("take_list_view called with non-list-view data type {d}"),
748    };
749
750    // SAFETY: the taken offsets/sizes are a permutation of the (valid) input
751    // offsets/sizes, so they remain within the bounds of the child array.
752    Ok(unsafe {
753        GenericListViewArray::<OffsetType::Native>::new_unchecked(
754            field,
755            taken_offsets,
756            taken_sizes,
757            Arc::clone(values.values()),
758            nulls,
759        )
760    })
761}
762
763/// `take` implementation for `FixedSizeListArray`
764///
765/// Calculates the index and indexed offset for the inner array,
766/// applying `take` on the inner array, then reconstructing a list array
767/// with the indexed offsets
768fn take_fixed_size_list<IndexType: ArrowPrimitiveType>(
769    values: &FixedSizeListArray,
770    indices: &PrimitiveArray<IndexType>,
771    length: <UInt32Type as ArrowPrimitiveType>::Native,
772) -> Result<FixedSizeListArray, ArrowError> {
773    let list_indices = take_value_indices_from_fixed_size_list(values, indices, length)?;
774    let taken = take_impl::<UInt32Type>(values.values().as_ref(), &list_indices)?;
775
776    // determine null count and null buffer, which are a function of `values` and `indices`
777    let num_bytes = bit_util::ceil(indices.len(), 8);
778    let mut null_buf = MutableBuffer::new(num_bytes).with_bitset(num_bytes, true);
779    let null_slice = null_buf.as_slice_mut();
780
781    for i in 0..indices.len() {
782        let index = indices
783            .value(i)
784            .to_usize()
785            .ok_or_else(|| ArrowError::ComputeError("Cast to usize failed".to_string()))?;
786        if !indices.is_valid(i) || values.is_null(index) {
787            bit_util::unset_bit(null_slice, i);
788        }
789    }
790
791    let field = match values.data_type() {
792        DataType::FixedSizeList(field, _) => field.clone(),
793        d => unreachable!("take_fixed_size_list called with non-fixed-size-list data type {d}"),
794    };
795    let nulls = NullBuffer::from_unsliced_buffer(null_buf, indices.len());
796
797    FixedSizeListArray::try_new(field, length as i32, taken, nulls)
798}
799
800/// The take kernel implementation for `FixedSizeBinaryArray`.
801///
802/// The computation is done in two steps:
803/// - Compute the values buffer
804/// - Compute the null buffer
805fn take_fixed_size_binary<IndexType: ArrowPrimitiveType>(
806    values: &FixedSizeBinaryArray,
807    indices: &PrimitiveArray<IndexType>,
808    size: i32,
809) -> Result<FixedSizeBinaryArray, ArrowError> {
810    let size_usize = usize::try_from(size).map_err(|_| {
811        ArrowError::InvalidArgumentError(format!("Cannot convert size '{}' to usize", size))
812    })?;
813
814    let result_buffer = match size_usize {
815        1 => take_fixed_size::<IndexType, 1>(values.values(), indices),
816        2 => take_fixed_size::<IndexType, 2>(values.values(), indices),
817        4 => take_fixed_size::<IndexType, 4>(values.values(), indices),
818        8 => take_fixed_size::<IndexType, 8>(values.values(), indices),
819        16 => take_fixed_size::<IndexType, 16>(values.values(), indices),
820        _ => take_fixed_size_binary_buffer_dynamic_length(values, indices, size_usize),
821    };
822
823    let value_nulls = take_nulls(values.nulls(), indices);
824    let final_nulls = NullBuffer::union(value_nulls.as_ref(), indices.nulls());
825
826    return FixedSizeBinaryArray::try_new(size, result_buffer, final_nulls);
827
828    /// Implementation of the take kernel for fixed size binary arrays.
829    #[inline(never)]
830    fn take_fixed_size_binary_buffer_dynamic_length<IndexType: ArrowPrimitiveType>(
831        values: &FixedSizeBinaryArray,
832        indices: &PrimitiveArray<IndexType>,
833        size_usize: usize,
834    ) -> Buffer {
835        let values_buffer = values.values().as_slice();
836        let mut values_buffer_builder = BufferBuilder::new(indices.len() * size_usize);
837
838        if indices.null_count() == 0 {
839            let array_iter = indices.values().iter().map(|idx| {
840                let offset = idx.as_usize() * size_usize;
841                &values_buffer[offset..offset + size_usize]
842            });
843            for slice in array_iter {
844                values_buffer_builder.append_slice(slice);
845            }
846        } else {
847            // The indices nullability cannot be ignored here because the values buffer may contain
848            // nulls which should not cause a panic.
849            let array_iter = indices.iter().map(|idx| {
850                idx.map(|idx| {
851                    let offset = idx.as_usize() * size_usize;
852                    &values_buffer[offset..offset + size_usize]
853                })
854            });
855            for slice in array_iter {
856                match slice {
857                    None => values_buffer_builder.append_n(size_usize, 0),
858                    Some(slice) => values_buffer_builder.append_slice(slice),
859                }
860            }
861        }
862
863        values_buffer_builder.finish()
864    }
865}
866
867/// Implements the take kernel semantics over a flat [`Buffer`], interpreting it as a slice of
868/// `&[[u8; N]]`, where `N` is a compile-time constant. The usage of a flat [`Buffer`] allows using
869/// this kernel without an available [`ArrowPrimitiveType`] (e.g., for `[u8; 5]`).
870///
871/// # Using This Function in the Primitive Take Kernel
872///
873/// This function is basically the same as [`take_native`] but just on a flat [`Buffer`] instead of
874/// the primitive [`ScalarBuffer`]. Ideally, the [`take_primitive`] kernel should just use this
875/// more general function. However, the "idiomatic code" requires the
876/// [feature(generic_const_exprs)](https://github.com/rust-lang/rust/issues/76560) for calling
877/// `take_fixed_size<I, { size_of::<T::Native> () } >(...)`. Once this feature has been stabilized,
878/// we can use this function also in the primitive kernels.
879fn take_fixed_size<IndexType: ArrowPrimitiveType, const N: usize>(
880    buffer: &Buffer,
881    indices: &PrimitiveArray<IndexType>,
882) -> Buffer {
883    assert_eq!(
884        buffer.len() % N,
885        0,
886        "Invalid array length in take_fixed_size"
887    );
888
889    let ptr = buffer.as_ptr();
890    let chunk_ptr = ptr.cast::<[u8; N]>();
891    let chunk_len = buffer.len() / N;
892    let buffer: &[[u8; N]] = unsafe {
893        // SAFETY: interpret an already valid slice as a slice of N-byte chunks. N divides buffer
894        // length without remainder.
895        std::slice::from_raw_parts(chunk_ptr, chunk_len)
896    };
897
898    let result_buffer = match indices.nulls().filter(|n| n.null_count() > 0) {
899        Some(n) => indices
900            .values()
901            .iter()
902            .enumerate()
903            .map(|(idx, index)| match buffer.get(index.as_usize()) {
904                Some(v) => *v,
905                // SAFETY: idx<indices.len()
906                None => match unsafe { n.inner().value_unchecked(idx) } {
907                    false => [0u8; N],
908                    true => panic!("Out-of-bounds index {index:?}"),
909                },
910            })
911            .collect::<Vec<_>>(),
912        None => indices
913            .values()
914            .iter()
915            .map(|index| buffer[index.as_usize()])
916            .collect::<Vec<_>>(),
917    };
918
919    let mut vec = ManuallyDrop::new(result_buffer); // Prevent de-allocation
920    let ptr = vec.as_mut_ptr();
921    let len = vec.len();
922    let cap = vec.capacity();
923    let result_buffer = unsafe {
924        // SAFETY: flattening an already valid Vec.
925        Vec::from_raw_parts(ptr.cast::<u8>(), len * N, cap * N)
926    };
927
928    Buffer::from_vec(result_buffer)
929}
930
931/// `take` implementation for dictionary arrays
932///
933/// applies `take` to the keys of the dictionary array and returns a new dictionary array
934/// with the same dictionary values and reordered keys
935fn take_dict<T: ArrowDictionaryKeyType, I: ArrowPrimitiveType>(
936    values: &DictionaryArray<T>,
937    indices: &PrimitiveArray<I>,
938) -> Result<DictionaryArray<T>, ArrowError> {
939    let new_keys = take_primitive(values.keys(), indices)?;
940    Ok(unsafe { DictionaryArray::new_unchecked(new_keys, values.values().clone()) })
941}
942
943/// `take` implementation for run arrays
944///
945/// Finds physical indices for the given logical indices and builds output run array
946/// by taking values in the input run_array.values at the physical indices.
947/// The output run array will be run encoded on the physical indices and not on output values.
948/// For e.g. an input `RunArray{ run_ends = [2,4,6,8], values=[1,2,1,2] }` and `logical_indices=[2,3,6,7]`
949/// would be converted to `physical_indices=[1,1,3,3]` which will be used to build
950/// output `RunArray{ run_ends=[2,4], values=[2,2] }`.
951fn take_run<T: RunEndIndexType, I: ArrowPrimitiveType>(
952    run_array: &RunArray<T>,
953    logical_indices: &PrimitiveArray<I>,
954) -> Result<RunArray<T>, ArrowError> {
955    // get physical indices for the input logical indices
956    let physical_indices = run_array.get_physical_indices(logical_indices.values())?;
957
958    // Run encode the physical indices into new_run_ends_builder
959    // Keep track of the physical indices to take in take_value_indices
960    // `unwrap` is used in this function because the unwrapped values are bounded by the corresponding `::Native`.
961    let mut new_run_ends_builder = BufferBuilder::<T::Native>::new(1);
962    let mut take_value_indices = BufferBuilder::<I::Native>::new(1);
963
964    let values_cmp = make_comparator(
965        run_array.values().as_ref(),
966        run_array.values().as_ref(),
967        SortOptions::default(),
968    )?;
969
970    for ix in 1..physical_indices.len() {
971        let prev_idx = physical_indices[ix - 1];
972        let cur_idx = physical_indices[ix];
973        let is_new_run = cur_idx != prev_idx && values_cmp(cur_idx, prev_idx).is_ne();
974        if is_new_run {
975            take_value_indices.append(I::Native::from_usize(prev_idx).unwrap());
976            new_run_ends_builder.append(T::Native::from_usize(ix).unwrap());
977        }
978    }
979    take_value_indices
980        .append(I::Native::from_usize(physical_indices[physical_indices.len() - 1]).unwrap());
981    new_run_ends_builder.append(T::Native::from_usize(physical_indices.len()).unwrap());
982
983    // SAFETY: run-ends are strictly increasing with last value == logical length.
984    let run_ends = unsafe {
985        RunEndBuffer::new_unchecked(
986            ScalarBuffer::from(new_run_ends_builder.finish()),
987            0,
988            physical_indices.len(),
989        )
990    };
991
992    let take_value_indices =
993        PrimitiveArray::<I>::new(ScalarBuffer::from(take_value_indices.finish()), None);
994
995    let new_values = take(run_array.values(), &take_value_indices, None)?;
996
997    // SAFETY: `new_values` has one entry per run.
998    Ok(
999        unsafe {
1000            RunArray::<T>::new_unchecked(run_array.data_type().clone(), run_ends, new_values)
1001        },
1002    )
1003}
1004
1005/// Takes/filters a fixed size list array's inner data using the offsets of the list array.
1006fn take_value_indices_from_fixed_size_list<IndexType>(
1007    list: &FixedSizeListArray,
1008    indices: &PrimitiveArray<IndexType>,
1009    length: <UInt32Type as ArrowPrimitiveType>::Native,
1010) -> Result<PrimitiveArray<UInt32Type>, ArrowError>
1011where
1012    IndexType: ArrowPrimitiveType,
1013{
1014    let mut values = UInt32Builder::with_capacity(length as usize * indices.len());
1015
1016    for i in 0..indices.len() {
1017        if indices.is_valid(i) {
1018            let index = indices
1019                .value(i)
1020                .to_usize()
1021                .ok_or_else(|| ArrowError::ComputeError("Cast to usize failed".to_string()))?;
1022            let start = list.value_offset(index) as <UInt32Type as ArrowPrimitiveType>::Native;
1023
1024            // Safety: Range always has known length.
1025            unsafe {
1026                values.append_trusted_len_iter(start..start + length);
1027            }
1028        } else {
1029            values.append_nulls(length as usize);
1030        }
1031    }
1032
1033    Ok(values.finish())
1034}
1035
1036/// To avoid generating take implementations for every index type, instead we
1037/// only generate for UInt32 and UInt64 and coerce inputs to these types
1038trait ToIndices {
1039    type T: ArrowPrimitiveType;
1040
1041    fn to_indices(&self) -> PrimitiveArray<Self::T>;
1042}
1043
1044macro_rules! to_indices_reinterpret {
1045    ($t:ty, $o:ty) => {
1046        impl ToIndices for PrimitiveArray<$t> {
1047            type T = $o;
1048
1049            fn to_indices(&self) -> PrimitiveArray<$o> {
1050                let cast = ScalarBuffer::new(self.values().inner().clone(), 0, self.len());
1051                PrimitiveArray::new(cast, self.nulls().cloned())
1052            }
1053        }
1054    };
1055}
1056
1057macro_rules! to_indices_identity {
1058    ($t:ty) => {
1059        impl ToIndices for PrimitiveArray<$t> {
1060            type T = $t;
1061
1062            fn to_indices(&self) -> PrimitiveArray<$t> {
1063                self.clone()
1064            }
1065        }
1066    };
1067}
1068
1069macro_rules! to_indices_widening {
1070    ($t:ty, $o:ty) => {
1071        impl ToIndices for PrimitiveArray<$t> {
1072            type T = UInt32Type;
1073
1074            fn to_indices(&self) -> PrimitiveArray<$o> {
1075                let cast = self.values().iter().copied().map(|x| x as _).collect();
1076                PrimitiveArray::new(cast, self.nulls().cloned())
1077            }
1078        }
1079    };
1080}
1081
1082to_indices_widening!(UInt8Type, UInt32Type);
1083to_indices_widening!(Int8Type, UInt32Type);
1084
1085to_indices_widening!(UInt16Type, UInt32Type);
1086to_indices_widening!(Int16Type, UInt32Type);
1087
1088to_indices_identity!(UInt32Type);
1089to_indices_reinterpret!(Int32Type, UInt32Type);
1090
1091to_indices_identity!(UInt64Type);
1092to_indices_reinterpret!(Int64Type, UInt64Type);
1093
1094/// Take rows by index from [`RecordBatch`] and returns a new [`RecordBatch`] from those indexes.
1095///
1096/// This function will call [`take`] on each array of the [`RecordBatch`] and assemble a new [`RecordBatch`].
1097///
1098/// # Example
1099/// ```
1100/// # use std::sync::Arc;
1101/// # use arrow_array::{StringArray, Int32Array, UInt32Array, RecordBatch};
1102/// # use arrow_schema::{DataType, Field, Schema};
1103/// # use arrow_select::take::take_record_batch;
1104/// let schema = Arc::new(Schema::new(vec![
1105///     Field::new("a", DataType::Int32, true),
1106///     Field::new("b", DataType::Utf8, true),
1107/// ]));
1108/// let batch = RecordBatch::try_new(
1109///     schema.clone(),
1110///     vec![
1111///         Arc::new(Int32Array::from_iter_values(0..20)),
1112///         Arc::new(StringArray::from_iter_values(
1113///             (0..20).map(|i| format!("str-{}", i)),
1114///         )),
1115///     ],
1116/// )
1117/// .unwrap();
1118///
1119/// let indices = UInt32Array::from(vec![1, 5, 10]);
1120/// let taken = take_record_batch(&batch, &indices).unwrap();
1121///
1122/// let expected = RecordBatch::try_new(
1123///     schema,
1124///     vec![
1125///         Arc::new(Int32Array::from(vec![1, 5, 10])),
1126///         Arc::new(StringArray::from(vec!["str-1", "str-5", "str-10"])),
1127///     ],
1128/// )
1129/// .unwrap();
1130/// assert_eq!(taken, expected);
1131/// ```
1132pub fn take_record_batch(
1133    record_batch: &RecordBatch,
1134    indices: &dyn Array,
1135) -> Result<RecordBatch, ArrowError> {
1136    let columns = record_batch
1137        .columns()
1138        .iter()
1139        .map(|c| take(c, indices, None))
1140        .collect::<Result<Vec<_>, _>>()?;
1141    RecordBatch::try_new(record_batch.schema(), columns)
1142}
1143
1144#[cfg(test)]
1145mod tests {
1146    use super::*;
1147    use arrow_array::builder::*;
1148    use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano};
1149    use arrow_data::ArrayData;
1150    use arrow_schema::{Field, Fields, TimeUnit, UnionFields};
1151    use num_traits::ToPrimitive;
1152
1153    fn test_take_decimal_arrays(
1154        data: Vec<Option<i128>>,
1155        index: &UInt32Array,
1156        options: Option<TakeOptions>,
1157        expected_data: Vec<Option<i128>>,
1158        precision: &u8,
1159        scale: &i8,
1160    ) -> Result<(), ArrowError> {
1161        let output = data
1162            .into_iter()
1163            .collect::<Decimal128Array>()
1164            .with_precision_and_scale(*precision, *scale)
1165            .unwrap();
1166
1167        let expected = expected_data
1168            .into_iter()
1169            .collect::<Decimal128Array>()
1170            .with_precision_and_scale(*precision, *scale)
1171            .unwrap();
1172
1173        let expected = Arc::new(expected) as ArrayRef;
1174        let output = take(&output, index, options).unwrap();
1175        assert_eq!(&output, &expected);
1176        Ok(())
1177    }
1178
1179    fn test_take_boolean_arrays(
1180        data: Vec<Option<bool>>,
1181        index: &UInt32Array,
1182        options: Option<TakeOptions>,
1183        expected_data: Vec<Option<bool>>,
1184    ) {
1185        let output = BooleanArray::from(data);
1186        let expected = Arc::new(BooleanArray::from(expected_data)) as ArrayRef;
1187        let output = take(&output, index, options).unwrap();
1188        assert_eq!(&output, &expected)
1189    }
1190
1191    fn test_take_primitive_arrays<T>(
1192        data: Vec<Option<T::Native>>,
1193        index: &UInt32Array,
1194        options: Option<TakeOptions>,
1195        expected_data: Vec<Option<T::Native>>,
1196    ) -> Result<(), ArrowError>
1197    where
1198        T: ArrowPrimitiveType,
1199        PrimitiveArray<T>: From<Vec<Option<T::Native>>>,
1200    {
1201        let output = PrimitiveArray::<T>::from(data);
1202        let expected = Arc::new(PrimitiveArray::<T>::from(expected_data)) as ArrayRef;
1203        let output = take(&output, index, options)?;
1204        assert_eq!(&output, &expected);
1205        Ok(())
1206    }
1207
1208    fn test_take_primitive_arrays_non_null<T>(
1209        data: Vec<T::Native>,
1210        index: &UInt32Array,
1211        options: Option<TakeOptions>,
1212        expected_data: Vec<Option<T::Native>>,
1213    ) -> Result<(), ArrowError>
1214    where
1215        T: ArrowPrimitiveType,
1216        PrimitiveArray<T>: From<Vec<T::Native>>,
1217        PrimitiveArray<T>: From<Vec<Option<T::Native>>>,
1218    {
1219        let output = PrimitiveArray::<T>::from(data);
1220        let expected = Arc::new(PrimitiveArray::<T>::from(expected_data)) as ArrayRef;
1221        let output = take(&output, index, options)?;
1222        assert_eq!(&output, &expected);
1223        Ok(())
1224    }
1225
1226    fn test_take_impl_primitive_arrays<T, I>(
1227        data: Vec<Option<T::Native>>,
1228        index: &PrimitiveArray<I>,
1229        options: Option<TakeOptions>,
1230        expected_data: Vec<Option<T::Native>>,
1231    ) where
1232        T: ArrowPrimitiveType,
1233        PrimitiveArray<T>: From<Vec<Option<T::Native>>>,
1234        I: ArrowPrimitiveType,
1235    {
1236        let output = PrimitiveArray::<T>::from(data);
1237        let expected = PrimitiveArray::<T>::from(expected_data);
1238        let output = take(&output, index, options).unwrap();
1239        let output = output.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
1240        assert_eq!(output, &expected)
1241    }
1242
1243    // create a simple struct for testing purposes
1244    fn create_test_struct(values: Vec<Option<(Option<bool>, Option<i32>)>>) -> StructArray {
1245        let mut struct_builder = StructBuilder::new(
1246            Fields::from(vec![
1247                Field::new("a", DataType::Boolean, true),
1248                Field::new("b", DataType::Int32, true),
1249            ]),
1250            vec![
1251                Box::new(BooleanBuilder::with_capacity(values.len())),
1252                Box::new(Int32Builder::with_capacity(values.len())),
1253            ],
1254        );
1255
1256        for value in values {
1257            struct_builder
1258                .field_builder::<BooleanBuilder>(0)
1259                .unwrap()
1260                .append_option(value.and_then(|v| v.0));
1261            struct_builder
1262                .field_builder::<Int32Builder>(1)
1263                .unwrap()
1264                .append_option(value.and_then(|v| v.1));
1265            struct_builder.append(value.is_some());
1266        }
1267        struct_builder.finish()
1268    }
1269
1270    #[test]
1271    fn test_take_decimal128_non_null_indices() {
1272        let index = UInt32Array::from(vec![0, 5, 3, 1, 4, 2]);
1273        let precision: u8 = 10;
1274        let scale: i8 = 5;
1275        test_take_decimal_arrays(
1276            vec![None, Some(3), Some(5), Some(2), Some(3), None],
1277            &index,
1278            None,
1279            vec![None, None, Some(2), Some(3), Some(3), Some(5)],
1280            &precision,
1281            &scale,
1282        )
1283        .unwrap();
1284    }
1285
1286    #[test]
1287    fn test_take_decimal128() {
1288        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1289        let precision: u8 = 10;
1290        let scale: i8 = 5;
1291        test_take_decimal_arrays(
1292            vec![Some(0), Some(1), Some(2), Some(3), Some(4)],
1293            &index,
1294            None,
1295            vec![Some(3), None, Some(1), Some(3), Some(2)],
1296            &precision,
1297            &scale,
1298        )
1299        .unwrap();
1300    }
1301
1302    #[test]
1303    fn test_take_primitive_non_null_indices() {
1304        let index = UInt32Array::from(vec![0, 5, 3, 1, 4, 2]);
1305        test_take_primitive_arrays::<Int8Type>(
1306            vec![None, Some(3), Some(5), Some(2), Some(3), None],
1307            &index,
1308            None,
1309            vec![None, None, Some(2), Some(3), Some(3), Some(5)],
1310        )
1311        .unwrap();
1312    }
1313
1314    #[test]
1315    fn test_take_primitive_non_null_values() {
1316        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1317        test_take_primitive_arrays::<Int8Type>(
1318            vec![Some(0), Some(1), Some(2), Some(3), Some(4)],
1319            &index,
1320            None,
1321            vec![Some(3), None, Some(1), Some(3), Some(2)],
1322        )
1323        .unwrap();
1324    }
1325
1326    #[test]
1327    fn test_take_primitive_non_null() {
1328        let index = UInt32Array::from(vec![0, 5, 3, 1, 4, 2]);
1329        test_take_primitive_arrays::<Int8Type>(
1330            vec![Some(0), Some(3), Some(5), Some(2), Some(3), Some(1)],
1331            &index,
1332            None,
1333            vec![Some(0), Some(1), Some(2), Some(3), Some(3), Some(5)],
1334        )
1335        .unwrap();
1336    }
1337
1338    #[test]
1339    fn test_take_primitive_nullable_indices_non_null_values_with_offset() {
1340        let index = UInt32Array::from(vec![Some(0), Some(1), Some(2), Some(3), None, None]);
1341        let index = index.slice(2, 4);
1342        let index = index.as_any().downcast_ref::<UInt32Array>().unwrap();
1343
1344        assert_eq!(
1345            index,
1346            &UInt32Array::from(vec![Some(2), Some(3), None, None])
1347        );
1348
1349        test_take_primitive_arrays_non_null::<Int64Type>(
1350            vec![0, 10, 20, 30, 40, 50],
1351            index,
1352            None,
1353            vec![Some(20), Some(30), None, None],
1354        )
1355        .unwrap();
1356    }
1357
1358    #[test]
1359    fn test_take_primitive_nullable_indices_nullable_values_with_offset() {
1360        let index = UInt32Array::from(vec![Some(0), Some(1), Some(2), Some(3), None, None]);
1361        let index = index.slice(2, 4);
1362        let index = index.as_any().downcast_ref::<UInt32Array>().unwrap();
1363
1364        assert_eq!(
1365            index,
1366            &UInt32Array::from(vec![Some(2), Some(3), None, None])
1367        );
1368
1369        test_take_primitive_arrays::<Int64Type>(
1370            vec![None, None, Some(20), Some(30), Some(40), Some(50)],
1371            index,
1372            None,
1373            vec![Some(20), Some(30), None, None],
1374        )
1375        .unwrap();
1376    }
1377
1378    #[test]
1379    fn test_take_primitive() {
1380        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1381
1382        // int8
1383        test_take_primitive_arrays::<Int8Type>(
1384            vec![Some(0), None, Some(2), Some(3), None],
1385            &index,
1386            None,
1387            vec![Some(3), None, None, Some(3), Some(2)],
1388        )
1389        .unwrap();
1390
1391        // int16
1392        test_take_primitive_arrays::<Int16Type>(
1393            vec![Some(0), None, Some(2), Some(3), None],
1394            &index,
1395            None,
1396            vec![Some(3), None, None, Some(3), Some(2)],
1397        )
1398        .unwrap();
1399
1400        // int32
1401        test_take_primitive_arrays::<Int32Type>(
1402            vec![Some(0), None, Some(2), Some(3), None],
1403            &index,
1404            None,
1405            vec![Some(3), None, None, Some(3), Some(2)],
1406        )
1407        .unwrap();
1408
1409        // int64
1410        test_take_primitive_arrays::<Int64Type>(
1411            vec![Some(0), None, Some(2), Some(3), None],
1412            &index,
1413            None,
1414            vec![Some(3), None, None, Some(3), Some(2)],
1415        )
1416        .unwrap();
1417
1418        // uint8
1419        test_take_primitive_arrays::<UInt8Type>(
1420            vec![Some(0), None, Some(2), Some(3), None],
1421            &index,
1422            None,
1423            vec![Some(3), None, None, Some(3), Some(2)],
1424        )
1425        .unwrap();
1426
1427        // uint16
1428        test_take_primitive_arrays::<UInt16Type>(
1429            vec![Some(0), None, Some(2), Some(3), None],
1430            &index,
1431            None,
1432            vec![Some(3), None, None, Some(3), Some(2)],
1433        )
1434        .unwrap();
1435
1436        // uint32
1437        test_take_primitive_arrays::<UInt32Type>(
1438            vec![Some(0), None, Some(2), Some(3), None],
1439            &index,
1440            None,
1441            vec![Some(3), None, None, Some(3), Some(2)],
1442        )
1443        .unwrap();
1444
1445        // int64
1446        test_take_primitive_arrays::<Int64Type>(
1447            vec![Some(0), None, Some(2), Some(-15), None],
1448            &index,
1449            None,
1450            vec![Some(-15), None, None, Some(-15), Some(2)],
1451        )
1452        .unwrap();
1453
1454        // interval_year_month
1455        test_take_primitive_arrays::<IntervalYearMonthType>(
1456            vec![Some(0), None, Some(2), Some(-15), None],
1457            &index,
1458            None,
1459            vec![Some(-15), None, None, Some(-15), Some(2)],
1460        )
1461        .unwrap();
1462
1463        // interval_day_time
1464        let v1 = IntervalDayTime::new(0, 0);
1465        let v2 = IntervalDayTime::new(2, 0);
1466        let v3 = IntervalDayTime::new(-15, 0);
1467        test_take_primitive_arrays::<IntervalDayTimeType>(
1468            vec![Some(v1), None, Some(v2), Some(v3), None],
1469            &index,
1470            None,
1471            vec![Some(v3), None, None, Some(v3), Some(v2)],
1472        )
1473        .unwrap();
1474
1475        // interval_month_day_nano
1476        let v1 = IntervalMonthDayNano::new(0, 0, 0);
1477        let v2 = IntervalMonthDayNano::new(2, 0, 0);
1478        let v3 = IntervalMonthDayNano::new(-15, 0, 0);
1479        test_take_primitive_arrays::<IntervalMonthDayNanoType>(
1480            vec![Some(v1), None, Some(v2), Some(v3), None],
1481            &index,
1482            None,
1483            vec![Some(v3), None, None, Some(v3), Some(v2)],
1484        )
1485        .unwrap();
1486
1487        // duration_second
1488        test_take_primitive_arrays::<DurationSecondType>(
1489            vec![Some(0), None, Some(2), Some(-15), None],
1490            &index,
1491            None,
1492            vec![Some(-15), None, None, Some(-15), Some(2)],
1493        )
1494        .unwrap();
1495
1496        // duration_millisecond
1497        test_take_primitive_arrays::<DurationMillisecondType>(
1498            vec![Some(0), None, Some(2), Some(-15), None],
1499            &index,
1500            None,
1501            vec![Some(-15), None, None, Some(-15), Some(2)],
1502        )
1503        .unwrap();
1504
1505        // duration_microsecond
1506        test_take_primitive_arrays::<DurationMicrosecondType>(
1507            vec![Some(0), None, Some(2), Some(-15), None],
1508            &index,
1509            None,
1510            vec![Some(-15), None, None, Some(-15), Some(2)],
1511        )
1512        .unwrap();
1513
1514        // duration_nanosecond
1515        test_take_primitive_arrays::<DurationNanosecondType>(
1516            vec![Some(0), None, Some(2), Some(-15), None],
1517            &index,
1518            None,
1519            vec![Some(-15), None, None, Some(-15), Some(2)],
1520        )
1521        .unwrap();
1522
1523        // float32
1524        test_take_primitive_arrays::<Float32Type>(
1525            vec![Some(0.0), None, Some(2.21), Some(-3.1), None],
1526            &index,
1527            None,
1528            vec![Some(-3.1), None, None, Some(-3.1), Some(2.21)],
1529        )
1530        .unwrap();
1531
1532        // float64
1533        test_take_primitive_arrays::<Float64Type>(
1534            vec![Some(0.0), None, Some(2.21), Some(-3.1), None],
1535            &index,
1536            None,
1537            vec![Some(-3.1), None, None, Some(-3.1), Some(2.21)],
1538        )
1539        .unwrap();
1540    }
1541
1542    #[test]
1543    fn test_take_preserve_timezone() {
1544        let index = Int64Array::from(vec![Some(0), None]);
1545
1546        let input = TimestampNanosecondArray::from(vec![
1547            1_639_715_368_000_000_000,
1548            1_639_715_368_000_000_000,
1549        ])
1550        .with_timezone("UTC".to_string());
1551        let result = take(&input, &index, None).unwrap();
1552        match result.data_type() {
1553            DataType::Timestamp(TimeUnit::Nanosecond, tz) => {
1554                assert_eq!(tz.clone(), Some("UTC".into()))
1555            }
1556            _ => panic!(),
1557        }
1558    }
1559
1560    #[test]
1561    fn test_take_impl_primitive_with_int64_indices() {
1562        let index = Int64Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1563
1564        // int16
1565        test_take_impl_primitive_arrays::<Int16Type, Int64Type>(
1566            vec![Some(0), None, Some(2), Some(3), None],
1567            &index,
1568            None,
1569            vec![Some(3), None, None, Some(3), Some(2)],
1570        );
1571
1572        // int64
1573        test_take_impl_primitive_arrays::<Int64Type, Int64Type>(
1574            vec![Some(0), None, Some(2), Some(-15), None],
1575            &index,
1576            None,
1577            vec![Some(-15), None, None, Some(-15), Some(2)],
1578        );
1579
1580        // uint64
1581        test_take_impl_primitive_arrays::<UInt64Type, Int64Type>(
1582            vec![Some(0), None, Some(2), Some(3), None],
1583            &index,
1584            None,
1585            vec![Some(3), None, None, Some(3), Some(2)],
1586        );
1587
1588        // duration_millisecond
1589        test_take_impl_primitive_arrays::<DurationMillisecondType, Int64Type>(
1590            vec![Some(0), None, Some(2), Some(-15), None],
1591            &index,
1592            None,
1593            vec![Some(-15), None, None, Some(-15), Some(2)],
1594        );
1595
1596        // float32
1597        test_take_impl_primitive_arrays::<Float32Type, Int64Type>(
1598            vec![Some(0.0), None, Some(2.21), Some(-3.1), None],
1599            &index,
1600            None,
1601            vec![Some(-3.1), None, None, Some(-3.1), Some(2.21)],
1602        );
1603    }
1604
1605    #[test]
1606    fn test_take_impl_primitive_with_uint8_indices() {
1607        let index = UInt8Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1608
1609        // int16
1610        test_take_impl_primitive_arrays::<Int16Type, UInt8Type>(
1611            vec![Some(0), None, Some(2), Some(3), None],
1612            &index,
1613            None,
1614            vec![Some(3), None, None, Some(3), Some(2)],
1615        );
1616
1617        // duration_millisecond
1618        test_take_impl_primitive_arrays::<DurationMillisecondType, UInt8Type>(
1619            vec![Some(0), None, Some(2), Some(-15), None],
1620            &index,
1621            None,
1622            vec![Some(-15), None, None, Some(-15), Some(2)],
1623        );
1624
1625        // float32
1626        test_take_impl_primitive_arrays::<Float32Type, UInt8Type>(
1627            vec![Some(0.0), None, Some(2.21), Some(-3.1), None],
1628            &index,
1629            None,
1630            vec![Some(-3.1), None, None, Some(-3.1), Some(2.21)],
1631        );
1632    }
1633
1634    #[test]
1635    fn test_take_bool() {
1636        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(2)]);
1637        // boolean
1638        test_take_boolean_arrays(
1639            vec![Some(false), None, Some(true), Some(false), None],
1640            &index,
1641            None,
1642            vec![Some(false), None, None, Some(false), Some(true)],
1643        );
1644    }
1645
1646    #[test]
1647    fn test_take_bool_nullable_index() {
1648        // indices where the masked invalid elements would be out of bounds
1649        let index_data = ArrayData::try_new(
1650            DataType::UInt32,
1651            6,
1652            Some(Buffer::from_iter(vec![
1653                false, true, false, true, false, true,
1654            ])),
1655            0,
1656            vec![Buffer::from_iter(vec![99, 0, 999, 1, 9999, 2])],
1657            vec![],
1658        )
1659        .unwrap();
1660        let index = UInt32Array::from(index_data);
1661        test_take_boolean_arrays(
1662            vec![Some(true), None, Some(false)],
1663            &index,
1664            None,
1665            vec![None, Some(true), None, None, None, Some(false)],
1666        );
1667    }
1668
1669    #[test]
1670    fn test_take_bool_nullable_index_nonnull_values() {
1671        // indices where the masked invalid elements would be out of bounds
1672        let index_data = ArrayData::try_new(
1673            DataType::UInt32,
1674            6,
1675            Some(Buffer::from_iter(vec![
1676                false, true, false, true, false, true,
1677            ])),
1678            0,
1679            vec![Buffer::from_iter(vec![99, 0, 999, 1, 9999, 2])],
1680            vec![],
1681        )
1682        .unwrap();
1683        let index = UInt32Array::from(index_data);
1684        test_take_boolean_arrays(
1685            vec![Some(true), Some(true), Some(false)],
1686            &index,
1687            None,
1688            vec![None, Some(true), None, Some(true), None, Some(false)],
1689        );
1690    }
1691
1692    #[test]
1693    fn test_take_bool_with_offset() {
1694        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(2), None]);
1695        let index = index.slice(2, 4);
1696        let index = index
1697            .as_any()
1698            .downcast_ref::<PrimitiveArray<UInt32Type>>()
1699            .unwrap();
1700
1701        // boolean
1702        test_take_boolean_arrays(
1703            vec![Some(false), None, Some(true), Some(false), None],
1704            index,
1705            None,
1706            vec![None, Some(false), Some(true), None],
1707        );
1708    }
1709
1710    fn _test_take_string<'a, K>()
1711    where
1712        K: Array + PartialEq + From<Vec<Option<&'a str>>> + 'static,
1713    {
1714        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(4)]);
1715
1716        let array = K::from(vec![
1717            Some("one"),
1718            None,
1719            Some("three"),
1720            Some("four"),
1721            Some("five"),
1722        ]);
1723        let actual = take(&array, &index, None).unwrap();
1724        assert_eq!(actual.len(), index.len());
1725
1726        let actual = actual.as_any().downcast_ref::<K>().unwrap();
1727
1728        let expected = K::from(vec![Some("four"), None, None, Some("four"), Some("five")]);
1729
1730        assert_eq!(actual, &expected);
1731    }
1732
1733    #[test]
1734    fn test_take_string() {
1735        _test_take_string::<StringArray>()
1736    }
1737
1738    #[test]
1739    fn test_take_large_string() {
1740        _test_take_string::<LargeStringArray>()
1741    }
1742
1743    #[test]
1744    fn test_take_slice_string() {
1745        let strings = StringArray::from(vec![Some("hello"), None, Some("world"), None, Some("hi")]);
1746        let indices = Int32Array::from(vec![Some(0), Some(1), None, Some(0), Some(2)]);
1747        let indices_slice = indices.slice(1, 4);
1748        let expected = StringArray::from(vec![None, None, Some("hello"), Some("world")]);
1749        let result = take(&strings, &indices_slice, None).unwrap();
1750        assert_eq!(result.as_ref(), &expected);
1751    }
1752
1753    /// Take from a *sliced* byte array, i.e. one whose value offsets do not
1754    /// start at zero. This exercises copying byte data out of an array with a
1755    /// non-zero base offset for both the no-null fast path and the nullable
1756    /// path (null indices and selected null values).
1757    #[test]
1758    fn test_take_bytes_sliced_values() {
1759        let values = StringArray::from(vec![
1760            Some("aaa"),
1761            Some("bbb"),
1762            None,
1763            Some("ccccc"),
1764            Some("dd"),
1765            None,
1766            Some("eeee"),
1767        ]);
1768        // Slice so the underlying value offsets no longer start at 0:
1769        // sliced == [None, "ccccc", "dd", None, "eeee"]
1770        let sliced = values.slice(2, 5);
1771
1772        // Fast path: every output slot is valid (no null indices, no null
1773        // values selected).
1774        let indices = Int32Array::from(vec![1, 2, 4, 1]);
1775        let result = take(&sliced, &indices, None).unwrap();
1776        let expected =
1777            StringArray::from(vec![Some("ccccc"), Some("dd"), Some("eeee"), Some("ccccc")]);
1778        assert_eq!(result.as_string::<i32>(), &expected);
1779
1780        // Nullable path: a null index (position 1) and selected null values
1781        // (sliced indices 0 and 3 are null).
1782        let indices = Int32Array::from(vec![Some(1), None, Some(0), Some(4), Some(3)]);
1783        let result = take(&sliced, &indices, None).unwrap();
1784        let expected = StringArray::from(vec![Some("ccccc"), None, None, Some("eeee"), None]);
1785        assert_eq!(result.as_string::<i32>(), &expected);
1786    }
1787
1788    fn _test_byte_view<T>()
1789    where
1790        T: ByteViewType,
1791        str: AsRef<T::Native>,
1792        T::Native: PartialEq,
1793    {
1794        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(4), Some(2)]);
1795        let array = {
1796            // ["hello", "world", null, "large payload over 12 bytes", "lulu"]
1797            let mut builder = GenericByteViewBuilder::<T>::new();
1798            builder.append_value("hello");
1799            builder.append_value("world");
1800            builder.append_null();
1801            builder.append_value("large payload over 12 bytes");
1802            builder.append_value("lulu");
1803            builder.finish()
1804        };
1805
1806        let actual = take(&array, &index, None).unwrap();
1807
1808        assert_eq!(actual.len(), index.len());
1809
1810        let expected = {
1811            // ["large payload over 12 bytes", null, "world", "large payload over 12 bytes", "lulu", null]
1812            let mut builder = GenericByteViewBuilder::<T>::new();
1813            builder.append_value("large payload over 12 bytes");
1814            builder.append_null();
1815            builder.append_value("world");
1816            builder.append_value("large payload over 12 bytes");
1817            builder.append_value("lulu");
1818            builder.append_null();
1819            builder.finish()
1820        };
1821
1822        assert_eq!(actual.as_ref(), &expected);
1823    }
1824
1825    #[test]
1826    fn test_take_string_view() {
1827        _test_byte_view::<StringViewType>()
1828    }
1829
1830    #[test]
1831    fn test_take_binary_view() {
1832        _test_byte_view::<BinaryViewType>()
1833    }
1834
1835    macro_rules! test_take_list {
1836        ($offset_type:ty, $list_data_type:ident, $list_array_type:ident) => {{
1837            // Construct a value array, [[0,0,0], [-1,-2,-1], [], [2,3]]
1838            let value_data = Int32Array::from(vec![0, 0, 0, -1, -2, -1, 2, 3]).into_data();
1839            // Construct offsets
1840            let value_offsets: [$offset_type; 5] = [0, 3, 6, 6, 8];
1841            let value_offsets = Buffer::from_slice_ref(&value_offsets);
1842            // Construct a list array from the above two
1843            let list_data_type =
1844                DataType::$list_data_type(Arc::new(Field::new_list_field(DataType::Int32, false)));
1845            let list_data = ArrayData::builder(list_data_type.clone())
1846                .len(4)
1847                .add_buffer(value_offsets)
1848                .add_child_data(value_data)
1849                .build()
1850                .unwrap();
1851            let list_array = $list_array_type::from(list_data);
1852
1853            // index returns: [[2,3], null, [-1,-2,-1], [], [0,0,0]]
1854            let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(2), Some(0)]);
1855
1856            let a = take(&list_array, &index, None).unwrap();
1857            let a: &$list_array_type = a.as_any().downcast_ref::<$list_array_type>().unwrap();
1858
1859            // construct a value array with expected results:
1860            // [[2,3], null, [-1,-2,-1], [], [0,0,0]]
1861            let expected_data = Int32Array::from(vec![
1862                Some(2),
1863                Some(3),
1864                Some(-1),
1865                Some(-2),
1866                Some(-1),
1867                Some(0),
1868                Some(0),
1869                Some(0),
1870            ])
1871            .into_data();
1872            // construct offsets
1873            let expected_offsets: [$offset_type; 6] = [0, 2, 2, 5, 5, 8];
1874            let expected_offsets = Buffer::from_slice_ref(&expected_offsets);
1875            // construct list array from the two
1876            let expected_list_data = ArrayData::builder(list_data_type)
1877                .len(5)
1878                // null buffer remains the same as only the indices have nulls
1879                .nulls(index.nulls().cloned())
1880                .add_buffer(expected_offsets)
1881                .add_child_data(expected_data)
1882                .build()
1883                .unwrap();
1884            let expected_list_array = $list_array_type::from(expected_list_data);
1885
1886            assert_eq!(a, &expected_list_array);
1887        }};
1888    }
1889
1890    macro_rules! test_take_list_with_value_nulls {
1891        ($offset_type:ty, $list_data_type:ident, $list_array_type:ident) => {{
1892            // Construct a value array, [[0,null,0], [-1,-2,3], [null], [5,null]]
1893            let value_data = Int32Array::from(vec![
1894                Some(0),
1895                None,
1896                Some(0),
1897                Some(-1),
1898                Some(-2),
1899                Some(3),
1900                None,
1901                Some(5),
1902                None,
1903            ])
1904            .into_data();
1905            // Construct offsets
1906            let value_offsets: [$offset_type; 5] = [0, 3, 6, 7, 9];
1907            let value_offsets = Buffer::from_slice_ref(&value_offsets);
1908            // Construct a list array from the above two
1909            let list_data_type =
1910                DataType::$list_data_type(Arc::new(Field::new_list_field(DataType::Int32, true)));
1911            let list_data = ArrayData::builder(list_data_type.clone())
1912                .len(4)
1913                .add_buffer(value_offsets)
1914                .null_bit_buffer(Some(Buffer::from([0b11111111])))
1915                .add_child_data(value_data)
1916                .build()
1917                .unwrap();
1918            let list_array = $list_array_type::from(list_data);
1919
1920            // index returns: [[null], null, [-1,-2,3], [2,null], [0,null,0]]
1921            let index = UInt32Array::from(vec![Some(2), None, Some(1), Some(3), Some(0)]);
1922
1923            let a = take(&list_array, &index, None).unwrap();
1924            let a: &$list_array_type = a.as_any().downcast_ref::<$list_array_type>().unwrap();
1925
1926            // construct a value array with expected results:
1927            // [[null], null, [-1,-2,3], [5,null], [0,null,0]]
1928            let expected_data = Int32Array::from(vec![
1929                None,
1930                Some(-1),
1931                Some(-2),
1932                Some(3),
1933                Some(5),
1934                None,
1935                Some(0),
1936                None,
1937                Some(0),
1938            ])
1939            .into_data();
1940            // construct offsets
1941            let expected_offsets: [$offset_type; 6] = [0, 1, 1, 4, 6, 9];
1942            let expected_offsets = Buffer::from_slice_ref(&expected_offsets);
1943            // construct list array from the two
1944            let expected_list_data = ArrayData::builder(list_data_type)
1945                .len(5)
1946                // null buffer remains the same as only the indices have nulls
1947                .nulls(index.nulls().cloned())
1948                .add_buffer(expected_offsets)
1949                .add_child_data(expected_data)
1950                .build()
1951                .unwrap();
1952            let expected_list_array = $list_array_type::from(expected_list_data);
1953
1954            assert_eq!(a, &expected_list_array);
1955        }};
1956    }
1957
1958    macro_rules! test_take_list_with_nulls {
1959        ($offset_type:ty, $list_data_type:ident, $list_array_type:ident) => {{
1960            // Construct a value array, [[0,null,0], [-1,-2,3], null, [5,null]]
1961            let value_data = Int32Array::from(vec![
1962                Some(0),
1963                None,
1964                Some(0),
1965                Some(-1),
1966                Some(-2),
1967                Some(3),
1968                Some(5),
1969                None,
1970            ])
1971            .into_data();
1972            // Construct offsets
1973            let value_offsets: [$offset_type; 5] = [0, 3, 6, 6, 8];
1974            let value_offsets = Buffer::from_slice_ref(&value_offsets);
1975            // Construct a list array from the above two
1976            let list_data_type =
1977                DataType::$list_data_type(Arc::new(Field::new_list_field(DataType::Int32, true)));
1978            let list_data = ArrayData::builder(list_data_type.clone())
1979                .len(4)
1980                .add_buffer(value_offsets)
1981                .null_bit_buffer(Some(Buffer::from([0b11111011])))
1982                .add_child_data(value_data)
1983                .build()
1984                .unwrap();
1985            let list_array = $list_array_type::from(list_data);
1986
1987            // index returns: [null, null, [-1,-2,3], [5,null], [0,null,0]]
1988            let index = UInt32Array::from(vec![Some(2), None, Some(1), Some(3), Some(0)]);
1989
1990            let a = take(&list_array, &index, None).unwrap();
1991            let a: &$list_array_type = a.as_any().downcast_ref::<$list_array_type>().unwrap();
1992
1993            // construct a value array with expected results:
1994            // [null, null, [-1,-2,3], [5,null], [0,null,0]]
1995            let expected_data = Int32Array::from(vec![
1996                Some(-1),
1997                Some(-2),
1998                Some(3),
1999                Some(5),
2000                None,
2001                Some(0),
2002                None,
2003                Some(0),
2004            ])
2005            .into_data();
2006            // construct offsets
2007            let expected_offsets: [$offset_type; 6] = [0, 0, 0, 3, 5, 8];
2008            let expected_offsets = Buffer::from_slice_ref(&expected_offsets);
2009            // construct list array from the two
2010            let mut null_bits: [u8; 1] = [0; 1];
2011            bit_util::set_bit(&mut null_bits, 2);
2012            bit_util::set_bit(&mut null_bits, 3);
2013            bit_util::set_bit(&mut null_bits, 4);
2014            let expected_list_data = ArrayData::builder(list_data_type)
2015                .len(5)
2016                // null buffer must be recalculated as both values and indices have nulls
2017                .null_bit_buffer(Some(Buffer::from(null_bits)))
2018                .add_buffer(expected_offsets)
2019                .add_child_data(expected_data)
2020                .build()
2021                .unwrap();
2022            let expected_list_array = $list_array_type::from(expected_list_data);
2023
2024            assert_eq!(a, &expected_list_array);
2025        }};
2026    }
2027
2028    fn test_take_list_view_generic<OffsetType: OffsetSizeTrait, ValuesType: ArrowPrimitiveType, F>(
2029        values: Vec<Option<Vec<Option<ValuesType::Native>>>>,
2030        take_indices: Vec<Option<usize>>,
2031        expected: Vec<Option<Vec<Option<ValuesType::Native>>>>,
2032        mapper: F,
2033    ) where
2034        F: Fn(GenericListViewArray<OffsetType>) -> GenericListViewArray<OffsetType>,
2035    {
2036        let mut list_view_array =
2037            GenericListViewBuilder::<OffsetType, _>::new(PrimitiveBuilder::<ValuesType>::new());
2038
2039        for value in values {
2040            list_view_array.append_option(value);
2041        }
2042        let list_view_array = list_view_array.finish();
2043        let list_view_array = mapper(list_view_array);
2044
2045        let mut indices = UInt64Builder::new();
2046        for idx in take_indices {
2047            indices.append_option(idx.map(|i| i.to_u64().unwrap()));
2048        }
2049        let indices = indices.finish();
2050
2051        let taken = take(&list_view_array, &indices, None)
2052            .unwrap()
2053            .as_list_view()
2054            .clone();
2055
2056        let mut expected_array =
2057            GenericListViewBuilder::<OffsetType, _>::new(PrimitiveBuilder::<ValuesType>::new());
2058        for value in expected {
2059            expected_array.append_option(value);
2060        }
2061        let expected_array = expected_array.finish();
2062
2063        assert_eq!(taken, expected_array);
2064    }
2065
2066    macro_rules! list_view_test_case {
2067        (values: $values:expr, indices: $indices:expr, expected: $expected: expr) => {{
2068            test_take_list_view_generic::<i32, Int8Type, _>($values, $indices, $expected, |x| x);
2069            test_take_list_view_generic::<i64, Int8Type, _>($values, $indices, $expected, |x| x);
2070        }};
2071        (values: $values:expr, transform: $fn:expr, indices: $indices:expr, expected: $expected: expr) => {{
2072            test_take_list_view_generic::<i32, Int8Type, _>($values, $indices, $expected, $fn);
2073            test_take_list_view_generic::<i64, Int8Type, _>($values, $indices, $expected, $fn);
2074        }};
2075    }
2076
2077    fn do_take_fixed_size_list_test<T>(
2078        length: <Int32Type as ArrowPrimitiveType>::Native,
2079        input_data: Vec<Option<Vec<Option<T::Native>>>>,
2080        indices: Vec<<UInt32Type as ArrowPrimitiveType>::Native>,
2081        expected_data: Vec<Option<Vec<Option<T::Native>>>>,
2082    ) where
2083        T: ArrowPrimitiveType,
2084        PrimitiveArray<T>: From<Vec<Option<T::Native>>>,
2085    {
2086        let indices = UInt32Array::from(indices);
2087
2088        let input_array = FixedSizeListArray::from_iter_primitive::<T, _, _>(input_data, length);
2089
2090        let output = take_fixed_size_list(&input_array, &indices, length as u32).unwrap();
2091
2092        let expected = FixedSizeListArray::from_iter_primitive::<T, _, _>(expected_data, length);
2093
2094        assert_eq!(&output, &expected)
2095    }
2096
2097    #[test]
2098    fn test_take_list() {
2099        test_take_list!(i32, List, ListArray);
2100    }
2101
2102    #[test]
2103    fn test_take_large_list() {
2104        test_take_list!(i64, LargeList, LargeListArray);
2105    }
2106
2107    #[test]
2108    fn test_take_list_with_value_nulls() {
2109        test_take_list_with_value_nulls!(i32, List, ListArray);
2110    }
2111
2112    #[test]
2113    fn test_take_large_list_with_value_nulls() {
2114        test_take_list_with_value_nulls!(i64, LargeList, LargeListArray);
2115    }
2116
2117    #[test]
2118    fn test_test_take_list_with_nulls() {
2119        test_take_list_with_nulls!(i32, List, ListArray);
2120    }
2121
2122    #[test]
2123    fn test_test_take_large_list_with_nulls() {
2124        test_take_list_with_nulls!(i64, LargeList, LargeListArray);
2125    }
2126
2127    #[test]
2128    fn test_test_take_list_view_reversed() {
2129        // Take reversed indices
2130        list_view_test_case! {
2131            values: vec![
2132                Some(vec![Some(1), None, Some(3)]),
2133                None,
2134                Some(vec![Some(7), Some(8), None]),
2135            ],
2136            indices: vec![Some(2), Some(1), Some(0)],
2137            expected: vec![
2138                Some(vec![Some(7), Some(8), None]),
2139                None,
2140                Some(vec![Some(1), None, Some(3)]),
2141            ]
2142        }
2143    }
2144
2145    #[test]
2146    fn test_take_list_view_null_indices() {
2147        // Take with null indices
2148        list_view_test_case! {
2149            values: vec![
2150                Some(vec![Some(1), None, Some(3)]),
2151                None,
2152                Some(vec![Some(7), Some(8), None]),
2153            ],
2154            indices: vec![None, Some(0), None],
2155            expected: vec![None, Some(vec![Some(1), None, Some(3)]), None]
2156        }
2157    }
2158
2159    #[test]
2160    fn test_take_list_view_null_values() {
2161        // Take at null values
2162        list_view_test_case! {
2163            values: vec![
2164                Some(vec![Some(1), None, Some(3)]),
2165                None,
2166                Some(vec![Some(7), Some(8), None]),
2167            ],
2168            indices: vec![Some(1), Some(1), Some(1), None, None],
2169            expected: vec![None; 5]
2170        }
2171    }
2172
2173    #[test]
2174    fn test_take_list_view_sliced() {
2175        // Take null indices/values, with slicing.
2176        list_view_test_case! {
2177            values: vec![
2178                Some(vec![Some(1)]),
2179                None,
2180                None,
2181                Some(vec![Some(2), Some(3)]),
2182                Some(vec![Some(4), Some(5)]),
2183                None,
2184            ],
2185            transform: |l| l.slice(2, 4),
2186            indices: vec![Some(0), Some(3), None, Some(1), Some(2)],
2187            expected: vec![
2188                None, None, None, Some(vec![Some(2), Some(3)]), Some(vec![Some(4), Some(5)])
2189            ]
2190        }
2191    }
2192
2193    #[test]
2194    fn test_take_fixed_size_list() {
2195        do_take_fixed_size_list_test::<Int32Type>(
2196            3,
2197            vec![
2198                Some(vec![None, Some(1), Some(2)]),
2199                Some(vec![Some(3), Some(4), None]),
2200                Some(vec![Some(6), Some(7), Some(8)]),
2201            ],
2202            vec![2, 1, 0],
2203            vec![
2204                Some(vec![Some(6), Some(7), Some(8)]),
2205                Some(vec![Some(3), Some(4), None]),
2206                Some(vec![None, Some(1), Some(2)]),
2207            ],
2208        );
2209
2210        do_take_fixed_size_list_test::<UInt8Type>(
2211            1,
2212            vec![
2213                Some(vec![Some(1)]),
2214                Some(vec![Some(2)]),
2215                Some(vec![Some(3)]),
2216                Some(vec![Some(4)]),
2217                Some(vec![Some(5)]),
2218                Some(vec![Some(6)]),
2219                Some(vec![Some(7)]),
2220                Some(vec![Some(8)]),
2221            ],
2222            vec![2, 7, 0],
2223            vec![
2224                Some(vec![Some(3)]),
2225                Some(vec![Some(8)]),
2226                Some(vec![Some(1)]),
2227            ],
2228        );
2229
2230        do_take_fixed_size_list_test::<UInt64Type>(
2231            3,
2232            vec![
2233                Some(vec![Some(10), Some(11), Some(12)]),
2234                Some(vec![Some(13), Some(14), Some(15)]),
2235                None,
2236                Some(vec![Some(16), Some(17), Some(18)]),
2237            ],
2238            vec![3, 2, 1, 2, 0],
2239            vec![
2240                Some(vec![Some(16), Some(17), Some(18)]),
2241                None,
2242                Some(vec![Some(13), Some(14), Some(15)]),
2243                None,
2244                Some(vec![Some(10), Some(11), Some(12)]),
2245            ],
2246        );
2247    }
2248
2249    #[test]
2250    fn test_take_fixed_size_binary_with_nulls_indices() {
2251        let fsb = FixedSizeBinaryArray::try_from_sparse_iter_with_size(
2252            [
2253                Some(vec![0x01, 0x01, 0x01, 0x01]),
2254                Some(vec![0x02, 0x02, 0x02, 0x02]),
2255                Some(vec![0x03, 0x03, 0x03, 0x03]),
2256                Some(vec![0x04, 0x04, 0x04, 0x04]),
2257            ]
2258            .into_iter(),
2259            4,
2260        )
2261        .unwrap();
2262
2263        // The two middle indices are null -> Should be null in the output.
2264        let indices = UInt32Array::from(vec![Some(0), None, None, Some(3)]);
2265
2266        let result = take_fixed_size_binary(&fsb, &indices, 4).unwrap();
2267        assert_eq!(result.len(), 4);
2268        assert_eq!(result.null_count(), 2);
2269        assert_eq!(
2270            result.nulls().unwrap().iter().collect::<Vec<_>>(),
2271            vec![true, false, false, true]
2272        );
2273    }
2274
2275    /// The [`take_fixed_size_binary`] kernel contains optimizations that provide a faster
2276    /// implementation for commonly-used value lengths. This test uses a value length that is not
2277    /// optimized to test both code paths.
2278    #[test]
2279    fn test_take_fixed_size_binary_with_nulls_indices_not_optimized_length() {
2280        let fsb = FixedSizeBinaryArray::try_from_sparse_iter_with_size(
2281            [
2282                Some(vec![0x01, 0x01, 0x01, 0x01, 0x01]),
2283                Some(vec![0x02, 0x02, 0x02, 0x02, 0x01]),
2284                Some(vec![0x03, 0x03, 0x03, 0x03, 0x01]),
2285                Some(vec![0x04, 0x04, 0x04, 0x04, 0x01]),
2286            ]
2287            .into_iter(),
2288            5,
2289        )
2290        .unwrap();
2291
2292        // The two middle indices are null -> Should be null in the output.
2293        let indices = UInt32Array::from(vec![Some(0), None, None, Some(3)]);
2294
2295        let result = take_fixed_size_binary(&fsb, &indices, 5).unwrap();
2296        assert_eq!(result.len(), 4);
2297        assert_eq!(result.null_count(), 2);
2298        assert_eq!(
2299            result.nulls().unwrap().iter().collect::<Vec<_>>(),
2300            vec![true, false, false, true]
2301        );
2302    }
2303
2304    #[test]
2305    #[should_panic(expected = "index out of bounds: the len is 4 but the index is 1000")]
2306    fn test_take_list_out_of_bounds() {
2307        // Construct a value array, [[0,0,0], [-1,-2,-1], [2,3]]
2308        let value_data = Int32Array::from(vec![0, 0, 0, -1, -2, -1, 2, 3]).into_data();
2309        // Construct offsets
2310        let value_offsets = Buffer::from_slice_ref([0, 3, 6, 8]);
2311        // Construct a list array from the above two
2312        let list_data_type =
2313            DataType::List(Arc::new(Field::new_list_field(DataType::Int32, false)));
2314        let list_data = ArrayData::builder(list_data_type)
2315            .len(3)
2316            .add_buffer(value_offsets)
2317            .add_child_data(value_data)
2318            .build()
2319            .unwrap();
2320        let list_array = ListArray::from(list_data);
2321
2322        let index = UInt32Array::from(vec![1000]);
2323
2324        // A panic is expected here since we have not supplied the check_bounds
2325        // option.
2326        take(&list_array, &index, None).unwrap();
2327    }
2328
2329    #[test]
2330    fn test_take_map() {
2331        let values = Int32Array::from(vec![1, 2, 3, 4]);
2332        let array =
2333            MapArray::new_from_strings(vec!["a", "b", "c", "a"].into_iter(), &values, &[0, 3, 4])
2334                .unwrap();
2335
2336        let index = UInt32Array::from(vec![0]);
2337
2338        let result = take(&array, &index, None).unwrap();
2339        let expected: ArrayRef = Arc::new(
2340            MapArray::new_from_strings(
2341                vec!["a", "b", "c"].into_iter(),
2342                &values.slice(0, 3),
2343                &[0, 3],
2344            )
2345            .unwrap(),
2346        );
2347        assert_eq!(&expected, &result);
2348    }
2349
2350    #[test]
2351    fn test_take_struct() {
2352        let array = create_test_struct(vec![
2353            Some((Some(true), Some(42))),
2354            Some((Some(false), Some(28))),
2355            Some((Some(false), Some(19))),
2356            Some((Some(true), Some(31))),
2357            None,
2358        ]);
2359
2360        let index = UInt32Array::from(vec![0, 3, 1, 0, 2, 4]);
2361        let actual = take(&array, &index, None).unwrap();
2362        let actual: &StructArray = actual.as_any().downcast_ref::<StructArray>().unwrap();
2363        assert_eq!(index.len(), actual.len());
2364        assert_eq!(1, actual.null_count());
2365
2366        let expected = create_test_struct(vec![
2367            Some((Some(true), Some(42))),
2368            Some((Some(true), Some(31))),
2369            Some((Some(false), Some(28))),
2370            Some((Some(true), Some(42))),
2371            Some((Some(false), Some(19))),
2372            None,
2373        ]);
2374
2375        assert_eq!(&expected, actual);
2376
2377        let nulls = NullBuffer::from(&[false, true, false, true, false, true]);
2378        let empty_struct_arr = StructArray::new_empty_fields(6, Some(nulls));
2379        let index = UInt32Array::from(vec![0, 2, 1, 4]);
2380        let actual = take(&empty_struct_arr, &index, None).unwrap();
2381
2382        let expected_nulls = NullBuffer::from(&[false, false, true, false]);
2383        let expected_struct_arr = StructArray::new_empty_fields(4, Some(expected_nulls));
2384        assert_eq!(&expected_struct_arr, actual.as_struct());
2385    }
2386
2387    #[test]
2388    fn test_take_struct_with_null_indices() {
2389        let array = create_test_struct(vec![
2390            Some((Some(true), Some(42))),
2391            Some((Some(false), Some(28))),
2392            Some((Some(false), Some(19))),
2393            Some((Some(true), Some(31))),
2394            None,
2395        ]);
2396
2397        let index = UInt32Array::from(vec![None, Some(3), Some(1), None, Some(0), Some(4)]);
2398        let actual = take(&array, &index, None).unwrap();
2399        let actual: &StructArray = actual.as_any().downcast_ref::<StructArray>().unwrap();
2400        assert_eq!(index.len(), actual.len());
2401        assert_eq!(3, actual.null_count()); // 2 because of indices, 1 because of struct array
2402
2403        let expected = create_test_struct(vec![
2404            None,
2405            Some((Some(true), Some(31))),
2406            Some((Some(false), Some(28))),
2407            None,
2408            Some((Some(true), Some(42))),
2409            None,
2410        ]);
2411
2412        assert_eq!(&expected, actual);
2413    }
2414
2415    #[test]
2416    fn test_take_out_of_bounds() {
2417        let index = UInt32Array::from(vec![Some(3), None, Some(1), Some(3), Some(6)]);
2418        let take_opt = TakeOptions { check_bounds: true };
2419
2420        // int64
2421        let result = test_take_primitive_arrays::<Int64Type>(
2422            vec![Some(0), None, Some(2), Some(3), None],
2423            &index,
2424            Some(take_opt),
2425            vec![None],
2426        );
2427        assert!(result.is_err());
2428    }
2429
2430    #[test]
2431    #[should_panic(expected = "index out of bounds: the len is 4 but the index is 1000")]
2432    fn test_take_out_of_bounds_panic() {
2433        let index = UInt32Array::from(vec![Some(1000)]);
2434
2435        test_take_primitive_arrays::<Int64Type>(
2436            vec![Some(0), Some(1), Some(2), Some(3)],
2437            &index,
2438            None,
2439            vec![None],
2440        )
2441        .unwrap();
2442    }
2443
2444    #[test]
2445    fn test_null_array_smaller_than_indices() {
2446        let values = NullArray::new(2);
2447        let indices = UInt32Array::from(vec![Some(0), None, Some(15)]);
2448
2449        let result = take(&values, &indices, None).unwrap();
2450        let expected: ArrayRef = Arc::new(NullArray::new(3));
2451        assert_eq!(&result, &expected);
2452    }
2453
2454    #[test]
2455    fn test_null_array_larger_than_indices() {
2456        let values = NullArray::new(5);
2457        let indices = UInt32Array::from(vec![Some(0), None, Some(15)]);
2458
2459        let result = take(&values, &indices, None).unwrap();
2460        let expected: ArrayRef = Arc::new(NullArray::new(3));
2461        assert_eq!(&result, &expected);
2462    }
2463
2464    #[test]
2465    fn test_null_array_indices_out_of_bounds() {
2466        let values = NullArray::new(5);
2467        let indices = UInt32Array::from(vec![Some(0), None, Some(15)]);
2468
2469        let result = take(&values, &indices, Some(TakeOptions { check_bounds: true }));
2470        assert_eq!(
2471            result.unwrap_err().to_string(),
2472            "Compute error: Array index out of bounds, cannot get item at index 15 from 5 entries"
2473        );
2474    }
2475
2476    #[test]
2477    fn test_take_dict() {
2478        let mut dict_builder = StringDictionaryBuilder::<Int16Type>::new();
2479
2480        dict_builder.append("foo").unwrap();
2481        dict_builder.append("bar").unwrap();
2482        dict_builder.append("").unwrap();
2483        dict_builder.append_null();
2484        dict_builder.append("foo").unwrap();
2485        dict_builder.append("bar").unwrap();
2486        dict_builder.append("bar").unwrap();
2487        dict_builder.append("foo").unwrap();
2488
2489        let array = dict_builder.finish();
2490        let dict_values = array.values().clone();
2491        let dict_values = dict_values.as_any().downcast_ref::<StringArray>().unwrap();
2492
2493        let indices = UInt32Array::from(vec![
2494            Some(0), // first "foo"
2495            Some(7), // last "foo"
2496            None,    // null index should return null
2497            Some(5), // second "bar"
2498            Some(6), // another "bar"
2499            Some(2), // empty string
2500            Some(3), // input is null at this index
2501        ]);
2502
2503        let result = take(&array, &indices, None).unwrap();
2504        let result = result
2505            .as_any()
2506            .downcast_ref::<DictionaryArray<Int16Type>>()
2507            .unwrap();
2508
2509        let result_values: StringArray = result.values().to_data().into();
2510
2511        // dictionary values should stay the same
2512        let expected_values = StringArray::from(vec!["foo", "bar", ""]);
2513        assert_eq!(&expected_values, dict_values);
2514        assert_eq!(&expected_values, &result_values);
2515
2516        let expected_keys = Int16Array::from(vec![
2517            Some(0),
2518            Some(0),
2519            None,
2520            Some(1),
2521            Some(1),
2522            Some(2),
2523            None,
2524        ]);
2525        assert_eq!(result.keys(), &expected_keys);
2526    }
2527
2528    fn build_generic_list<S, T>(data: Vec<Option<Vec<T::Native>>>) -> GenericListArray<S>
2529    where
2530        S: OffsetSizeTrait + 'static,
2531        T: ArrowPrimitiveType,
2532        PrimitiveArray<T>: From<Vec<Option<T::Native>>>,
2533    {
2534        GenericListArray::from_iter_primitive::<T, _, _>(
2535            data.iter()
2536                .map(|x| x.as_ref().map(|x| x.iter().map(|x| Some(*x)))),
2537        )
2538    }
2539
2540    fn test_take_sliced_list_generic<S: OffsetSizeTrait + 'static>() {
2541        let list = build_generic_list::<S, Int32Type>(vec![
2542            Some(vec![0, 1]),
2543            Some(vec![2, 3, 4]),
2544            None,
2545            Some(vec![]),
2546            Some(vec![5, 6]),
2547            Some(vec![7]),
2548        ]);
2549        let sliced = list.slice(1, 4);
2550        let indices = UInt32Array::from(vec![Some(3), Some(0), None, Some(2), Some(1)]);
2551
2552        let taken = take(&sliced, &indices, None).unwrap();
2553        let taken = taken.as_list::<S>();
2554
2555        let expected = build_generic_list::<S, Int32Type>(vec![
2556            Some(vec![5, 6]),
2557            Some(vec![2, 3, 4]),
2558            None,
2559            Some(vec![]),
2560            None,
2561        ]);
2562
2563        assert_eq!(taken, &expected);
2564    }
2565
2566    fn test_take_sliced_list_with_value_nulls_generic<S: OffsetSizeTrait + 'static>() {
2567        let list = GenericListArray::<S>::from_iter_primitive::<Int32Type, _, _>(vec![
2568            Some(vec![Some(10)]),
2569            Some(vec![None, Some(1)]),
2570            None,
2571            Some(vec![Some(2), None]),
2572            Some(vec![]),
2573            Some(vec![Some(3)]),
2574        ]);
2575        let sliced = list.slice(1, 4);
2576        let indices = UInt32Array::from(vec![Some(2), Some(0), None, Some(3), Some(1)]);
2577
2578        let taken = take(&sliced, &indices, None).unwrap();
2579        let taken = taken.as_list::<S>();
2580
2581        let expected = GenericListArray::<S>::from_iter_primitive::<Int32Type, _, _>(vec![
2582            Some(vec![Some(2), None]),
2583            Some(vec![None, Some(1)]),
2584            None,
2585            Some(vec![]),
2586            None,
2587        ]);
2588
2589        assert_eq!(taken, &expected);
2590    }
2591
2592    #[test]
2593    fn test_take_sliced_list() {
2594        test_take_sliced_list_generic::<i32>();
2595    }
2596
2597    #[test]
2598    fn test_take_sliced_large_list() {
2599        test_take_sliced_list_generic::<i64>();
2600    }
2601
2602    #[test]
2603    fn test_take_sliced_list_with_value_nulls() {
2604        test_take_sliced_list_with_value_nulls_generic::<i32>();
2605    }
2606
2607    #[test]
2608    fn test_take_sliced_large_list_with_value_nulls() {
2609        test_take_sliced_list_with_value_nulls_generic::<i64>();
2610    }
2611
2612    #[test]
2613    fn test_take_runs() {
2614        let logical_array: Vec<i32> = vec![1_i32, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 2];
2615
2616        let mut builder = PrimitiveRunBuilder::<Int32Type, Int32Type>::new();
2617        builder.extend(logical_array.into_iter().map(Some));
2618        let run_array = builder.finish();
2619
2620        let take_indices: PrimitiveArray<Int32Type> =
2621            vec![7, 2, 3, 7, 11, 4, 6].into_iter().collect();
2622
2623        let take_out = take_run(&run_array, &take_indices).unwrap();
2624
2625        assert_eq!(take_out.len(), 7);
2626        // adjacent identical values are merged: [2,2,2,2,2,1,1] -> 2 runs
2627        assert_eq!(
2628            take_out.run_ends().values().len(),
2629            2,
2630            "expected two physical runs"
2631        );
2632        assert_eq!(take_out.run_ends().values(), &[5_i32, 7]);
2633
2634        let take_out_values = take_out.values().as_primitive::<Int32Type>();
2635        assert_eq!(take_out_values.values(), &[2, 1]);
2636    }
2637
2638    #[test]
2639    fn test_take_runs_sliced() {
2640        let logical_array: Vec<i32> = vec![1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6];
2641
2642        let mut builder = PrimitiveRunBuilder::<Int32Type, Int32Type>::new();
2643        builder.extend(logical_array.into_iter().map(Some));
2644        let run_array = builder.finish();
2645
2646        let run_array = run_array.slice(4, 6); // [3, 3, 3, 4, 4, 5]
2647
2648        let take_indices: PrimitiveArray<Int32Type> = vec![0, 5, 5, 1, 4].into_iter().collect();
2649
2650        let result = take_run(&run_array, &take_indices).unwrap();
2651        let result = result.downcast::<Int32Array>().unwrap();
2652
2653        // [3, 5, 5, 3, 4] -> 4 physical runs (no adjacent duplicates to merge)
2654        assert_eq!(
2655            result.run_ends().values().len(),
2656            4,
2657            "expected four physical runs"
2658        );
2659        assert_eq!(result.run_ends().values(), &[1_i32, 3, 4, 5]);
2660
2661        let expected = vec![3, 5, 5, 3, 4];
2662        let actual = result.into_iter().flatten().collect::<Vec<_>>();
2663
2664        assert_eq!(expected, actual);
2665    }
2666
2667    #[test]
2668    fn test_take_value_index_from_fixed_list() {
2669        let list = FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
2670            vec![
2671                Some(vec![Some(1), Some(2), None]),
2672                Some(vec![Some(4), None, Some(6)]),
2673                None,
2674                Some(vec![None, Some(8), Some(9)]),
2675            ],
2676            3,
2677        );
2678
2679        let indices = UInt32Array::from(vec![2, 1, 0]);
2680        let indexed = take_value_indices_from_fixed_size_list(&list, &indices, 3).unwrap();
2681
2682        assert_eq!(indexed, UInt32Array::from(vec![6, 7, 8, 3, 4, 5, 0, 1, 2]));
2683
2684        let indices = UInt32Array::from(vec![3, 2, 1, 2, 0]);
2685        let indexed = take_value_indices_from_fixed_size_list(&list, &indices, 3).unwrap();
2686
2687        assert_eq!(
2688            indexed,
2689            UInt32Array::from(vec![9, 10, 11, 6, 7, 8, 3, 4, 5, 6, 7, 8, 0, 1, 2])
2690        );
2691    }
2692
2693    #[test]
2694    fn test_take_null_indices() {
2695        // Build indices with values that are out of bounds, but masked by null mask
2696        let indices = Int32Array::new(
2697            vec![1, 2, 400, 400].into(),
2698            Some(NullBuffer::from(vec![true, true, false, false])),
2699        );
2700        let values = Int32Array::from(vec![1, 23, 4, 5]);
2701        let r = take(&values, &indices, None).unwrap();
2702        let values = r
2703            .as_primitive::<Int32Type>()
2704            .into_iter()
2705            .collect::<Vec<_>>();
2706        assert_eq!(&values, &[Some(23), Some(4), None, None])
2707    }
2708
2709    #[test]
2710    fn test_take_fixed_size_list_null_indices() {
2711        let indices = Int32Array::from_iter([Some(0), None]);
2712        let values = Arc::new(Int32Array::from(vec![0, 1, 2, 3]));
2713        let arr_field = Arc::new(Field::new_list_field(values.data_type().clone(), true));
2714        let values = FixedSizeListArray::try_new(arr_field, 2, values, None).unwrap();
2715
2716        let r = take(&values, &indices, None).unwrap();
2717        let values = r
2718            .as_fixed_size_list()
2719            .values()
2720            .as_primitive::<Int32Type>()
2721            .into_iter()
2722            .collect::<Vec<_>>();
2723        assert_eq!(values, &[Some(0), Some(1), None, None])
2724    }
2725
2726    #[test]
2727    fn test_take_bytes_null_indices() {
2728        let indices = Int32Array::new(
2729            vec![0, 1, 400, 400].into(),
2730            Some(NullBuffer::from_iter(vec![true, true, false, false])),
2731        );
2732        let values = StringArray::from(vec![Some("foo"), None]);
2733        let r = take(&values, &indices, None).unwrap();
2734        let values = r.as_string::<i32>().iter().collect::<Vec<_>>();
2735        assert_eq!(&values, &[Some("foo"), None, None, None])
2736    }
2737
2738    #[test]
2739    fn test_take_union_sparse() {
2740        let structs = create_test_struct(vec![
2741            Some((Some(true), Some(42))),
2742            Some((Some(false), Some(28))),
2743            Some((Some(false), Some(19))),
2744            Some((Some(true), Some(31))),
2745            None,
2746        ]);
2747        let strings = StringArray::from(vec![Some("a"), None, Some("c"), None, Some("d")]);
2748        let type_ids = [1; 5].into_iter().collect::<ScalarBuffer<i8>>();
2749
2750        let union_fields = [
2751            (
2752                0,
2753                Arc::new(Field::new("f1", structs.data_type().clone(), true)),
2754            ),
2755            (
2756                1,
2757                Arc::new(Field::new("f2", strings.data_type().clone(), true)),
2758            ),
2759        ]
2760        .into_iter()
2761        .collect();
2762        let children = vec![Arc::new(structs) as Arc<dyn Array>, Arc::new(strings)];
2763        let array = UnionArray::try_new(union_fields, type_ids, None, children).unwrap();
2764
2765        let indices = vec![0, 3, 1, 0, 2, 4];
2766        let index = UInt32Array::from(indices.clone());
2767        let actual = take(&array, &index, None).unwrap();
2768        let actual = actual.as_any().downcast_ref::<UnionArray>().unwrap();
2769        let strings = actual.child(1);
2770        let strings = strings.as_any().downcast_ref::<StringArray>().unwrap();
2771
2772        let actual = strings.iter().collect::<Vec<_>>();
2773        let expected = vec![Some("a"), None, None, Some("a"), Some("c"), Some("d")];
2774        assert_eq!(expected, actual);
2775    }
2776
2777    #[test]
2778    fn test_take_union_dense() {
2779        let type_ids = vec![0, 1, 1, 0, 0, 1, 0];
2780        let offsets = vec![0, 0, 1, 1, 2, 2, 3];
2781        let ints = vec![10, 20, 30, 40];
2782        let strings = vec![Some("a"), None, Some("c"), Some("d")];
2783
2784        let indices = vec![0, 3, 1, 0, 2, 4];
2785
2786        let taken_type_ids = vec![0, 0, 1, 0, 1, 0];
2787        let taken_offsets = vec![0, 1, 0, 2, 1, 3];
2788        let taken_ints = vec![10, 20, 10, 30];
2789        let taken_strings = vec![Some("a"), None];
2790
2791        let type_ids = <ScalarBuffer<i8>>::from(type_ids);
2792        let offsets = <ScalarBuffer<i32>>::from(offsets);
2793        let ints = UInt32Array::from(ints);
2794        let strings = StringArray::from(strings);
2795
2796        let union_fields = [
2797            (
2798                0,
2799                Arc::new(Field::new("f1", ints.data_type().clone(), true)),
2800            ),
2801            (
2802                1,
2803                Arc::new(Field::new("f2", strings.data_type().clone(), true)),
2804            ),
2805        ]
2806        .into_iter()
2807        .collect();
2808
2809        let array = UnionArray::try_new(
2810            union_fields,
2811            type_ids,
2812            Some(offsets),
2813            vec![Arc::new(ints), Arc::new(strings)],
2814        )
2815        .unwrap();
2816
2817        let index = UInt32Array::from(indices);
2818
2819        let actual = take(&array, &index, None).unwrap();
2820        let actual = actual.as_any().downcast_ref::<UnionArray>().unwrap();
2821
2822        assert_eq!(actual.offsets(), Some(&ScalarBuffer::from(taken_offsets)));
2823        assert_eq!(actual.type_ids(), &ScalarBuffer::from(taken_type_ids));
2824        assert_eq!(
2825            UInt32Array::from(actual.child(0).to_data()),
2826            UInt32Array::from(taken_ints)
2827        );
2828        assert_eq!(
2829            StringArray::from(actual.child(1).to_data()),
2830            StringArray::from(taken_strings)
2831        );
2832    }
2833
2834    #[test]
2835    fn test_take_union_dense_using_builder() {
2836        let mut builder = UnionBuilder::new_dense();
2837
2838        builder.append::<Int32Type>("a", 1).unwrap();
2839        builder.append::<Float64Type>("b", 3.0).unwrap();
2840        builder.append::<Int32Type>("a", 4).unwrap();
2841        builder.append::<Int32Type>("a", 5).unwrap();
2842        builder.append::<Float64Type>("b", 2.0).unwrap();
2843
2844        let union = builder.build().unwrap();
2845
2846        let indices = UInt32Array::from(vec![2, 0, 1, 2]);
2847
2848        let mut builder = UnionBuilder::new_dense();
2849
2850        builder.append::<Int32Type>("a", 4).unwrap();
2851        builder.append::<Int32Type>("a", 1).unwrap();
2852        builder.append::<Float64Type>("b", 3.0).unwrap();
2853        builder.append::<Int32Type>("a", 4).unwrap();
2854
2855        let taken = builder.build().unwrap();
2856
2857        assert_eq!(
2858            taken.to_data(),
2859            take(&union, &indices, None).unwrap().to_data()
2860        );
2861    }
2862
2863    #[test]
2864    fn test_take_union_dense_all_match_issue_6206() {
2865        let fields = UnionFields::from_fields(vec![Field::new("a", DataType::Int64, false)]);
2866        let ints = Arc::new(Int64Array::from(vec![1, 2, 3, 4, 5]));
2867
2868        let array = UnionArray::try_new(
2869            fields,
2870            ScalarBuffer::from(vec![0_i8, 0, 0, 0, 0]),
2871            Some(ScalarBuffer::from_iter(0_i32..5)),
2872            vec![ints],
2873        )
2874        .unwrap();
2875
2876        let indicies = Int64Array::from(vec![0, 2, 4]);
2877        let array = take(&array, &indicies, None).unwrap();
2878        assert_eq!(array.len(), 3);
2879    }
2880
2881    /// Fixture for the offset-overflow tests: a single large value plus the
2882    /// number of times it must be selected so the cumulative offset exceeds
2883    /// `i32::MAX`. Using a large value keeps the index count (and the test
2884    /// runtime) small.
2885    fn offset_overflow_fixture() -> (StringArray, usize) {
2886        let value_len = 1_000_000;
2887        let values = StringArray::from(vec![Some("a".repeat(value_len))]);
2888        let n = i32::MAX as usize / value_len + 1;
2889        (values, n)
2890    }
2891
2892    #[test]
2893    fn test_take_bytes_offset_overflow() {
2894        let (values, n) = offset_overflow_fixture();
2895        let indices = Int32Array::from(vec![0; n]);
2896        assert!(matches!(
2897            take(&values, &indices, None),
2898            Err(ArrowError::OffsetOverflowError(_))
2899        ));
2900    }
2901
2902    /// The offset-overflow error must also be produced on the nullable code
2903    /// path (when the output contains nulls), not only on the no-null fast path.
2904    #[test]
2905    fn test_take_bytes_offset_overflow_nullable() {
2906        let (values, n) = offset_overflow_fixture();
2907        // A null index forces the output to contain nulls, exercising the
2908        // nullable code path.
2909        let validity =
2910            NullBuffer::from_iter(std::iter::once(false).chain(std::iter::repeat_n(true, n)));
2911        let indices = Int32Array::new(vec![0i32; n + 1].into(), Some(validity));
2912
2913        assert!(matches!(
2914            take(&values, &indices, None),
2915            Err(ArrowError::OffsetOverflowError(_))
2916        ));
2917    }
2918
2919    #[test]
2920    fn test_take_run_empty_indices() {
2921        let mut builder = PrimitiveRunBuilder::<Int32Type, Int32Type>::new();
2922        builder.extend([Some(1), Some(1), Some(2), Some(2)]);
2923        let run_array = builder.finish();
2924
2925        let logical_indices: PrimitiveArray<Int32Type> = PrimitiveArray::from(Vec::<i32>::new());
2926
2927        let result = take_impl(&run_array, &logical_indices).expect("take_run with empty indices");
2928
2929        // Verify the result is a valid empty RunArray
2930        assert_eq!(result.len(), 0);
2931        assert_eq!(result.null_count(), 0);
2932
2933        // Verify that the result can be downcast and used without validation errors
2934        // This specifically tests that "The values in run_ends array should be strictly positive" is not triggered
2935        let run_result = result
2936            .as_any()
2937            .downcast_ref::<RunArray<Int32Type>>()
2938            .expect("result should be a RunArray");
2939        assert_eq!(run_result.run_ends().len(), 0);
2940        assert_eq!(run_result.values().len(), 0);
2941    }
2942
2943    #[test]
2944    fn test_take_run_end_encoded_merges_identical_runs() {
2945        // https://github.com/apache/arrow-rs/issues/7710
2946        // Indices [0,1,4,5] select from [1,1,0,0,1,1] — the 0s are skipped,
2947        // so the output should be a single run of 1s, not two.
2948        let mut builder = PrimitiveRunBuilder::<Int32Type, Int32Type>::new();
2949        builder.extend([1, 1, 0, 0, 1, 1].into_iter().map(Some));
2950        let ree = builder.finish();
2951
2952        let indexes = Int32Array::from_iter_values(vec![0, 1, 4, 5]);
2953        let result = take(&ree, &indexes, None).unwrap();
2954        let result = result
2955            .as_run::<Int32Type>()
2956            .downcast::<Int32Array>()
2957            .unwrap();
2958
2959        // Verify physical layout: all four logical values collapse into one run.
2960        assert_eq!(
2961            result.run_ends().values().len(),
2962            1,
2963            "expected a single physical run"
2964        );
2965        assert_eq!(result.run_ends().values(), &[4_i32]);
2966
2967        let actual = result.into_iter().flatten().collect::<Vec<_>>();
2968        assert_eq!(actual, vec![1, 1, 1, 1]);
2969    }
2970
2971    #[test]
2972    fn test_take_run_end_encoded_merges_identical_string_runs() {
2973        let mut builder = StringRunBuilder::<Int32Type>::new();
2974        builder.extend(
2975            ["bob", "bob", "alice", "alice", "bob", "bob"]
2976                .into_iter()
2977                .map(Some),
2978        );
2979        let ree = builder.finish();
2980
2981        let indexes = Int32Array::from_iter_values(vec![0, 1, 4, 5]);
2982        let result = take(&ree, &indexes, None).unwrap();
2983        let result = result
2984            .as_run::<Int32Type>()
2985            .downcast::<StringArray>()
2986            .unwrap();
2987
2988        // Verify physical layout: all four logical values collapse into one run.
2989        assert_eq!(
2990            result.run_ends().values().len(),
2991            1,
2992            "expected a single physical run"
2993        );
2994        assert_eq!(result.run_ends().values(), &[4_i32]);
2995
2996        let actual = result.into_iter().flatten().collect::<Vec<_>>();
2997        assert_eq!(actual, vec!["bob", "bob", "bob", "bob"]);
2998    }
2999
3000    #[test]
3001    fn test_take_run_end_encoded_mixed_runs() {
3002        // Validates that runs are merged whether the same logical value comes
3003        // from the same physical index (repeated indices) or distinct physical indices.
3004        let mut builder = StringRunBuilder::<Int32Type>::new();
3005        builder.extend(
3006            ["bob", "bob", "alice", "alice", "bob", "bob", "eve", "eve"]
3007                .into_iter()
3008                .map(Some),
3009        );
3010        let ree = builder.finish();
3011
3012        // [bob,bob,bob,bob,bob,alice,alice,alice,eve,eve,eve]
3013        let indexes = Int32Array::from_iter_values(vec![0, 0, 1, 4, 5, 2, 3, 2, 6, 7, 6]);
3014        let result = take(&ree, &indexes, None).unwrap();
3015        let result = result
3016            .as_run::<Int32Type>()
3017            .downcast::<StringArray>()
3018            .unwrap();
3019
3020        // Verify physical layout: 11 logical values across exactly 3 physical runs.
3021
3022        println!("run_ends_raw: {:?}", result.run_ends());
3023        println!("run_ends: {:?}", result.run_ends().values());
3024        println!("values : {:?}", result.values());
3025        assert_eq!(
3026            result.run_ends().values().len(),
3027            3,
3028            "expected three physical runs"
3029        );
3030        assert_eq!(result.run_ends().values(), &[5_i32, 8, 11]);
3031
3032        let actual = result.into_iter().flatten().collect::<Vec<_>>();
3033        assert_eq!(
3034            actual,
3035            vec![
3036                "bob", "bob", "bob", "bob", "bob", "alice", "alice", "alice", "eve", "eve", "eve"
3037            ]
3038        );
3039    }
3040}