foundationdb/
keyselector.rs

1// Copyright 2018 foundationdb-rs developers, https://github.com/Clikengo/foundationdb-rs/graphs/contributors
2// Copyright 2013-2018 Apple, Inc and the FoundationDB project authors.
3//
4// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
5// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
6// http://opensource.org/licenses/MIT>, at your option. This file may not be
7// copied, modified, or distributed except according to those terms.
8
9//! A `KeySelector` identifies a particular key in the database.
10
11use crate::tuple::Bytes;
12use std::borrow::Cow;
13
14/// A `KeySelector` identifies a particular key in the database.
15///
16/// FoundationDB's lexicographically ordered data model permits finding keys based on their order
17/// (for example, finding the first key in the database greater than a given key). Key selectors
18/// represent a description of a key in the database that could be resolved to an actual key by
19/// `Transaction::get_key` or used directly as the beginning or end of a range in
20/// `Transaction::getRange`.
21///
22/// Note that the way the key selectors are resolved is somewhat non-intuitive, so users who wish
23/// to use a key selector other than the default ones described below should probably consult that
24/// documentation before proceeding.
25///
26/// Generally one of the following static methods should be used to construct a KeySelector:
27///
28/// - `last_less_than`
29/// - `last_less_or_equal`
30/// - `first_greater_than`
31/// - `first_greater_or_equal`
32///
33/// A dedicated [example](https://github.com/foundationdb-rs/foundationdb-rs/blob/main/foundationdb/examples/key_selectors.rs) is available on Github.
34#[derive(Clone, Debug)]
35pub struct KeySelector<'a> {
36    key: Bytes<'a>,
37    or_equal: bool,
38    offset: i32,
39}
40
41impl<'a> KeySelector<'a> {
42    /// Constructs a new KeySelector from the given parameters.
43    pub const fn new(key: Cow<'a, [u8]>, or_equal: bool, offset: i32) -> Self {
44        Self {
45            key: Bytes(key),
46            or_equal,
47            offset,
48        }
49    }
50
51    /// Returns a the key that serves as the anchor for this `KeySelector`
52    pub fn key(&self) -> &[u8] {
53        self.key.as_ref()
54    }
55
56    /// True if this is an `or_equal` `KeySelector`
57    pub fn or_equal(&self) -> bool {
58        self.or_equal
59    }
60
61    /// Returns the key offset parameter for this `KeySelector`
62    pub fn offset(&self) -> i32 {
63        self.offset
64    }
65
66    /// Creates a `KeySelector` that picks the last key less than the parameter
67    pub fn last_less_than<K: Into<Cow<'a, [u8]>>>(key: K) -> Self {
68        Self::new(key.into(), false, 0)
69    }
70
71    /// Creates a `KeySelector` that picks the last key less than or equal to the parameter
72    pub fn last_less_or_equal<K: Into<Cow<'a, [u8]>>>(key: K) -> Self {
73        Self::new(key.into(), true, 0)
74    }
75
76    /// Creates a `KeySelector` that picks the first key greater than the parameter
77    pub fn first_greater_than<K: Into<Cow<'a, [u8]>>>(key: K) -> Self {
78        Self::new(key.into(), true, 1)
79    }
80
81    /// Creates a `KeySelector` that picks the first key greater than or equal to the parameter
82    pub fn first_greater_or_equal<K: Into<Cow<'a, [u8]>>>(key: K) -> Self {
83        Self::new(key.into(), false, 1)
84    }
85
86    fn make_key(&mut self, key: &[u8]) {
87        match &mut self.key {
88            Bytes(Cow::Borrowed(..)) => self.key = Bytes::from(key.to_owned()),
89            Bytes(Cow::Owned(vec)) => {
90                vec.clear();
91                vec.extend_from_slice(key);
92            }
93        };
94    }
95
96    pub(crate) fn make_first_greater_or_equal(&mut self, key: &[u8]) {
97        self.make_key(key);
98        self.or_equal = false;
99        self.offset = 1;
100    }
101
102    pub(crate) fn make_first_greater_than(&mut self, key: &[u8]) {
103        self.make_key(key);
104        self.or_equal = true;
105        self.offset = 1;
106    }
107}