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