vortex_array/arrays/varbinview/compute/
take.rs1use std::ops::Deref;
5
6use num_traits::AsPrimitive;
7use vortex_buffer::Buffer;
8use vortex_dtype::match_each_integer_ptype;
9use vortex_error::VortexResult;
10
11use crate::arrays::{BinaryView, VarBinViewArray, VarBinViewVTable};
12use crate::compute::{TakeKernel, TakeKernelAdapter};
13use crate::vtable::ValidityHelper;
14use crate::{Array, ArrayRef, IntoArray, ToCanonical, register_kernel};
15
16impl TakeKernel for VarBinViewVTable {
18 fn take(&self, array: &VarBinViewArray, indices: &dyn Array) -> VortexResult<ArrayRef> {
19 let validity = array.validity().take(indices)?;
24 let indices = indices.to_primitive()?;
25
26 let views_buffer = match_each_integer_ptype!(indices.ptype(), |I| {
27 take_views(array.views(), indices.as_slice::<I>())
29 });
30
31 Ok(VarBinViewArray::try_new(
32 views_buffer,
33 array.buffers().clone(),
34 array
35 .dtype()
36 .union_nullability(indices.dtype().nullability()),
37 validity,
38 )?
39 .into_array())
40 }
41}
42
43register_kernel!(TakeKernelAdapter(VarBinViewVTable).lift());
44
45fn take_views<I: AsPrimitive<usize>>(
46 views: &Buffer<BinaryView>,
47 indices: &[I],
48) -> Buffer<BinaryView> {
49 let views_ref = views.deref();
51 Buffer::<BinaryView>::from_iter(indices.iter().map(|i| views_ref[i.as_()]))
52}
53
54#[cfg(test)]
55mod tests {
56 use rstest::rstest;
57 use vortex_buffer::buffer;
58 use vortex_dtype::DType;
59 use vortex_dtype::Nullability::NonNullable;
60
61 use crate::IntoArray;
62 use crate::accessor::ArrayAccessor;
63 use crate::array::Array;
64 use crate::arrays::{PrimitiveArray, VarBinViewArray};
65 use crate::canonical::ToCanonical;
66 use crate::compute::conformance::take::test_take_conformance;
67 use crate::compute::take;
68
69 #[test]
70 fn take_nullable() {
71 let arr = VarBinViewArray::from_iter_nullable_str([
72 Some("one"),
73 None,
74 Some("three"),
75 Some("four"),
76 None,
77 Some("six"),
78 ]);
79
80 let taken = take(arr.as_ref(), &buffer![0, 3].into_array()).unwrap();
81
82 assert!(taken.dtype().is_nullable());
83 assert_eq!(
84 taken
85 .to_varbinview()
86 .unwrap()
87 .with_iterator(|it| it
88 .map(|v| v.map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) }))
89 .collect::<Vec<_>>())
90 .unwrap(),
91 [Some("one".to_string()), Some("four".to_string())]
92 );
93 }
94
95 #[test]
96 fn take_nullable_indices() {
97 let arr = VarBinViewArray::from_iter(["one", "two"].map(Some), DType::Utf8(NonNullable));
98
99 let taken = take(
100 arr.as_ref(),
101 PrimitiveArray::from_option_iter(vec![Some(1), None]).as_ref(),
102 )
103 .unwrap();
104
105 assert!(taken.dtype().is_nullable());
106 assert_eq!(
107 taken
108 .to_varbinview()
109 .unwrap()
110 .with_iterator(|it| it
111 .map(|v| v.map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) }))
112 .collect::<Vec<_>>())
113 .unwrap(),
114 [Some("two".to_string()), None]
115 );
116 }
117
118 #[rstest]
119 #[case(VarBinViewArray::from_iter(
120 ["hello", "world", "test", "data", "array"].map(Some),
121 DType::Utf8(NonNullable),
122 ))]
123 #[case(VarBinViewArray::from_iter_nullable_str([
124 Some("hello"),
125 None,
126 Some("test"),
127 Some("data"),
128 None,
129 ]))]
130 #[case(VarBinViewArray::from_iter(
131 [b"hello".as_slice(), b"world", b"test", b"data", b"array"].map(Some),
132 DType::Binary(NonNullable),
133 ))]
134 #[case(VarBinViewArray::from_iter(["single"].map(Some), DType::Utf8(NonNullable)))]
135 fn test_take_varbinview_conformance(#[case] array: VarBinViewArray) {
136 test_take_conformance(array.as_ref());
137 }
138}