use crate::protocol::Value;
use dashmap::DashMap;
use bytes::Bytes;
#[derive(Default)]
pub struct Dict {
pub(crate) inner: DashMap<Bytes, Value>,
}
impl Dict {
#[inline]
pub fn get(&self, k: &[u8]) -> Option<Value> {
self.inner.get(k).map(|v| v.clone())
}
#[inline]
pub fn set(&self, k: Bytes, v: Value) {
self.inner.insert(k, v);
}
#[inline]
pub fn del(&self, k: &[u8]) -> bool {
self.inner.remove(k).is_some()
}
#[inline]
pub fn rename(&self, from: Bytes, to: Bytes) -> bool {
if from == to {
return true;
}
if let Some((_, v)) = self.inner.remove(&from) {
self.inner.insert(to, v);
true
} else {
false
}
}
#[inline]
pub fn exists(&self, k: &[u8]) -> bool {
self.inner.contains_key(k)
}
pub fn incr(&self, k: &[u8]) -> i64 {
use dashmap::mapref::entry::Entry;
match self.inner.entry(Bytes::copy_from_slice(k)) {
Entry::Occupied(mut e) => match e.get_mut() {
Value::Int(i) => {
*i += 1;
*i
}
Value::Str(s) => {
let mut n = std::str::from_utf8(s)
.ok()
.and_then(|x| x.parse::<i64>().ok())
.unwrap_or(0);
n += 1;
*e.get_mut() = Value::Int(n);
n
}
_ => 0,
},
Entry::Vacant(v) => {
v.insert(Value::Int(1));
1
}
}
}
}