reifydb_core/value/index/
range.rs1use std::{collections::Bound, iter};
5
6use crate::{
7 encoded::key::{EncodedKey, EncodedKeyRange},
8 value::index::encoded::EncodedIndexKey,
9};
10
11#[derive(Clone, Debug)]
12pub struct EncodedIndexKeyRange {
13 pub start: Bound<EncodedIndexKey>,
14 pub end: Bound<EncodedIndexKey>,
15}
16
17impl EncodedIndexKeyRange {
18 pub fn new(start: Bound<EncodedIndexKey>, end: Bound<EncodedIndexKey>) -> Self {
19 Self {
20 start,
21 end,
22 }
23 }
24
25 pub fn start_end(start: Option<EncodedIndexKey>, end: Option<EncodedIndexKey>) -> Self {
33 let start = match start {
34 Some(s) => Bound::Included(s),
35 None => Bound::Unbounded,
36 };
37
38 let end = match end {
39 Some(e) => Bound::Excluded(e),
40 None => Bound::Unbounded,
41 };
42
43 Self {
44 start,
45 end,
46 }
47 }
48
49 pub fn start_end_inclusive(start: Option<EncodedIndexKey>, end: Option<EncodedIndexKey>) -> Self {
58 let start = match start {
59 Some(s) => Bound::Included(s),
60 None => Bound::Unbounded,
61 };
62
63 let end = match end {
64 Some(e) => Bound::Included(e),
65 None => Bound::Unbounded,
66 };
67
68 Self {
69 start,
70 end,
71 }
72 }
73
74 pub fn prefix(prefix: &[u8]) -> Self {
83 let start = Bound::Included(EncodedIndexKey::from_bytes(prefix));
84 let end = match prefix.iter().rposition(|&b| b != 0xff) {
85 Some(i) => Bound::Excluded(EncodedIndexKey::from_bytes(
86 &prefix.iter().take(i).copied().chain(iter::once(prefix[i] + 1)).collect::<Vec<_>>(),
87 )),
88 None => Bound::Unbounded,
89 };
90 Self {
91 start,
92 end,
93 }
94 }
95
96 pub fn all() -> Self {
98 Self {
99 start: Bound::Unbounded,
100 end: Bound::Unbounded,
101 }
102 }
103
104 pub fn to_encoded_key_range(&self) -> EncodedKeyRange {
108 let start = match &self.start {
109 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
110 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
111 Bound::Unbounded => Bound::Unbounded,
112 };
113
114 let end = match &self.end {
115 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
116 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
117 Bound::Unbounded => Bound::Unbounded,
118 };
119
120 EncodedKeyRange::new(start, end)
121 }
122
123 pub fn from_prefix(key: &EncodedIndexKey) -> Self {
126 Self::prefix(key.as_slice())
127 }
128}
129
130impl From<EncodedIndexKeyRange> for EncodedKeyRange {
131 fn from(range: EncodedIndexKeyRange) -> Self {
132 range.to_encoded_key_range()
133 }
134}
135
136#[cfg(test)]
137pub mod tests {
138 use reifydb_type::value::r#type::Type;
139
140 use super::*;
141 use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
142
143 #[test]
144 fn test_start_end() {
145 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
146
147 let mut key1 = layout.allocate_key();
148 layout.set_u64(&mut key1, 0, 100u64);
149
150 let mut key2 = layout.allocate_key();
151 layout.set_u64(&mut key2, 0, 200u64);
152
153 let range = EncodedIndexKeyRange::start_end(Some(key1.clone()), Some(key2.clone()));
154
155 match &range.start {
156 Bound::Included(k) => {
157 assert_eq!(k.as_slice(), key1.as_slice())
158 }
159 _ => panic!("Expected Included start bound"),
160 }
161
162 match &range.end {
163 Bound::Excluded(k) => {
164 assert_eq!(k.as_slice(), key2.as_slice())
165 }
166 _ => panic!("Expected Excluded end bound"),
167 }
168 }
169
170 #[test]
171 fn test_start_end_inclusive() {
172 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
173
174 let mut key1 = layout.allocate_key();
175 layout.set_u64(&mut key1, 0, 100u64);
176
177 let mut key2 = layout.allocate_key();
178 layout.set_u64(&mut key2, 0, 200u64);
179
180 let range = EncodedIndexKeyRange::start_end_inclusive(Some(key1.clone()), Some(key2.clone()));
181
182 match &range.start {
183 Bound::Included(k) => {
184 assert_eq!(k.as_slice(), key1.as_slice())
185 }
186 _ => panic!("Expected Included start bound"),
187 }
188
189 match &range.end {
190 Bound::Included(k) => {
191 assert_eq!(k.as_slice(), key2.as_slice())
192 }
193 _ => panic!("Expected Included end bound"),
194 }
195 }
196
197 #[test]
198 fn test_unbounded() {
199 let range = EncodedIndexKeyRange::start_end(None, None);
200 assert!(matches!(range.start, Bound::Unbounded));
201 assert!(matches!(range.end, Bound::Unbounded));
202 }
203
204 #[test]
205 fn test_prefix() {
206 let prefix = &[0x12, 0x34];
207 let range = EncodedIndexKeyRange::prefix(prefix);
208
209 match &range.start {
210 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
211 _ => panic!("Expected Included start bound"),
212 }
213
214 match &range.end {
215 Bound::Excluded(k) => {
216 assert_eq!(k.as_slice(), &[0x12, 0x35])
217 }
218 _ => panic!("Expected Excluded end bound"),
219 }
220 }
221
222 #[test]
223 fn test_prefix_with_ff() {
224 let prefix = &[0x12, 0xff];
225 let range = EncodedIndexKeyRange::prefix(prefix);
226
227 match &range.start {
228 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
229 _ => panic!("Expected Included start bound"),
230 }
231
232 match &range.end {
233 Bound::Excluded(k) => assert_eq!(k.as_slice(), &[0x13]),
234 _ => panic!("Expected Excluded end bound"),
235 }
236 }
237
238 #[test]
239 fn test_prefix_all_ff() {
240 let prefix = &[0xff, 0xff];
241 let range = EncodedIndexKeyRange::prefix(prefix);
242
243 match &range.start {
244 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
245 _ => panic!("Expected Included start bound"),
246 }
247
248 assert!(matches!(range.end, Bound::Unbounded));
249 }
250
251 #[test]
252 fn test_to_encoded_key_range() {
253 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
254
255 let mut key = layout.allocate_key();
256 layout.set_u64(&mut key, 0, 100u64);
257
258 let index_range = EncodedIndexKeyRange::start_end(Some(key.clone()), None);
259 let key_range = index_range.to_encoded_key_range();
260
261 match &key_range.start {
262 Bound::Included(k) => {
263 assert_eq!(k.as_slice(), key.as_slice())
264 }
265 _ => panic!("Expected Included start bound"),
266 }
267
268 assert!(matches!(key_range.end, Bound::Unbounded));
269 }
270
271 #[test]
272 fn test_all() {
273 let range = EncodedIndexKeyRange::all();
274 assert!(matches!(range.start, Bound::Unbounded));
275 assert!(matches!(range.end, Bound::Unbounded));
276 }
277}