use std::collections::HashMap;
use std::sync::{Arc, OnceLock, RwLock};
const KEY_CAP: usize = 4096;
pub struct KeyCache {
map: RwLock<HashMap<Box<str>, Arc<str>>>,
}
impl KeyCache {
pub fn new() -> Arc<Self> {
Arc::new(Self {
map: RwLock::new(HashMap::with_capacity(64)),
})
}
#[inline]
pub fn intern(&self, k: &str) -> Arc<str> {
if let Ok(m) = self.map.read() {
if let Some(a) = m.get(k) {
return Arc::clone(a);
}
}
let mut m = match self.map.write() {
Ok(g) => g,
Err(_) => return Arc::<str>::from(k),
};
if let Some(a) = m.get(k) {
return Arc::clone(a);
}
if m.len() >= KEY_CAP {
return Arc::<str>::from(k);
}
let a: Arc<str> = Arc::<str>::from(k);
m.insert(k.into(), Arc::clone(&a));
a
}
pub fn clear(&self) {
if let Ok(mut m) = self.map.write() {
m.clear();
}
}
}
static DEFAULT_KEY_CACHE: OnceLock<Arc<KeyCache>> = OnceLock::new();
#[inline]
pub fn default_cache() -> &'static Arc<KeyCache> {
DEFAULT_KEY_CACHE.get_or_init(KeyCache::new)
}