1use vortex_array::arrays::ConstantArray;
2use vortex_array::vtable::OperationsVTable;
3use vortex_array::{Array, ArrayRef, IntoArray};
4use vortex_error::VortexResult;
5use vortex_scalar::Scalar;
6
7use crate::{RunEndArray, RunEndVTable};
8
9impl OperationsVTable<RunEndVTable> for RunEndVTable {
10 fn slice(array: &RunEndArray, start: usize, stop: usize) -> VortexResult<ArrayRef> {
11 let new_length = stop - start;
12
13 let (slice_begin, slice_end) = if new_length == 0 {
14 let values_len = array.values().len();
15 (values_len, values_len)
16 } else {
17 let physical_start = array.find_physical_index(start)?;
18 let physical_stop = array.find_physical_index(stop)?;
19
20 (physical_start, physical_stop + 1)
21 };
22
23 if slice_begin + 1 == slice_end {
24 let value = array.values().scalar_at(slice_begin)?;
25 return Ok(ConstantArray::new(value, new_length).into_array());
26 }
27
28 Ok(RunEndArray::with_offset_and_length(
29 array.ends().slice(slice_begin, slice_end)?,
30 array.values().slice(slice_begin, slice_end)?,
31 if new_length == 0 {
32 0
33 } else {
34 start + array.offset()
35 },
36 new_length,
37 )?
38 .into_array())
39 }
40
41 fn scalar_at(array: &RunEndArray, index: usize) -> VortexResult<Scalar> {
42 array.values().scalar_at(array.find_physical_index(index)?)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48
49 use vortex_array::arrays::PrimitiveArray;
50 use vortex_array::{Array, IntoArray, ToCanonical};
51 use vortex_buffer::buffer;
52 use vortex_dtype::{DType, Nullability, PType};
53
54 use crate::RunEndArray;
55
56 #[test]
57 fn slice_array() {
58 let arr = RunEndArray::try_new(
59 buffer![2u32, 5, 10].into_array(),
60 buffer![1i32, 2, 3].into_array(),
61 )
62 .unwrap()
63 .slice(3, 8)
64 .unwrap();
65 assert_eq!(
66 arr.dtype(),
67 &DType::Primitive(PType::I32, Nullability::NonNullable)
68 );
69 assert_eq!(arr.len(), 5);
70
71 assert_eq!(
72 arr.to_primitive().unwrap().as_slice::<i32>(),
73 vec![2, 2, 3, 3, 3]
74 );
75 }
76
77 #[test]
78 fn double_slice() {
79 let arr = RunEndArray::try_new(
80 buffer![2u32, 5, 10].into_array(),
81 buffer![1i32, 2, 3].into_array(),
82 )
83 .unwrap()
84 .slice(3, 8)
85 .unwrap();
86 assert_eq!(arr.len(), 5);
87
88 let doubly_sliced = arr.slice(0, 3).unwrap();
89
90 assert_eq!(
91 doubly_sliced.to_primitive().unwrap().as_slice::<i32>(),
92 vec![2, 2, 3]
93 );
94 }
95
96 #[test]
97 fn slice_end_inclusive() {
98 let arr = RunEndArray::try_new(
99 buffer![2u32, 5, 10].into_array(),
100 buffer![1i32, 2, 3].into_array(),
101 )
102 .unwrap()
103 .slice(4, 10)
104 .unwrap();
105 assert_eq!(
106 arr.dtype(),
107 &DType::Primitive(PType::I32, Nullability::NonNullable)
108 );
109 assert_eq!(arr.len(), 6);
110
111 assert_eq!(
112 arr.to_primitive().unwrap().as_slice::<i32>(),
113 vec![2, 3, 3, 3, 3, 3]
114 );
115 }
116
117 #[test]
118 fn slice_at_end() {
119 let re_array = RunEndArray::try_new(
120 buffer![7_u64, 10].into_array(),
121 buffer![2_u64, 3].into_array(),
122 )
123 .unwrap();
124
125 assert_eq!(re_array.len(), 10);
126
127 let sliced_array = re_array.slice(re_array.len(), re_array.len()).unwrap();
128 assert!(sliced_array.is_empty());
129 }
130
131 #[test]
132 fn slice_single_end() {
133 let re_array = RunEndArray::try_new(
134 buffer![7_u64, 10].into_array(),
135 buffer![2_u64, 3].into_array(),
136 )
137 .unwrap();
138
139 assert_eq!(re_array.len(), 10);
140
141 let sliced_array = re_array.slice(2, 5).unwrap();
142
143 assert!(sliced_array.is_constant())
144 }
145
146 #[test]
147 fn ree_scalar_at_end() {
148 let scalar = RunEndArray::encode(
149 PrimitiveArray::from_iter([1, 1, 1, 4, 4, 4, 2, 2, 5, 5, 5, 5]).into_array(),
150 )
151 .unwrap()
152 .scalar_at(11)
153 .unwrap();
154 assert_eq!(scalar, 5.into());
155 }
156}