reifydb_core/value/encoded/
key.rs1use std::{
5 collections::{
6 Bound,
7 Bound::{Excluded, Included, Unbounded},
8 },
9 ops::{Deref, RangeBounds},
10};
11
12use serde::{Deserialize, Serialize};
13
14use crate::util::{CowVec, encoding::binary::decode_binary};
15
16#[derive(Debug, Clone, PartialOrd, Ord, Hash, PartialEq, Eq, Serialize, Deserialize)]
17pub struct EncodedKey(pub CowVec<u8>);
18
19impl Deref for EncodedKey {
20 type Target = CowVec<u8>;
21
22 fn deref(&self) -> &Self::Target {
23 &self.0
24 }
25}
26
27impl EncodedKey {
28 pub fn new(key: impl Into<Vec<u8>>) -> Self {
29 Self(CowVec::new(key.into()))
30 }
31
32 pub fn as_bytes(&self) -> &[u8] {
33 self.0.as_ref()
34 }
35
36 pub fn as_slice(&self) -> &[u8] {
37 self.0.as_ref()
38 }
39}
40
41#[derive(Clone, Debug)]
42pub struct EncodedKeyRange {
43 pub start: Bound<EncodedKey>,
44 pub end: Bound<EncodedKey>,
45}
46
47impl EncodedKeyRange {
48 pub fn new(start: Bound<EncodedKey>, end: Bound<EncodedKey>) -> Self {
49 Self {
50 start,
51 end,
52 }
53 }
54
55 pub fn prefix(prefix: &[u8]) -> Self {
63 let start = Bound::Included(EncodedKey::new(prefix));
64 let end = match prefix.iter().rposition(|&b| b != 0xff) {
65 Some(i) => Bound::Excluded(EncodedKey::new(
66 prefix.iter()
67 .take(i)
68 .copied()
69 .chain(std::iter::once(prefix[i] + 1))
70 .collect::<Vec<_>>(),
71 )),
72 None => Bound::Unbounded,
73 };
74 Self {
75 start,
76 end,
77 }
78 }
79
80 pub fn with_prefix(&self, prefix: EncodedKey) -> Self {
81 let start = match self.start_bound() {
82 Included(key) => {
83 let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
84 prefixed.extend_from_slice(prefix.as_ref());
85 prefixed.extend_from_slice(key.as_ref());
86 Included(EncodedKey::new(prefixed))
87 }
88 Excluded(key) => {
89 let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
90 prefixed.extend_from_slice(prefix.as_ref());
91 prefixed.extend_from_slice(key.as_ref());
92 Excluded(EncodedKey::new(prefixed))
93 }
94 Unbounded => Included(prefix.clone()),
95 };
96
97 let end = match self.end_bound() {
98 Included(key) => {
99 let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
100 prefixed.extend_from_slice(prefix.as_ref());
101 prefixed.extend_from_slice(key.as_ref());
102 Included(EncodedKey::new(prefixed))
103 }
104 Excluded(key) => {
105 let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
106 prefixed.extend_from_slice(prefix.as_ref());
107 prefixed.extend_from_slice(key.as_ref());
108 Excluded(EncodedKey::new(prefixed))
109 }
110 Unbounded => match prefix.as_ref().iter().rposition(|&b| b != 0xff) {
111 Some(i) => {
112 let mut next_prefix = prefix.as_ref()[..=i].to_vec();
113 next_prefix[i] += 1;
114 Excluded(EncodedKey::new(next_prefix))
115 }
116 None => Unbounded,
117 },
118 };
119
120 EncodedKeyRange::new(start, end)
121 }
122
123 pub fn start_end(start: Option<EncodedKey>, end: Option<EncodedKey>) -> Self {
137 let start = match start {
138 Some(s) => Bound::Included(s),
139 None => Bound::Unbounded,
140 };
141
142 let end = match end {
143 Some(e) => Bound::Included(e),
144 None => Bound::Unbounded,
145 };
146
147 Self {
148 start,
149 end,
150 }
151 }
152
153 pub fn all() -> Self {
160 Self {
161 start: Bound::Unbounded,
162 end: Bound::Unbounded,
163 }
164 }
165
166 pub fn parse(str: &str) -> Self {
183 let (mut start, mut end) = (Bound::<EncodedKey>::Unbounded, Bound::<EncodedKey>::Unbounded);
184
185 if let Some(dot_pos) = str.find("..") {
187 let start_part = &str[..dot_pos];
188 let end_part = &str[dot_pos + 2..];
189
190 if !start_part.is_empty() {
192 start = Bound::Included(EncodedKey(decode_binary(start_part)));
193 }
194
195 if let Some(end_str) = end_part.strip_prefix('=') {
197 if !end_str.is_empty() {
199 end = Bound::Included(EncodedKey(decode_binary(end_str)));
200 }
201 } else {
202 if !end_part.is_empty() {
204 end = Bound::Excluded(EncodedKey(decode_binary(end_part)));
205 }
206 }
207
208 Self {
209 start,
210 end,
211 }
212 } else {
213 Self {
215 start: Bound::Included(EncodedKey::new([0xff])),
216 end: Bound::Excluded(EncodedKey::new([0xff])),
217 }
218 }
219 }
220}
221
222impl RangeBounds<EncodedKey> for EncodedKeyRange {
223 fn start_bound(&self) -> Bound<&EncodedKey> {
224 self.start.as_ref()
225 }
226
227 fn end_bound(&self) -> Bound<&EncodedKey> {
228 self.end.as_ref()
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use std::collections::Bound;
235
236 use super::EncodedKey;
237
238 macro_rules! as_key {
239 ($key:expr) => {{ EncodedKey::new(keycode::serialize(&$key)) }};
240 }
241
242 mod prefix {
243 use std::ops::Bound;
244
245 use crate::value::encoded::key::{
246 EncodedKeyRange,
247 tests::{excluded, included},
248 };
249
250 #[test]
251 fn test_simple() {
252 let range = EncodedKeyRange::prefix(&[0x12, 0x34]);
253 assert_eq!(range.start, included(&[0x12, 0x34]));
254 assert_eq!(range.end, excluded(&[0x12, 0x35]));
255 }
256
257 #[test]
258 fn test_with_trailing_ff() {
259 let range = EncodedKeyRange::prefix(&[0x12, 0xff]);
260 assert_eq!(range.start, included(&[0x12, 0xff]));
261 assert_eq!(range.end, excluded(&[0x13]));
262 }
263
264 #[test]
265 fn test_with_multiple_trailing_ff() {
266 let range = EncodedKeyRange::prefix(&[0x12, 0xff, 0xff]);
267 assert_eq!(range.start, included(&[0x12, 0xff, 0xff]));
268 assert_eq!(range.end, excluded(&[0x13]));
269 }
270
271 #[test]
272 fn test_all_ff() {
273 let range = EncodedKeyRange::prefix(&[0xff, 0xff]);
274 assert_eq!(range.start, included(&[0xff, 0xff]));
275 assert_eq!(range.end, Bound::Unbounded);
276 }
277
278 #[test]
279 fn test_empty() {
280 let range = EncodedKeyRange::prefix(&[]);
281 assert_eq!(range.start, included(&[]));
282 assert_eq!(range.end, Bound::Unbounded);
283 }
284
285 #[test]
286 fn test_mid_increment() {
287 let range = EncodedKeyRange::prefix(&[0x12, 0x00, 0xff]);
288 assert_eq!(range.start, included(&[0x12, 0x00, 0xff]));
289 assert_eq!(range.end, excluded(&[0x12, 0x01]));
290 }
291 }
292
293 mod start_end {
294 use std::ops::Bound;
295
296 use crate::{
297 EncodedKey,
298 util::encoding::keycode,
299 value::encoded::key::{EncodedKeyRange, tests::included},
300 };
301
302 #[test]
303 fn test_start_and_end() {
304 let range = EncodedKeyRange::start_end(Some(as_key!(1)), Some(as_key!(2)));
305 assert_eq!(range.start, included(&as_key!(1)));
306 assert_eq!(range.end, included(&as_key!(2)));
307 }
308
309 #[test]
310 fn test_start_only() {
311 let range = EncodedKeyRange::start_end(Some(as_key!(1)), None);
312 assert_eq!(range.start, included(&as_key!(1)));
313 assert_eq!(range.end, Bound::Unbounded);
314 }
315
316 #[test]
317 fn test_end_only() {
318 let range = EncodedKeyRange::start_end(None, Some(as_key!(2)));
319 assert_eq!(range.start, Bound::Unbounded);
320 assert_eq!(range.end, included(&as_key!(2)));
321 }
322
323 #[test]
324 fn test_unbounded_range() {
325 let range = EncodedKeyRange::start_end(None, None);
326 assert_eq!(range.start, Bound::Unbounded);
327 assert_eq!(range.end, Bound::Unbounded);
328 }
329
330 #[test]
331 fn test_full_byte_range() {
332 let range = EncodedKeyRange::start_end(Some(as_key!(0x00)), Some(as_key!(0xff)));
333 assert_eq!(range.start, included(&as_key!(0x00)));
334 assert_eq!(range.end, included(&as_key!(0xff)));
335 }
336
337 #[test]
338 fn test_identical_bounds() {
339 let range = EncodedKeyRange::start_end(Some(as_key!(0x42)), Some(as_key!(0x42)));
340 assert_eq!(range.start, included(&as_key!(0x42)));
341 assert_eq!(range.end, included(&as_key!(0x42)));
342 }
343 }
344
345 mod all {
346 use std::ops::Bound;
347
348 use crate::value::encoded::key::EncodedKeyRange;
349
350 #[test]
351 fn test_is_unbounded() {
352 let range = EncodedKeyRange::all();
353 assert_eq!(range.start, Bound::Unbounded);
354 assert_eq!(range.end, Bound::Unbounded);
355 }
356 }
357
358 mod parse {
359 use std::ops::Bound;
360
361 use crate::value::encoded::key::{
362 EncodedKey, EncodedKeyRange,
363 tests::{excluded, included},
364 };
365
366 #[test]
367 fn test_full_range() {
368 let r = EncodedKeyRange::parse("a..z");
369 assert_eq!(r.start, included(b"a"));
370 assert_eq!(r.end, excluded(b"z"));
371 }
372
373 #[test]
374 fn test_inclusive_end() {
375 let r = EncodedKeyRange::parse("a..=z");
376 assert_eq!(r.start, included(b"a"));
377 assert_eq!(r.end, included(b"z"));
378 }
379
380 #[test]
381 fn test_unbounded_start() {
382 let r = EncodedKeyRange::parse("..z");
383 assert_eq!(r.start, Bound::Unbounded);
384 assert_eq!(r.end, excluded(b"z"));
385 }
386
387 #[test]
388 fn test_unbounded_end() {
389 let r = EncodedKeyRange::parse("a..");
390 assert_eq!(r.start, included(b"a"));
391 assert_eq!(r.end, Bound::Unbounded);
392 }
393
394 #[test]
395 fn test_inclusive_only() {
396 let r = EncodedKeyRange::parse("..=z");
397 assert_eq!(r.start, Bound::Unbounded);
398 assert_eq!(r.end, included(b"z"));
399 }
400
401 #[test]
402 fn test_invalid_string_returns_degenerate_range() {
403 let r = EncodedKeyRange::parse("not a range");
404 let expected = EncodedKey::new([0xff]);
405 assert_eq!(r.start, Bound::Included(expected.clone()));
406 assert_eq!(r.end, Bound::Excluded(expected));
407 }
408
409 #[test]
410 fn test_empty_string_returns_degenerate_range() {
411 let r = EncodedKeyRange::parse("");
412 let expected = EncodedKey::new([0xff]);
413 assert_eq!(r.start, Bound::Included(expected.clone()));
414 assert_eq!(r.end, Bound::Excluded(expected));
415 }
416
417 #[test]
418 fn test_binary_encoded_values() {
419 let r = EncodedKeyRange::parse("0101..=0aff");
420 assert_eq!(r.start, included(b"0101"));
422 assert_eq!(r.end, included(b"0aff"));
424 }
425 }
426
427 fn included(key: &[u8]) -> Bound<EncodedKey> {
428 Bound::Included(EncodedKey::new(key))
429 }
430
431 fn excluded(key: &[u8]) -> Bound<EncodedKey> {
432 Bound::Excluded(EncodedKey::new(key))
433 }
434}