1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Options for one read.
/// How one read or iterator behaves.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct ReadOptions {
/// Verify the checksum of every block read from a table (default `true`).
///
/// Turning it off trades corruption detection for a little CPU; a corrupt block then decodes
/// to an error or to wrong data instead of a [`crate::ErrorCategory::Corruption`] error.
pub verify_checksums: bool,
/// Keep the blocks this read loads in the block cache (default `true`).
///
/// A one-off scan sets it to `false` so it does not evict the working set.
pub fill_cache: bool,
/// The least key an iterator shows (inclusive); `None` for no bound. Ignored by point reads
/// and scans, which take their range as arguments.
pub lower_bound: Option<Vec<u8>>,
/// The key an iterator stops before (exclusive); `None` for no bound. Ignored by point
/// reads and scans.
pub upper_bound: Option<Vec<u8>>,
}
impl Default for ReadOptions {
fn default() -> Self {
Self {
verify_checksums: true,
fill_cache: true,
lower_bound: None,
upper_bound: None,
}
}
}
impl ReadOptions {
/// Bounds an iterator to the keys that start with `prefix`.
///
/// ```
/// use tessarikv::ReadOptions;
///
/// let options = ReadOptions::default().with_prefix(b"user/");
/// assert_eq!(options.lower_bound.as_deref(), Some(&b"user/"[..]));
/// assert_eq!(options.upper_bound.as_deref(), Some(&b"user0"[..]));
/// ```
#[must_use]
pub fn with_prefix(mut self, prefix: &[u8]) -> Self {
self.lower_bound = Some(prefix.to_vec());
self.upper_bound = prefix_end(prefix);
self
}
}
/// The least key greater than every key that starts with `prefix`: the prefix with its last
/// byte below `0xff` incremented and the rest dropped. `None` when no such key exists (the
/// prefix is empty or all `0xff`), so the range has no upper end.
fn prefix_end(prefix: &[u8]) -> Option<Vec<u8>> {
let last = prefix.iter().rposition(|&byte| byte != u8::MAX)?;
let mut end = prefix.get(..=last)?.to_vec();
let byte = end.last_mut()?;
*byte = byte.checked_add(1)?;
Some(end)
}
#[cfg(test)]
mod tests {
use super::prefix_end;
#[test]
fn a_prefix_ends_at_its_least_successor() {
assert_eq!(prefix_end(b"ab"), Some(b"ac".to_vec()));
assert_eq!(prefix_end(b"a\xff\xff"), Some(b"b".to_vec()));
assert_eq!(prefix_end(b"\xff\xff"), None);
assert_eq!(prefix_end(b""), None);
}
}