reifydb_core/value/index/
range.rs1use std::collections::Bound;
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()
87 .take(i)
88 .copied()
89 .chain(std::iter::once(prefix[i] + 1))
90 .collect::<Vec<_>>(),
91 )),
92 None => Bound::Unbounded,
93 };
94 Self {
95 start,
96 end,
97 }
98 }
99
100 pub fn all() -> Self {
102 Self {
103 start: Bound::Unbounded,
104 end: Bound::Unbounded,
105 }
106 }
107
108 pub fn to_encoded_key_range(&self) -> EncodedKeyRange {
112 let start = match &self.start {
113 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
114 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
115 Bound::Unbounded => Bound::Unbounded,
116 };
117
118 let end = match &self.end {
119 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
120 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
121 Bound::Unbounded => Bound::Unbounded,
122 };
123
124 EncodedKeyRange::new(start, end)
125 }
126
127 pub fn from_prefix(key: &EncodedIndexKey) -> Self {
130 Self::prefix(key.as_slice())
131 }
132}
133
134impl From<EncodedIndexKeyRange> for EncodedKeyRange {
135 fn from(range: EncodedIndexKeyRange) -> Self {
136 range.to_encoded_key_range()
137 }
138}
139
140#[cfg(test)]
141pub mod tests {
142 use reifydb_type::value::r#type::Type;
143
144 use super::*;
145 use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
146
147 #[test]
148 fn test_start_end() {
149 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
150
151 let mut key1 = layout.allocate_key();
152 layout.set_u64(&mut key1, 0, 100u64);
153
154 let mut key2 = layout.allocate_key();
155 layout.set_u64(&mut key2, 0, 200u64);
156
157 let range = EncodedIndexKeyRange::start_end(Some(key1.clone()), Some(key2.clone()));
158
159 match &range.start {
160 Bound::Included(k) => {
161 assert_eq!(k.as_slice(), key1.as_slice())
162 }
163 _ => panic!("Expected Included start bound"),
164 }
165
166 match &range.end {
167 Bound::Excluded(k) => {
168 assert_eq!(k.as_slice(), key2.as_slice())
169 }
170 _ => panic!("Expected Excluded end bound"),
171 }
172 }
173
174 #[test]
175 fn test_start_end_inclusive() {
176 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
177
178 let mut key1 = layout.allocate_key();
179 layout.set_u64(&mut key1, 0, 100u64);
180
181 let mut key2 = layout.allocate_key();
182 layout.set_u64(&mut key2, 0, 200u64);
183
184 let range = EncodedIndexKeyRange::start_end_inclusive(Some(key1.clone()), Some(key2.clone()));
185
186 match &range.start {
187 Bound::Included(k) => {
188 assert_eq!(k.as_slice(), key1.as_slice())
189 }
190 _ => panic!("Expected Included start bound"),
191 }
192
193 match &range.end {
194 Bound::Included(k) => {
195 assert_eq!(k.as_slice(), key2.as_slice())
196 }
197 _ => panic!("Expected Included end bound"),
198 }
199 }
200
201 #[test]
202 fn test_unbounded() {
203 let range = EncodedIndexKeyRange::start_end(None, None);
204 assert!(matches!(range.start, Bound::Unbounded));
205 assert!(matches!(range.end, Bound::Unbounded));
206 }
207
208 #[test]
209 fn test_prefix() {
210 let prefix = &[0x12, 0x34];
211 let range = EncodedIndexKeyRange::prefix(prefix);
212
213 match &range.start {
214 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
215 _ => panic!("Expected Included start bound"),
216 }
217
218 match &range.end {
219 Bound::Excluded(k) => {
220 assert_eq!(k.as_slice(), &[0x12, 0x35])
221 }
222 _ => panic!("Expected Excluded end bound"),
223 }
224 }
225
226 #[test]
227 fn test_prefix_with_ff() {
228 let prefix = &[0x12, 0xff];
229 let range = EncodedIndexKeyRange::prefix(prefix);
230
231 match &range.start {
232 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
233 _ => panic!("Expected Included start bound"),
234 }
235
236 match &range.end {
237 Bound::Excluded(k) => assert_eq!(k.as_slice(), &[0x13]),
238 _ => panic!("Expected Excluded end bound"),
239 }
240 }
241
242 #[test]
243 fn test_prefix_all_ff() {
244 let prefix = &[0xff, 0xff];
245 let range = EncodedIndexKeyRange::prefix(prefix);
246
247 match &range.start {
248 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
249 _ => panic!("Expected Included start bound"),
250 }
251
252 assert!(matches!(range.end, Bound::Unbounded));
253 }
254
255 #[test]
256 fn test_to_encoded_key_range() {
257 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
258
259 let mut key = layout.allocate_key();
260 layout.set_u64(&mut key, 0, 100u64);
261
262 let index_range = EncodedIndexKeyRange::start_end(Some(key.clone()), None);
263 let key_range = index_range.to_encoded_key_range();
264
265 match &key_range.start {
266 Bound::Included(k) => {
267 assert_eq!(k.as_slice(), key.as_slice())
268 }
269 _ => panic!("Expected Included start bound"),
270 }
271
272 assert!(matches!(key_range.end, Bound::Unbounded));
273 }
274
275 #[test]
276 fn test_all() {
277 let range = EncodedIndexKeyRange::all();
278 assert!(matches!(range.start, Bound::Unbounded));
279 assert!(matches!(range.end, Bound::Unbounded));
280 }
281}