poly_commitment/
hash_map_cache.rs

1use std::{
2    cmp::Eq,
3    collections::{hash_map::Entry, HashMap},
4    hash::Hash,
5    sync::{Arc, Mutex},
6};
7
8#[derive(Debug, Clone, Default)]
9pub struct HashMapCache<Key: Hash, Value> {
10    contents: Arc<Mutex<HashMap<Key, Value>>>,
11}
12
13impl<Key: Hash + Eq, Value> HashMapCache<Key, Value> {
14    pub fn new() -> Self {
15        HashMapCache {
16            contents: Arc::new(Mutex::new(HashMap::new())),
17        }
18    }
19
20    pub fn new_from_hashmap(hashmap: HashMap<Key, Value>) -> Self {
21        HashMapCache {
22            contents: Arc::new(Mutex::new(hashmap)),
23        }
24    }
25
26    pub fn get_or_generate<F: FnOnce() -> Value>(&self, key: Key, generator: F) -> &Value {
27        let mut hashmap = self.contents.lock().unwrap();
28        let entry = (*hashmap).entry(key);
29        let inner_ptr = match entry {
30            Entry::Occupied(o) => {
31                let o_ref = o.into_mut();
32                &*o_ref as *const Value
33            }
34            Entry::Vacant(v) => {
35                let v_ref = v.insert(generator());
36                &*v_ref as *const Value
37            }
38        };
39
40        // This is safe because we never delete entries from the cache, and the value reference
41        // must live at least at most as long as the cache value.
42        unsafe { &*inner_ptr }
43    }
44
45    pub fn contains_key(&self, key: &Key) -> bool {
46        self.contents.lock().unwrap().contains_key(key)
47    }
48}
49
50impl<Key: Hash + Eq + Clone, Value: Clone> From<HashMapCache<Key, Value>> for HashMap<Key, Value> {
51    fn from(cache: HashMapCache<Key, Value>) -> HashMap<Key, Value> {
52        cache.contents.lock().unwrap().clone()
53    }
54}