1use std::ops::Range;
5
6use vortex_array::Array;
7use vortex_array::ArrayRef;
8use vortex_array::IntoArray;
9use vortex_array::arrays::ConstantArray;
10use vortex_array::search_sorted::SearchResult;
11use vortex_array::search_sorted::SearchSorted;
12use vortex_array::search_sorted::SearchSortedSide;
13use vortex_array::vtable::OperationsVTable;
14use vortex_scalar::PValue;
15use vortex_scalar::Scalar;
16
17use crate::RunEndArray;
18use crate::RunEndVTable;
19
20impl OperationsVTable<RunEndVTable> for RunEndVTable {
21 fn slice(array: &RunEndArray, range: Range<usize>) -> ArrayRef {
22 let new_length = range.len();
23
24 let slice_begin = array.find_physical_index(range.start);
25 let slice_end = find_slice_end_index(array.ends(), range.end + array.offset());
26
27 if slice_begin + 1 == slice_end {
29 let value = array.values().scalar_at(slice_begin);
30 return ConstantArray::new(value, new_length).into_array();
31 }
32
33 unsafe {
35 RunEndArray::new_unchecked(
36 array.ends().slice(slice_begin..slice_end),
37 array.values().slice(slice_begin..slice_end),
38 range.start + array.offset(),
39 new_length,
40 )
41 .into_array()
42 }
43 }
44
45 fn scalar_at(array: &RunEndArray, index: usize) -> Scalar {
46 array.values().scalar_at(array.find_physical_index(index))
47 }
48}
49
50pub(crate) fn find_slice_end_index(array: &dyn Array, index: usize) -> usize {
55 let result = array
56 .as_primitive_typed()
57 .search_sorted(&PValue::from(index), SearchSortedSide::Right);
58 match result {
59 SearchResult::Found(i) => i,
60 SearchResult::NotFound(i) => {
61 if i == array.len() {
62 i
63 } else {
64 i + 1
65 }
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72
73 use vortex_array::Array;
74 use vortex_array::IntoArray;
75 use vortex_array::arrays::PrimitiveArray;
76 use vortex_array::assert_arrays_eq;
77 use vortex_buffer::buffer;
78 use vortex_dtype::DType;
79 use vortex_dtype::Nullability;
80 use vortex_dtype::PType;
81
82 use crate::RunEndArray;
83
84 #[test]
85 fn slice_array() {
86 let arr = RunEndArray::try_new(
87 buffer![2u32, 5, 10].into_array(),
88 buffer![1i32, 2, 3].into_array(),
89 )
90 .unwrap()
91 .slice(3..8);
92 assert_eq!(
93 arr.dtype(),
94 &DType::Primitive(PType::I32, Nullability::NonNullable)
95 );
96 assert_eq!(arr.len(), 5);
97
98 let expected = PrimitiveArray::from_iter(vec![2i32, 2, 3, 3, 3]).into_array();
99 assert_arrays_eq!(arr, expected);
100 }
101
102 #[test]
103 fn double_slice() {
104 let arr = RunEndArray::try_new(
105 buffer![2u32, 5, 10].into_array(),
106 buffer![1i32, 2, 3].into_array(),
107 )
108 .unwrap()
109 .slice(3..8);
110 assert_eq!(arr.len(), 5);
111
112 let doubly_sliced = arr.slice(0..3);
113
114 let expected = PrimitiveArray::from_iter(vec![2i32, 2, 3]).into_array();
115 assert_arrays_eq!(doubly_sliced, expected);
116 }
117
118 #[test]
119 fn slice_end_inclusive() {
120 let arr = RunEndArray::try_new(
121 buffer![2u32, 5, 10].into_array(),
122 buffer![1i32, 2, 3].into_array(),
123 )
124 .unwrap()
125 .slice(4..10);
126 assert_eq!(
127 arr.dtype(),
128 &DType::Primitive(PType::I32, Nullability::NonNullable)
129 );
130 assert_eq!(arr.len(), 6);
131
132 let expected = PrimitiveArray::from_iter(vec![2i32, 3, 3, 3, 3, 3]).into_array();
133 assert_arrays_eq!(arr, expected);
134 }
135
136 #[test]
137 fn slice_at_end() {
138 let re_array = RunEndArray::try_new(
139 buffer![7_u64, 10].into_array(),
140 buffer![2_u64, 3].into_array(),
141 )
142 .unwrap();
143
144 assert_eq!(re_array.len(), 10);
145
146 let sliced_array = re_array.slice(re_array.len()..re_array.len());
147 assert!(sliced_array.is_empty());
148 }
149
150 #[test]
151 fn slice_single_end() {
152 let re_array = RunEndArray::try_new(
153 buffer![7_u64, 10].into_array(),
154 buffer![2_u64, 3].into_array(),
155 )
156 .unwrap();
157
158 assert_eq!(re_array.len(), 10);
159
160 let sliced_array = re_array.slice(2..5);
161
162 assert!(sliced_array.is_constant())
163 }
164
165 #[test]
166 fn ree_scalar_at_end() {
167 let scalar = RunEndArray::encode(buffer![1, 1, 1, 4, 4, 4, 2, 2, 5, 5, 5, 5].into_array())
168 .unwrap()
169 .scalar_at(11);
170 assert_eq!(scalar, 5.into());
171 }
172
173 #[test]
174 #[allow(clippy::cognitive_complexity)]
175 fn slice_along_run_boundaries() {
176 let arr = RunEndArray::try_new(
179 buffer![3u32, 6, 8, 12].into_array(),
180 buffer![1i32, 4, 2, 5].into_array(),
181 )
182 .unwrap();
183
184 let slice1 = arr.slice(0..3);
186 assert_eq!(slice1.len(), 3);
187 let expected = PrimitiveArray::from_iter(vec![1i32, 1, 1]).into_array();
188 assert_arrays_eq!(slice1, expected);
189
190 let slice2 = arr.slice(3..6);
192 assert_eq!(slice2.len(), 3);
193 let expected = PrimitiveArray::from_iter(vec![4i32, 4, 4]).into_array();
194 assert_arrays_eq!(slice2, expected);
195
196 let slice3 = arr.slice(6..8);
198 assert_eq!(slice3.len(), 2);
199 let expected = PrimitiveArray::from_iter(vec![2i32, 2]).into_array();
200 assert_arrays_eq!(slice3, expected);
201
202 let slice4 = arr.slice(8..12);
204 assert_eq!(slice4.len(), 4);
205 let expected = PrimitiveArray::from_iter(vec![5i32, 5, 5, 5]).into_array();
206 assert_arrays_eq!(slice4, expected);
207
208 let slice5 = arr.slice(3..8);
210 assert_eq!(slice5.len(), 5);
211 let expected = PrimitiveArray::from_iter(vec![4i32, 4, 4, 2, 2]).into_array();
212 assert_arrays_eq!(slice5, expected);
213
214 let slice6 = arr.slice(1..6);
216 assert_eq!(slice6.len(), 5);
217 let expected = PrimitiveArray::from_iter(vec![1i32, 1, 4, 4, 4]).into_array();
218 assert_arrays_eq!(slice6, expected);
219
220 let slice7 = arr.slice(3..7);
222 assert_eq!(slice7.len(), 4);
223 let expected = PrimitiveArray::from_iter(vec![4i32, 4, 4, 2]).into_array();
224 assert_arrays_eq!(slice7, expected);
225 }
226}