luct_core/store.rs
1use crate::tree::HashOutput;
2
3mod r#async;
4pub mod async_adapter;
5mod memory;
6
7pub use crate::store::r#async::{
8 AsyncAppendableStore, AsyncOrderedStore, AsyncOrderedStoreRead, AsyncSearchableStore,
9 AsyncSearchableStoreRead, AsyncStore, AsyncStoreRead, AsyncStoreWrite,
10};
11pub use crate::store::memory::MemoryStore;
12
13/// Trait indicating that an object can be hased with respect to the CT protocol
14///
15/// This for now always refers to the Sha256 algorithm, but this might change in the future
16pub trait Hashable {
17 /// Hash the object
18 fn hash(&self) -> HashOutput;
19}
20
21pub trait StoreBase {
22 type Key;
23 type Value;
24}
25
26pub trait StoreRead: StoreBase {
27 /// Returns the value associated with `key` from the [`Store`]
28 ///
29 /// # Arguments:
30 /// - `key`: the key indexing the object
31 ///
32 /// # Returns:
33 /// - `Some(value)`, if the value exists
34 /// - `None` otherwise
35 fn get(&self, key: &Self::Key) -> Option<Self::Value>;
36
37 /// Returns the number of elements in the [`Store`]
38 fn len(&self) -> usize;
39
40 /// Returns `true`, if the store is empty
41 fn is_empty(&self) -> bool {
42 self.len() == 0
43 }
44}
45
46pub trait StoreWrite: StoreBase {
47 /// Insert a value into the store
48 ///
49 /// # Arguments:
50 /// - `key`: the key associated with the value
51 /// - `value`: the value itself
52 fn insert(&self, key: Self::Key, value: Self::Value);
53
54 /// Remove a value from the store
55 ///
56 /// # Arguments
57 /// - `key`: the key to be removed
58 ///
59 /// # Returns
60 /// - `true` if the key existed and has been removed
61 /// - `false` otherwise
62 fn delete(&self, key: &Self::Key) -> bool;
63}
64
65/// The [`Store`] trait is a basic key-value store trait
66///
67/// Note that there is no ACID requirement in the trait.
68pub trait Store: StoreRead + StoreWrite {}
69impl<T> Store for T where T: StoreRead + StoreWrite {}
70
71/// Extension to regular [`Stores`](Store), which have ordered keys
72pub trait OrderedStoreRead: StoreRead<Key: Ord> {
73 /// Returns the last element in the store
74 ///
75 /// The last element is the largest element with respect to the keys [`Ord`] implementation.
76 ///
77 /// # Returns
78 /// - `Some(key, value)` if the store is non-empty
79 /// - `None` otherwise
80 fn last(&self) -> Option<(Self::Key, Self::Value)>;
81}
82
83pub trait OrderedStore: OrderedStoreRead + StoreWrite {}
84impl<T> OrderedStore for T where T: OrderedStoreRead + StoreWrite {}
85
86/// Extension to regular [`Stores`](Store), which use an index as a key
87///
88/// The main difference is, that the values can be inserted without providing a key.
89/// The key is then returned after insertion.
90///
91/// The key that was returned last must have be the largest value wrt [`Ord`].
92pub trait AppendableStore: OrderedStoreRead {
93 /// Insert a value into the store and return the index
94 ///
95 /// # Arguments:
96 /// - `value`: the value itself
97 ///
98 /// # Returns:
99 /// - the index of the new value. This is the key under which the value can later be retreived
100 fn append(&self, value: Self::Value) -> Self::Key;
101}
102
103/// Extension to a [`OrderedStoreRead`], that allows looking through the store to look for specific
104/// entries,
105pub trait SearchableStoreRead: OrderedStoreRead {
106 /// Search for all entries in the store, that fulfill a certain predicate
107 ///
108 /// Note that the elements are being searched through in the order specified by [`Ord`] of key
109 ///
110 /// # Arguments
111 /// - `pred`: A predicate that has access to the key and value
112 ///
113 /// # Returns
114 /// - An array of key-value pairs, for which `pred` holds true
115 fn filter(
116 &self,
117 pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
118 ) -> Vec<(Self::Key, Self::Value)>;
119
120 fn find(
121 &self,
122 mut pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
123 ) -> Option<(Self::Key, Self::Value)> {
124 let mut found = false;
125
126 let vals = self.filter(|key, value| {
127 if !found && pred(key, value) {
128 found = true;
129 true
130 } else {
131 false
132 }
133 });
134
135 if found {
136 assert_eq!(vals.len(), 1);
137 Some(vals.into_iter().next().unwrap())
138 } else {
139 None
140 }
141 }
142}
143
144pub trait SearchableStore: SearchableStoreRead + StoreWrite {}
145impl<T> SearchableStore for T where T: SearchableStoreRead + StoreWrite {}