poly_commitment/
hash_map_cache.rs1#![allow(unsafe_code)]
2
3use std::{
4 cmp::Eq,
5 collections::{hash_map::Entry, HashMap},
6 hash::Hash,
7 sync::{Arc, Mutex},
8};
9
10#[derive(Debug, Clone, Default)]
11pub struct HashMapCache<Key: Hash, Value> {
12 contents: Arc<Mutex<HashMap<Key, Value>>>,
13}
14
15impl<Key: Hash + Eq, Value> HashMapCache<Key, Value> {
16 #[must_use]
17 pub fn new() -> Self {
18 Self {
19 contents: Arc::new(Mutex::new(HashMap::new())),
20 }
21 }
22
23 #[must_use]
24 pub fn new_from_hashmap(hashmap: HashMap<Key, Value>) -> Self {
25 Self {
26 contents: Arc::new(Mutex::new(hashmap)),
27 }
28 }
29
30 pub fn get_or_generate<F: FnOnce() -> Value>(&self, key: Key, generator: F) -> &Value {
37 let mut hashmap = self.contents.lock().unwrap();
38 let entry = (*hashmap).entry(key);
39 let inner_ptr = match entry {
40 Entry::Occupied(o) => {
41 let o_ref = o.into_mut();
42 std::ptr::from_ref(o_ref)
43 }
44 Entry::Vacant(v) => {
45 let v_ref = v.insert(generator());
46 std::ptr::from_ref(v_ref)
47 }
48 };
49 drop(hashmap);
50
51 unsafe { &*inner_ptr }
55 }
56
57 pub fn contains_key(&self, key: &Key) -> bool {
63 self.contents.lock().unwrap().contains_key(key)
64 }
65}
66
67#[allow(clippy::implicit_hasher)]
68#[allow(clippy::fallible_impl_from)]
69impl<Key: Hash + Eq + Clone, Value: Clone> From<HashMapCache<Key, Value>> for HashMap<Key, Value> {
70 fn from(cache: HashMapCache<Key, Value>) -> Self {
71 cache.contents.lock().unwrap().clone()
72 }
73}