polars_compute/gather/sublist/
fixed_size_list.rs1use arrow::array::{ArrayRef, FixedSizeListArray, PrimitiveArray};
2use arrow::legacy::prelude::*;
3use arrow::legacy::utils::CustomIterTools;
4use polars_error::{polars_bail, PolarsResult};
5use polars_utils::index::NullCount;
6use polars_utils::IdxSize;
7
8use crate::gather::take_unchecked;
9
10fn sub_fixed_size_list_get_indexes_literal(width: usize, len: usize, index: i64) -> IdxArr {
11 (0..len)
12 .map(|i| {
13 if index >= width as i64 {
14 return None;
15 }
16
17 index
18 .negative_to_usize(width)
19 .map(|idx| (idx + i * width) as IdxSize)
20 })
21 .collect_trusted()
22}
23
24fn sub_fixed_size_list_get_indexes(width: usize, index: &PrimitiveArray<i64>) -> IdxArr {
25 index
26 .iter()
27 .enumerate()
28 .map(|(i, idx)| {
29 if let Some(idx) = idx {
30 if *idx >= width as i64 {
31 return None;
32 }
33
34 idx.negative_to_usize(width)
35 .map(|idx| (idx + i * width) as IdxSize)
36 } else {
37 None
38 }
39 })
40 .collect_trusted()
41}
42
43pub fn sub_fixed_size_list_get_literal(
44 arr: &FixedSizeListArray,
45 index: i64,
46 null_on_oob: bool,
47) -> PolarsResult<ArrayRef> {
48 let take_by = sub_fixed_size_list_get_indexes_literal(arr.size(), arr.len(), index);
49 if !null_on_oob && take_by.null_count() > 0 {
50 polars_bail!(ComputeError: "get index is out of bounds");
51 }
52
53 let values = arr.values();
54 unsafe { Ok(take_unchecked(&**values, &take_by)) }
57}
58
59pub fn sub_fixed_size_list_get(
60 arr: &FixedSizeListArray,
61 index: &PrimitiveArray<i64>,
62 null_on_oob: bool,
63) -> PolarsResult<ArrayRef> {
64 let take_by = sub_fixed_size_list_get_indexes(arr.size(), index);
65 if !null_on_oob && take_by.null_count() > 0 {
66 polars_bail!(ComputeError: "get index is out of bounds");
67 }
68
69 let values = arr.values();
70 unsafe { Ok(take_unchecked(&**values, &take_by)) }
73}