Skip to main content

luct_core/
store.rs

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