rocksdb/iter_range.rs
1/// A range which can be set as iterate bounds on [`crate::ReadOptions`].
2///
3/// See [`crate::ReadOptions::set_iterate_range`] for documentation and
4/// examples.
5pub trait IterateBounds {
6 /// Converts object into lower and upper bounds pair.
7 ///
8 /// If this object represents range with one of the bounds unset,
9 /// corresponding element is returned as `None`. For example, `..upper`
10 /// range would be converted into `(None, Some(upper))` pair.
11 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>);
12}
13
14impl IterateBounds for std::ops::RangeFull {
15 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>) {
16 (None, None)
17 }
18}
19
20impl<K: Into<Vec<u8>>> IterateBounds for std::ops::Range<K> {
21 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>) {
22 (Some(self.start.into()), Some(self.end.into()))
23 }
24}
25
26impl<K: Into<Vec<u8>>> IterateBounds for std::ops::RangeFrom<K> {
27 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>) {
28 (Some(self.start.into()), None)
29 }
30}
31
32impl<K: Into<Vec<u8>>> IterateBounds for std::ops::RangeTo<K> {
33 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>) {
34 (None, Some(self.end.into()))
35 }
36}
37
38/// Representation of a range of keys starting with given prefix.
39///
40/// Can be used as argument of [`crate::ReadOptions::set_iterate_range`] method
41/// to set iterate bounds.
42#[derive(Clone, Copy)]
43pub struct PrefixRange<K>(pub K);
44
45impl<K: Into<Vec<u8>>> IterateBounds for PrefixRange<K> {
46 /// Converts the prefix range representation into pair of bounds.
47 ///
48 /// The conversion assumes lexicographical sorting on `u8` values. For
49 /// example, `PrefixRange("a")` is equivalent to `"a".."b"` range. Note
50 /// that for some prefixes, either of the bounds may be `None`. For
51 /// example, an empty prefix is equivalent to a full range (i.e. both bounds
52 /// being `None`).
53 fn into_bounds(self) -> (Option<Vec<u8>>, Option<Vec<u8>>) {
54 let start = self.0.into();
55 if start.is_empty() {
56 (None, None)
57 } else {
58 let end = next_prefix(&start);
59 (Some(start), end)
60 }
61 }
62}
63
64/// Returns lowest value following largest value with given prefix.
65///
66/// In other words, computes upper bound for a prefix scan over list of keys
67/// sorted in lexicographical order. This means that a prefix scan can be
68/// expressed as range scan over a right-open `[prefix, next_prefix(prefix))`
69/// range.
70///
71/// For example, for prefix `foo` the function returns `fop`.
72///
73/// Returns `None` if there is no value which can follow value with given
74/// prefix. This happens when prefix consists entirely of `'\xff'` bytes (or is
75/// empty).
76fn next_prefix(prefix: &[u8]) -> Option<Vec<u8>> {
77 let ffs = prefix
78 .iter()
79 .rev()
80 .take_while(|&&byte| byte == u8::MAX)
81 .count();
82 let next = &prefix[..(prefix.len() - ffs)];
83 if next.is_empty() {
84 // Prefix consisted of \xff bytes. There is no prefix that
85 // follows it.
86 None
87 } else {
88 let mut next = next.to_vec();
89 *next.last_mut().unwrap() += 1;
90 Some(next)
91 }
92}
93
94#[test]
95fn test_prefix_range() {
96 fn test(start: &[u8], end: Option<&[u8]>) {
97 let got = PrefixRange(start).into_bounds();
98 assert_eq!((Some(start), end), (got.0.as_deref(), got.1.as_deref()));
99 }
100
101 let empty: &[u8] = &[];
102 assert_eq!((None, None), PrefixRange(empty).into_bounds());
103 test(b"\xff", None);
104 test(b"\xff\xff\xff\xff", None);
105 test(b"a", Some(b"b"));
106 test(b"a\xff\xff\xff", Some(b"b"));
107}