use crate::types::RowId;
use parking_lot::Mutex;
use std::num::NonZeroUsize;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum PkKey {
Int(i64),
Float(u64),
Text(Box<str>),
Bool(bool),
Null,
}
impl PkKey {
pub fn from_value(value: &crate::types::Value) -> Self {
match value {
crate::types::Value::Integer(i) => PkKey::Int(*i),
crate::types::Value::Float(f) => PkKey::Float(f.to_bits()),
crate::types::Value::Text(s) => PkKey::Text(s.clone().into_boxed_str()),
crate::types::Value::Bool(b) => PkKey::Bool(*b),
crate::types::Value::Null => PkKey::Null,
_ => PkKey::Null,
}
}
pub fn from_hash_key(s: &str) -> Self {
if let Some(rest) = s.strip_prefix("i:") {
if let Ok(i) = rest.parse::<i64>() {
return PkKey::Int(i);
}
} else if let Some(rest) = s.strip_prefix("f:") {
if let Ok(bits) = rest.parse::<u64>() {
return PkKey::Float(bits);
}
} else if let Some(rest) = s.strip_prefix("t:") {
return PkKey::Text(rest.into());
} else if let Some(rest) = s.strip_prefix("b:") {
if let Ok(b) = rest.parse::<bool>() {
return PkKey::Bool(b);
}
}
PkKey::Null
}
}
pub struct PkLookupCache {
cache: Mutex<lru::LruCache<PkKey, RowId>>,
}
impl PkLookupCache {
pub fn new(capacity: usize) -> Self {
Self {
cache: Mutex::new(lru::LruCache::new(
NonZeroUsize::new(capacity.max(1)).unwrap(),
)),
}
}
pub fn insert(&self, key: PkKey, row_id: RowId) {
let mut cache = self.cache.lock();
cache.put(key, row_id);
}
pub fn get(&self, key: &str) -> Option<RowId> {
let mut cache = self.cache.lock();
let pk_key = PkKey::from_hash_key(key);
cache.get(&pk_key).copied()
}
pub fn get_pk(&self, key: &PkKey) -> Option<RowId> {
let mut cache = self.cache.lock();
cache.get(key).copied()
}
pub fn remove(&self, key: &str) {
let mut cache = self.cache.lock();
let pk_key = PkKey::from_hash_key(key);
cache.pop(&pk_key);
}
pub fn remove_pk(&self, key: &PkKey) {
let mut cache = self.cache.lock();
cache.pop(key);
}
}