fuel_merkle/common/
storage_map.rs

1use crate::{
2    alloc::borrow::ToOwned,
3    storage::{
4        Mappable,
5        StorageInspect,
6        StorageMutate,
7    },
8};
9
10use alloc::borrow::Cow;
11use hashbrown::HashMap;
12
13#[derive(Debug, Clone)]
14pub struct StorageMap<Type>
15where
16    Type: Mappable,
17{
18    map: HashMap<Type::OwnedKey, Type::OwnedValue>,
19}
20
21impl<Type> Default for StorageMap<Type>
22where
23    Type: Mappable,
24{
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl<Type> StorageMap<Type>
31where
32    Type: Mappable,
33{
34    pub fn new() -> Self {
35        Self {
36            map: Default::default(),
37        }
38    }
39
40    pub fn is_empty(&self) -> bool {
41        self.map.is_empty()
42    }
43
44    pub fn len(&self) -> usize {
45        self.map.len()
46    }
47}
48
49impl<Type> StorageInspect<Type> for StorageMap<Type>
50where
51    Type: Mappable,
52    Type::Key: Eq + core::hash::Hash,
53    Type::OwnedKey: Eq + core::hash::Hash + core::borrow::Borrow<Type::Key>,
54{
55    type Error = core::convert::Infallible;
56
57    fn get(&self, key: &Type::Key) -> Result<Option<Cow<Type::OwnedValue>>, Self::Error> {
58        let result = self.map.get(key);
59        let value = result.map(Cow::Borrowed);
60        Ok(value)
61    }
62
63    fn contains_key(&self, key: &Type::Key) -> Result<bool, Self::Error> {
64        let contains = self.map.contains_key(key);
65        Ok(contains)
66    }
67}
68
69impl<Type> StorageMutate<Type> for StorageMap<Type>
70where
71    Type: Mappable,
72    Type::Key: Eq + core::hash::Hash,
73    Type::OwnedKey: Eq + core::hash::Hash + core::borrow::Borrow<Type::Key>,
74{
75    fn replace(
76        &mut self,
77        key: &Type::Key,
78        value: &Type::Value,
79    ) -> Result<Option<Type::OwnedValue>, Self::Error> {
80        let previous = self
81            .map
82            .insert(key.to_owned().into(), value.to_owned().into());
83        Ok(previous)
84    }
85
86    fn take(&mut self, key: &Type::Key) -> Result<Option<Type::OwnedValue>, Self::Error> {
87        let value = self.map.remove(key);
88        Ok(value)
89    }
90}
91
92#[cfg(test)]
93mod test {
94    use super::*;
95
96    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
97    struct TestKey(u32);
98
99    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
100    struct TestValue(u32);
101
102    struct TestTable;
103
104    impl Mappable for TestTable {
105        type Key = Self::OwnedKey;
106        type OwnedKey = TestKey;
107        type OwnedValue = TestValue;
108        type Value = Self::OwnedValue;
109    }
110
111    #[test]
112    fn test_get_returns_value_for_given_key() {
113        let key = TestKey(0);
114        let mut store = StorageMap::<TestTable>::new();
115        let _ = store.insert(&key, &TestValue(0));
116
117        assert_eq!(store.get(&key).unwrap(), Some(Cow::Borrowed(&TestValue(0))));
118    }
119    #[test]
120    fn test_get_returns_none_for_invalid_key() {
121        let key = TestKey(0);
122        let invalid_key = TestKey(1);
123        let mut store = StorageMap::<TestTable>::new();
124        let _ = store.insert(&key, &TestValue(0));
125
126        assert_eq!(store.get(&invalid_key).unwrap(), None);
127    }
128
129    #[test]
130    fn test_insert_existing_key_updates_value_for_given_key() {
131        let key = TestKey(0);
132        let mut store = StorageMap::<TestTable>::new();
133        let _ = store.insert(&key, &TestValue(0));
134        let _ = store.insert(&key, &TestValue(1));
135
136        assert_eq!(store.get(&key).unwrap(), Some(Cow::Borrowed(&TestValue(1))));
137    }
138
139    #[test]
140    fn test_remove_deletes_the_value_for_given_key() {
141        let key = TestKey(0);
142        let mut store = StorageMap::<TestTable>::new();
143        let _ = store.insert(&key, &TestValue(0));
144        let _ = store.remove(&key);
145
146        assert_eq!(store.get(&key).unwrap(), None);
147    }
148
149    #[test]
150    fn test_remove_returns_the_deleted_value_for_given_key() {
151        let key = TestKey(0);
152        let mut store = StorageMap::<TestTable>::new();
153        let _ = store.insert(&key, &TestValue(0));
154
155        assert_eq!(store.take(&key).unwrap(), Some(TestValue(0)));
156    }
157
158    #[test]
159    fn test_remove_returns_none_for_invalid_key() {
160        let invalid_key = TestKey(0);
161        let mut store = StorageMap::<TestTable>::new();
162
163        assert_eq!(store.take(&invalid_key).unwrap(), None);
164    }
165
166    #[test]
167    fn test_contains_key_returns_true_for_valid_key() {
168        let key = TestKey(0);
169        let mut store = StorageMap::<TestTable>::new();
170        let _ = store.insert(&key, &TestValue(0));
171
172        assert_eq!(store.contains_key(&key).unwrap(), true);
173    }
174
175    #[test]
176    fn test_contains_key_returns_false_for_invalid_key() {
177        let invalid_key = TestKey(0);
178        let store = StorageMap::<TestTable>::new();
179
180        assert_eq!(store.contains_key(&invalid_key).unwrap(), false);
181    }
182}