commonware_storage/kv/
mod.rs

1//! Traits for interacting with a key/value store.
2
3mod batch;
4pub use batch::{Batch, Batchable};
5use std::future::Future;
6
7/// A readable key-value store.
8pub trait Gettable {
9    type Key: Send + Sync;
10    type Value: Send + Sync;
11    type Error;
12
13    /// Get the value of a key.
14    fn get<'a>(
15        &'a self,
16        key: &'a Self::Key,
17    ) -> impl Future<Output = Result<Option<Self::Value>, Self::Error>> + Send + use<'a, Self>;
18}
19
20/// A mutable key-value store.
21pub trait Updatable: Gettable {
22    /// Update the value of a key.
23    fn update<'a>(
24        &'a mut self,
25        key: Self::Key,
26        value: Self::Value,
27    ) -> impl Future<Output = Result<(), Self::Error>> + Send + use<'a, Self>;
28
29    /// Creates a new key-value pair in the db. Returns true if the key was created, false if it
30    /// already existed. The key is not modified if it already existed.
31    fn create<'a>(
32        &'a mut self,
33        key: Self::Key,
34        value: Self::Value,
35    ) -> impl Future<Output = Result<bool, Self::Error>> + Send + use<'a, Self>
36    where
37        Self: Send,
38    {
39        async {
40            if self.get(&key).await?.is_some() {
41                return Ok(false);
42            }
43            self.update(key, value).await?;
44            Ok(true)
45        }
46    }
47
48    /// Updates the value associated with the given key in the store, inserting a default value if
49    /// the key does not already exist.
50    fn upsert<'a, F>(
51        &'a mut self,
52        key: Self::Key,
53        update: F,
54    ) -> impl Future<Output = Result<(), Self::Error>> + Send + use<'a, Self, F>
55    where
56        Self: Send,
57        Self::Value: Default,
58        F: FnOnce(&mut Self::Value) + Send + 'a,
59    {
60        async move {
61            let mut value = self.get(&key).await?.unwrap_or_default();
62            update(&mut value);
63            self.update(key, value).await
64        }
65    }
66}
67
68/// A mutable key-value store that supports deleting values.
69pub trait Deletable: Updatable {
70    /// Delete the value of a key.
71    ///
72    /// Returns `true` if the key existed and was deleted, `false` if it did not exist.
73    fn delete<'a>(
74        &'a mut self,
75        key: Self::Key,
76    ) -> impl Future<Output = Result<bool, Self::Error>> + Send + use<'a, Self>;
77}
78
79#[cfg(test)]
80pub(crate) mod tests {
81    use super::{Batchable, Deletable, Gettable, Updatable};
82
83    pub fn assert_send<T: Send>(_: T) {}
84
85    #[allow(dead_code)]
86    pub fn assert_gettable<T: Gettable + Send>(db: &T, key: &T::Key) {
87        assert_send(db.get(key));
88    }
89
90    #[allow(dead_code)]
91    pub fn assert_updatable<T: Updatable + Send>(db: &mut T, key: T::Key, value: T::Value)
92    where
93        T::Key: Clone,
94        T::Value: Default + Clone,
95    {
96        assert_send(db.update(key.clone(), value.clone()));
97        assert_send(db.create(key.clone(), value));
98        assert_send(db.upsert(key, |_| {}));
99    }
100
101    #[allow(dead_code)]
102    pub fn assert_deletable<T: Deletable + Send>(db: &mut T, key: T::Key) {
103        assert_send(db.delete(key));
104    }
105
106    #[allow(dead_code)]
107    pub fn assert_batchable<T: Batchable + Send>(db: &mut T, key: T::Key, value: T::Value) {
108        assert_send(db.write_batch(vec![(key, Some(value))].into_iter()));
109    }
110}