stupid_simple_kv/
list_builder.rs

1use std::sync::{Arc, RwLock};
2
3use crate::{IntoKey, KvBackend, KvKey, KvResult, KvValue};
4
5/// Builder for flexible queries over a key/value backend.
6///
7/// Use prefix, start, and end keys to define your query range, then call [`KvListBuilder::entries`].
8///
9/// # Examples
10///
11/// ```rust
12/// use stupid_simple_kv::{Kv, MemoryBackend, KvValue, IntoKey};
13/// let mut kv = Kv::new(Box::new(MemoryBackend::new()));
14///
15/// // List all pairs with prefix (1, _)
16/// let pairs = kv.list().prefix(&(1u64,)).entries().unwrap();
17///
18/// // Range scan from (99,2) up to (99,5)
19/// let result = kv.list().start(&(99u64, 2i64)).end(&(99u64, 5i64)).entries().unwrap();
20/// ```
21pub struct KvListBuilder {
22    pub(crate) backend: Arc<RwLock<Box<dyn KvBackend>>>,
23    pub(crate) prefix: Option<KvKey>,
24    pub(crate) start: Option<KvKey>,
25    pub(crate) end: Option<KvKey>,
26}
27
28impl KvListBuilder {
29    pub(crate) fn new(backend: Arc<RwLock<Box<dyn KvBackend>>>) -> Self {
30        Self {
31            backend,
32            prefix: None,
33            start: None,
34            end: None,
35        }
36    }
37
38    /// Restrict results to the given key prefix.
39    pub fn prefix(&mut self, prefix: &dyn IntoKey) -> &mut Self {
40        self.prefix = Some(prefix.to_key());
41        self
42    }
43
44    /// Start listing at this key (inclusive).
45    pub fn start(&mut self, start: &dyn IntoKey) -> &mut Self {
46        self.start = Some(start.to_key());
47        self
48    }
49
50    /// End listing at this key (exclusive).
51    pub fn end(&mut self, end: &dyn IntoKey) -> &mut Self {
52        self.end = Some(end.to_key());
53        self
54    }
55
56    /// Run the current query and return key-value pairs.
57    /// Returns all results matching the filter/prefix/bounds.
58    ///
59    /// # Errors
60    /// Returns an error if the combination of selectors is invalid, or if decoding fails.
61    pub fn entries(&self) -> KvResult<Vec<(KvKey, KvValue)>> {
62        use crate::KvError;
63
64        // Disallow all three present.
65        if self.prefix.is_some() && self.start.is_some() && self.end.is_some() {
66            return Err(KvError::InvalidSelector);
67        }
68
69        let (range_start, range_end) =
70            match (self.prefix.clone(), self.start.clone(), self.end.clone()) {
71                (Some(prefix), None, None) => {
72                    let end = prefix.successor();
73                    (Some(prefix), end)
74                }
75                (None, Some(start), None) => (Some(start), None),
76                (None, None, Some(end)) => (None, Some(end)),
77                (Some(_prefix), Some(start), None) => (Some(start), None), // start wins
78                (Some(prefix), None, Some(end)) => (Some(prefix), Some(end)),
79                (None, Some(start), Some(end)) => (Some(start), Some(end)),
80                (None, None, None) => (None, None),
81                _ => return Err(KvError::InvalidSelector),
82            };
83
84        // Fetch the range (unbounded if end is None)
85        let items = self
86            .backend
87            .try_write()?
88            .get_range(range_start, range_end)?;
89
90        let mut result = Vec::with_capacity(items.len());
91        for (k, v) in items {
92            let (decoded, _consumed) =
93                bincode::decode_from_slice::<KvValue, _>(&v, bincode::config::standard())
94                    .map_err(KvError::ValDecodeError)?;
95            result.push((k, decoded));
96        }
97        Ok(result)
98    }
99}