commonware_storage/kv/
mod.rs1use commonware_macros::{stability, stability_mod};
4
5stability_mod!(ALPHA, mod batch);
6#[stability(ALPHA)]
7pub use batch::{Batch, Batchable};
8use std::future::Future;
9
10pub trait Gettable {
12 type Key: Send + Sync;
13 type Value: Send + Sync;
14 type Error;
15
16 fn get<'a>(
18 &'a self,
19 key: &'a Self::Key,
20 ) -> impl Future<Output = Result<Option<Self::Value>, Self::Error>> + Send + use<'a, Self>;
21}
22
23pub trait Updatable: Gettable {
25 fn update<'a>(
27 &'a mut self,
28 key: Self::Key,
29 value: Self::Value,
30 ) -> impl Future<Output = Result<(), Self::Error>> + Send + use<'a, Self>;
31
32 fn create<'a>(
35 &'a mut self,
36 key: Self::Key,
37 value: Self::Value,
38 ) -> impl Future<Output = Result<bool, Self::Error>> + Send + use<'a, Self>
39 where
40 Self: Send,
41 {
42 async {
43 if self.get(&key).await?.is_some() {
44 return Ok(false);
45 }
46 self.update(key, value).await?;
47 Ok(true)
48 }
49 }
50
51 fn upsert<'a, F>(
54 &'a mut self,
55 key: Self::Key,
56 update: F,
57 ) -> impl Future<Output = Result<(), Self::Error>> + Send + use<'a, Self, F>
58 where
59 Self: Send,
60 Self::Value: Default,
61 F: FnOnce(&mut Self::Value) + Send + 'a,
62 {
63 async move {
64 let mut value = self.get(&key).await?.unwrap_or_default();
65 update(&mut value);
66 self.update(key, value).await
67 }
68 }
69}
70
71pub trait Deletable: Updatable {
73 fn delete<'a>(
77 &'a mut self,
78 key: Self::Key,
79 ) -> impl Future<Output = Result<bool, Self::Error>> + Send + use<'a, Self>;
80}
81
82#[cfg(test)]
83pub(crate) mod tests {
84 use super::{Batchable, Deletable, Gettable, Updatable};
85 use commonware_codec::DecodeExt;
86 use commonware_utils::sequence::FixedBytes;
87
88 pub fn assert_send<T: Send>(_: T) {}
89
90 pub fn test_key(key: &str) -> FixedBytes<64> {
92 let mut buf = [0u8; 64];
93 let key = key.as_bytes();
94 assert!(key.len() <= buf.len());
95 buf[..key.len()].copy_from_slice(key);
96 FixedBytes::decode(buf.as_ref()).unwrap()
97 }
98
99 #[allow(dead_code)]
100 pub fn assert_gettable<T: Gettable + Send>(db: &T, key: &T::Key) {
101 assert_send(db.get(key));
102 }
103
104 #[allow(dead_code)]
105 pub fn assert_updatable<T: Updatable + Send>(db: &mut T, key: T::Key, value: T::Value)
106 where
107 T::Key: Clone,
108 T::Value: Default + Clone,
109 {
110 assert_send(db.update(key.clone(), value.clone()));
111 assert_send(db.create(key.clone(), value));
112 assert_send(db.upsert(key, |_| {}));
113 }
114
115 #[allow(dead_code)]
116 pub fn assert_deletable<T: Deletable + Send>(db: &mut T, key: T::Key) {
117 assert_send(db.delete(key));
118 }
119
120 #[allow(dead_code)]
121 pub fn assert_batchable<T: Batchable + Send>(db: &mut T, key: T::Key, value: T::Value) {
122 assert_send(db.write_batch(vec![(key, Some(value))].into_iter()));
123 }
124}