use core::hash::{BuildHasher, Hash};
use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::pin::Pin;
#[derive(Default)]
pub struct LocalCache<K, V, H> {
store: UnsafeCell<HashMap<K, Pin<Box<V>>, H>>,
}
impl<K, V, H> LocalCache<K, V, H>
where
K: Eq + Hash,
H: Default + BuildHasher,
{
pub fn new() -> Self {
LocalCache {
store: UnsafeCell::new(HashMap::with_hasher(Default::default())),
}
}
pub fn get_or_insert_with(&self, key: K, f: impl FnOnce() -> V) -> &V {
let mut_store = unsafe { &mut *self.store.get() };
mut_store.entry(key).or_insert_with(|| Box::pin(f()))
}
pub fn flush_iter(self) -> impl Iterator<Item = (K, V)> {
self.store
.into_inner()
.into_iter()
.map(|(k, v)| (k, unsafe { *Pin::into_inner_unchecked(v) }))
}
}