use std::fmt::Debug;
use std::{hash::Hash, rc::Rc};
use crate::computed::struct_mut::HashMapMut;
type CreateType<K, V> = Box<dyn Fn(&AutoMap<K, V>, &K) -> V>;
fn get_unique_id() -> u64 {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(1);
COUNTER.fetch_add(1, Ordering::Relaxed)
}
#[derive(Clone)]
pub struct AutoMap<K, V> {
id: u64,
create: Rc<CreateType<K, V>>,
values: Rc<HashMapMut<K, V>>,
}
impl<K, V> Debug for AutoMap<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AutoMap").finish()
}
}
impl<K, V> PartialEq for AutoMap<K, V> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<K: Eq + Hash + Clone, V: Clone> AutoMap<K, V> {
pub fn new<C: Fn(&AutoMap<K, V>, &K) -> V + 'static>(create: C) -> AutoMap<K, V> {
AutoMap {
id: get_unique_id(),
create: Rc::new(Box::new(create)),
values: Rc::new(HashMapMut::new()),
}
}
pub fn get(&self, key: &K) -> V {
let item: Option<V> = self.values.get(key);
if let Some(item) = item {
return item;
}
let new_item = {
let create = &self.create;
create(self, key)
};
self.values.insert(key.clone(), new_item.clone());
new_item
}
pub fn for_each(&self, callback: fn(&K, &V)) {
self.values.for_each(callback);
}
}