use core::marker::PhantomData;
use crate::db::{Scope, key_delete, key_get, key_prefix, key_put};
use crate::{Codec, Postcard, Result, String, Vec};
pub struct Kv<V, C = Postcard> {
scope: Scope,
prefix: &'static str,
_marker: PhantomData<(V, C)>,
}
impl<V, C> Kv<V, C> {
pub const fn new(prefix: &'static str) -> Self {
Self::new_in(prefix, Scope::private())
}
pub const fn new_in(prefix: &'static str, scope: Scope) -> Self {
Self {
scope,
prefix,
_marker: PhantomData,
}
}
fn scope(&self) -> Scope {
self.scope.clone()
}
}
impl<V, C> Kv<V, C>
where
V: serde::Serialize + serde::de::DeserializeOwned,
C: Codec,
{
fn full_key(&self, key: &str) -> String {
let mut k = String::with_capacity(self.prefix.len() + 1 + key.len());
k.push_str(self.prefix);
k.push('/');
k.push_str(key);
k
}
pub fn get(&self, key: &str) -> Result<Option<V>> {
let mut req = [0u8; 256];
let mut resp = alloc::vec![0u8; 8192];
key_get(self.scope(), self.full_key(key), &mut req, &mut resp)?
.map(|b| C::decode(&b))
.transpose()
}
pub fn put(&self, key: &str, val: &V) -> Result<()> {
let bytes = C::encode(val)?;
let mut buf = alloc::vec![0u8; bytes.len() + 1024];
key_put(self.scope(), self.full_key(key), bytes, &mut buf).map_err(|_| "Kv::put")?;
Ok(())
}
pub fn delete(&self, key: &str) -> Result<()> {
let mut buf = [0u8; 256];
key_delete(self.scope(), self.full_key(key), &mut buf).map_err(|_| "Kv::delete")?;
Ok(())
}
pub fn keys(&self, sub: &str) -> Result<Vec<String>> {
let mut req = alloc::vec![0u8; 1024];
let mut resp = alloc::vec![0u8; 16384];
key_prefix(self.scope(), self.full_key(sub), &mut req, &mut resp).map_err(|_| "Kv::keys")
}
pub fn for_each<F: FnMut(V)>(&self, sub: &str, mut f: F) -> Result<()> {
for key in self.keys(sub)? {
let mut req = [0u8; 256];
let mut resp = alloc::vec![0u8; 8192];
if let Ok(Some(bytes)) = key_get(self.scope(), key, &mut req, &mut resp)
&& let Ok(v) = C::decode::<V>(&bytes)
{
f(v);
}
}
Ok(())
}
pub fn iter(&self, sub: &str) -> Result<Iter<V, C>> {
Ok(Iter {
scope: self.scope(),
keys: self.keys(sub)?,
idx: 0,
_marker: PhantomData,
})
}
pub fn list(&self, sub: &str) -> Result<Vec<V>> {
self.iter(sub)?.collect()
}
}
pub struct Iter<V, C = Postcard> {
scope: Scope,
keys: Vec<String>,
idx: usize,
_marker: PhantomData<(V, C)>,
}
impl<V, C> Iterator for Iter<V, C>
where
V: serde::de::DeserializeOwned,
C: Codec,
{
type Item = Result<V>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let key = self.keys.get(self.idx)?.clone();
self.idx += 1;
let mut req = [0u8; 256];
let mut resp = alloc::vec![0u8; 8192];
match key_get(self.scope.clone(), key, &mut req, &mut resp) {
Ok(Some(bytes)) => return Some(C::decode::<V>(&bytes)),
Ok(None) => continue, Err(_) => return Some(Err("Kv::iter")),
}
}
}
}