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 {
26 let start = match start {
27 Some(s) => Bound::Included(s),
28 None => Bound::Unbounded,
29 };
30
31 let end = match end {
32 Some(e) => Bound::Excluded(e),
33 None => Bound::Unbounded,
34 };
35
36 Self {
37 start,
38 end,
39 }
40 }
41
42 pub fn start_end_inclusive(start: Option<EncodedIndexKey>, end: Option<EncodedIndexKey>) -> Self {
43 let start = match start {
44 Some(s) => Bound::Included(s),
45 None => Bound::Unbounded,
46 };
47
48 let end = match end {
49 Some(e) => Bound::Included(e),
50 None => Bound::Unbounded,
51 };
52
53 Self {
54 start,
55 end,
56 }
57 }
58
59 pub fn prefix(prefix: &[u8]) -> Self {
60 let start = Bound::Included(EncodedIndexKey::from_bytes(prefix));
61 let end = match prefix.iter().rposition(|&b| b != 0xff) {
62 Some(i) => Bound::Excluded(EncodedIndexKey::from_bytes(
63 &prefix.iter().take(i).copied().chain(iter::once(prefix[i] + 1)).collect::<Vec<_>>(),
64 )),
65 None => Bound::Unbounded,
66 };
67 Self {
68 start,
69 end,
70 }
71 }
72
73 pub fn all() -> Self {
74 Self {
75 start: Bound::Unbounded,
76 end: Bound::Unbounded,
77 }
78 }
79
80 pub fn to_encoded_key_range(&self) -> EncodedKeyRange {
81 let start = match &self.start {
82 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
83 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
84 Bound::Unbounded => Bound::Unbounded,
85 };
86
87 let end = match &self.end {
88 Bound::Included(key) => Bound::Included(EncodedKey::new(key.as_slice())),
89 Bound::Excluded(key) => Bound::Excluded(EncodedKey::new(key.as_slice())),
90 Bound::Unbounded => Bound::Unbounded,
91 };
92
93 EncodedKeyRange::new(start, end)
94 }
95
96 pub fn from_prefix(key: &EncodedIndexKey) -> Self {
97 Self::prefix(key.as_slice())
98 }
99}
100
101impl From<EncodedIndexKeyRange> for EncodedKeyRange {
102 fn from(range: EncodedIndexKeyRange) -> Self {
103 range.to_encoded_key_range()
104 }
105}
106
107#[cfg(test)]
108pub mod tests {
109 use reifydb_type::value::r#type::Type;
110
111 use super::*;
112 use crate::{sort::SortDirection, value::index::shape::IndexShape};
113
114 #[test]
115 fn test_start_end() {
116 let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
117
118 let mut key1 = layout.allocate_key();
119 layout.set_u64(&mut key1, 0, 100u64);
120
121 let mut key2 = layout.allocate_key();
122 layout.set_u64(&mut key2, 0, 200u64);
123
124 let range = EncodedIndexKeyRange::start_end(Some(key1.clone()), Some(key2.clone()));
125
126 match &range.start {
127 Bound::Included(k) => {
128 assert_eq!(k.as_slice(), key1.as_slice())
129 }
130 _ => panic!("Expected Included start bound"),
131 }
132
133 match &range.end {
134 Bound::Excluded(k) => {
135 assert_eq!(k.as_slice(), key2.as_slice())
136 }
137 _ => panic!("Expected Excluded end bound"),
138 }
139 }
140
141 #[test]
142 fn test_start_end_inclusive() {
143 let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
144
145 let mut key1 = layout.allocate_key();
146 layout.set_u64(&mut key1, 0, 100u64);
147
148 let mut key2 = layout.allocate_key();
149 layout.set_u64(&mut key2, 0, 200u64);
150
151 let range = EncodedIndexKeyRange::start_end_inclusive(Some(key1.clone()), Some(key2.clone()));
152
153 match &range.start {
154 Bound::Included(k) => {
155 assert_eq!(k.as_slice(), key1.as_slice())
156 }
157 _ => panic!("Expected Included start bound"),
158 }
159
160 match &range.end {
161 Bound::Included(k) => {
162 assert_eq!(k.as_slice(), key2.as_slice())
163 }
164 _ => panic!("Expected Included end bound"),
165 }
166 }
167
168 #[test]
169 fn test_unbounded() {
170 let range = EncodedIndexKeyRange::start_end(None, None);
171 assert!(matches!(range.start, Bound::Unbounded));
172 assert!(matches!(range.end, Bound::Unbounded));
173 }
174
175 #[test]
176 fn test_prefix() {
177 let prefix = &[0x12, 0x34];
178 let range = EncodedIndexKeyRange::prefix(prefix);
179
180 match &range.start {
181 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
182 _ => panic!("Expected Included start bound"),
183 }
184
185 match &range.end {
186 Bound::Excluded(k) => {
187 assert_eq!(k.as_slice(), &[0x12, 0x35])
188 }
189 _ => panic!("Expected Excluded end bound"),
190 }
191 }
192
193 #[test]
194 fn test_prefix_with_ff() {
195 let prefix = &[0x12, 0xff];
196 let range = EncodedIndexKeyRange::prefix(prefix);
197
198 match &range.start {
199 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
200 _ => panic!("Expected Included start bound"),
201 }
202
203 match &range.end {
204 Bound::Excluded(k) => assert_eq!(k.as_slice(), &[0x13]),
205 _ => panic!("Expected Excluded end bound"),
206 }
207 }
208
209 #[test]
210 fn test_prefix_all_ff() {
211 let prefix = &[0xff, 0xff];
212 let range = EncodedIndexKeyRange::prefix(prefix);
213
214 match &range.start {
215 Bound::Included(k) => assert_eq!(k.as_slice(), prefix),
216 _ => panic!("Expected Included start bound"),
217 }
218
219 assert!(matches!(range.end, Bound::Unbounded));
220 }
221
222 #[test]
223 fn test_to_encoded_key_range() {
224 let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
225
226 let mut key = layout.allocate_key();
227 layout.set_u64(&mut key, 0, 100u64);
228
229 let index_range = EncodedIndexKeyRange::start_end(Some(key.clone()), None);
230 let key_range = index_range.to_encoded_key_range();
231
232 match &key_range.start {
233 Bound::Included(k) => {
234 assert_eq!(k.as_slice(), key.as_slice())
235 }
236 _ => panic!("Expected Included start bound"),
237 }
238
239 assert!(matches!(key_range.end, Bound::Unbounded));
240 }
241
242 #[test]
243 fn test_all() {
244 let range = EncodedIndexKeyRange::all();
245 assert!(matches!(range.start, Bound::Unbounded));
246 assert!(matches!(range.end, Bound::Unbounded));
247 }
248}