use crate::keri::core::serdering::{Rawifiable, Serder, SerderACDC, SerderKERI};
use crate::keri::db::dbing::{BytesDatabase, LMDBer};
use crate::keri::db::errors::DBError;
use crate::keri::db::subing::{SuberError, ValueCodec};
use std::marker::PhantomData;
use std::sync::Arc;
pub struct SerderCodec<S: Serder + 'static> {
verify: bool,
_serder_type: PhantomData<S>,
}
impl<S: Serder + 'static> SerderCodec<S> {
pub fn new(verify: bool) -> Self {
Self {
verify,
_serder_type: PhantomData,
}
}
}
impl<S: Serder + 'static> ValueCodec for SerderCodec<S> {
type Error = SuberError;
fn serialize<T: ?Sized + Clone + Into<Vec<u8>>>(val: &T) -> Result<Vec<u8>, SuberError> {
Ok(val.clone().into())
}
fn deserialize<T: TryFrom<Vec<u8>>>(bytes: &[u8]) -> Result<T, SuberError> {
Err(SuberError::DeserializationError(
"Direct deserialization not implemented".to_string(),
))
}
}
pub struct SerderSuberBase<'db, S: Serder + Rawifiable + 'static> {
db: Arc<&'db LMDBer>, sdb: BytesDatabase, sep: u8, verify: bool, _serder_type: PhantomData<S>, }
impl<'db, S: Serder + Rawifiable + 'static> SerderSuberBase<'db, S> {
pub fn new(
db: Arc<&'db LMDBer>,
subkey: &str,
sep: Option<u8>,
verify: bool,
) -> Result<Self, SuberError> {
let sdb = db.create_database(Some(subkey), Some(false))?;
Ok(Self {
db,
sdb,
sep: sep.unwrap_or(b'.'),
verify,
_serder_type: PhantomData,
})
}
pub fn to_key<K: AsRef<[u8]>>(&self, keys: &[K], topive: bool) -> Vec<u8> {
let mut result = Vec::new();
if keys.len() == 1 {
let key = keys[0].as_ref();
if !topive {
return key.to_vec();
}
result.extend_from_slice(key);
result.push(self.sep);
return result;
}
for (i, key) in keys.iter().enumerate() {
if i > 0 {
result.push(self.sep);
}
result.extend_from_slice(key.as_ref());
}
if topive && (!result.is_empty() && result[result.len() - 1] != self.sep) {
result.push(self.sep);
}
result
}
pub fn to_keys(&self, key: &[u8]) -> Vec<Vec<u8>> {
key.split(|&b| b == self.sep)
.map(|part| part.to_vec())
.collect()
}
fn ser(&self, val: &S) -> Vec<u8> {
val.raw().to_vec()
}
fn des(&self, val: &[u8]) -> Result<S, SuberError> {
S::from_raw(val, None).map_err(|e| {
SuberError::DeserializationError(format!("Failed to deserialize Serder: {}", e))
})
}
pub fn get<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<Option<S>, SuberError> {
let key = self.to_key(keys, false);
if let Some(val) = self.db.get_val(&self.sdb, &key)? {
let serder = self.des(&val)?;
Ok(Some(serder))
} else {
Ok(None)
}
}
pub fn put<K: AsRef<[u8]>>(&self, keys: &[K], val: &S) -> Result<bool, SuberError> {
let key = self.to_key(keys, false);
let val_bytes = self.ser(val);
Ok(self.db.put_val(&self.sdb, &key, &val_bytes)?)
}
pub fn pin<K: AsRef<[u8]>>(&self, keys: &[K], val: &S) -> Result<bool, SuberError> {
let key = self.to_key(keys, false);
let val_bytes = self.ser(val);
Ok(self.db.set_val(&self.sdb, &key, &val_bytes)?)
}
pub fn rem<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<bool, SuberError> {
let key = self.to_key(keys, false);
Ok(self.db.del_val(&self.sdb, &key)?)
}
pub fn trim<K: AsRef<[u8]>>(&self, keys: &[K], topive: bool) -> Result<bool, SuberError> {
let key = self.to_key(keys, topive);
Ok(self.db.del_top_val(&self.sdb, &key)?)
}
pub fn get_full_item_iter<K: AsRef<[u8]>>(
&self,
keys: &[K],
topive: bool,
) -> Result<Vec<(Vec<Vec<u8>>, S)>, SuberError> {
let key = self.to_key(keys, topive);
let mut result = Vec::new();
self.db.get_top_items_iter(&self.sdb, &key, |k, v| {
let serder = match self.des(v) {
Ok(s) => s,
Err(e) => {
return Err(DBError::ValueError(format!(
"Failed to deserialize Serder: {}",
e
)))
}
};
result.push((self.to_keys(k), serder));
Ok(true) })?;
Ok(result)
}
pub fn get_item_iter<K: AsRef<[u8]>>(
&self,
keys: &[K],
topive: bool,
) -> Result<Vec<(Vec<Vec<u8>>, S)>, SuberError> {
self.get_full_item_iter(keys, topive)
}
pub fn cnt_all(&self) -> Result<usize, SuberError> {
Ok(self.db.cnt(&self.sdb)?)
}
}
pub struct SerderSuber<'db, S: Serder + Rawifiable + 'static> {
base: SerderSuberBase<'db, S>,
}
impl<'db, S: Serder + Rawifiable + 'static> SerderSuber<'db, S> {
pub fn new(
db: Arc<&'db LMDBer>,
subkey: &str,
sep: Option<u8>,
verify: bool,
) -> Result<Self, SuberError> {
let base = SerderSuberBase::new(db, subkey, sep, verify)?;
Ok(Self { base })
}
pub fn put<K: AsRef<[u8]>>(&self, keys: &[K], val: &S) -> Result<bool, SuberError> {
self.base.put(keys, val)
}
pub fn pin<K: AsRef<[u8]>>(&self, keys: &[K], val: &S) -> Result<bool, SuberError> {
self.base.pin(keys, val)
}
pub fn get<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<Option<S>, SuberError> {
self.base.get(keys)
}
pub fn rem<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<bool, SuberError> {
self.base.rem(keys)
}
pub fn trim<K: AsRef<[u8]>>(&self, keys: &[K], topive: bool) -> Result<bool, SuberError> {
self.base.trim(keys, topive)
}
pub fn get_full_item_iter<K: AsRef<[u8]>>(
&self,
keys: &[K],
topive: bool,
) -> Result<Vec<(Vec<Vec<u8>>, S)>, SuberError> {
self.base.get_full_item_iter(keys, topive)
}
pub fn get_item_iter<K: AsRef<[u8]>>(
&self,
keys: &[K],
topive: bool,
) -> Result<Vec<(Vec<Vec<u8>>, S)>, SuberError> {
self.base.get_item_iter(keys, topive)
}
pub fn cnt_all(&self) -> Result<usize, SuberError> {
self.base.cnt_all()
}
}
pub type SerderKERISuber<'db> = SerderSuber<'db, SerderKERI>;
pub type SerderACDCSuber<'db> = SerderSuber<'db, SerderACDC>;
#[cfg(test)]
mod tests {
use super::*;
use crate::keri::core::serdering::SerderKERI;
use crate::keri::db::dbing::LMDBer;
use std::sync::Arc;
#[test]
fn test_serder_suber() -> Result<(), SuberError> {
let lmdber = LMDBer::builder()
.name("test_serder_db")
.temp(true)
.build()?;
let db = Arc::new(&lmdber);
let suber: SerderSuber<SerderKERI> = SerderSuber::new(db, "serders.", None, false)?;
let sample_ked = r#"{"v":"KERI10JSON00012b_","t":"icp","d":"EDkU2U_TPKca14VElEItpj7twohQL60GIaUPvSHAghga","i":"EDkU2U_TPKca14VElEItpj7twohQL60GIaUPvSHAghga","s":"0","kt":"1","k":["DLcVCJsrp_z4To1j52pggULYa_PEs2sCZggVJ3jBUFeI"],"nt":"1","n":["EA1P0H2qNRf_685xnztMESEs36hwWBTTQmwVrZr5qGyQ"],"bt":"0","b":[],"c":[],"a":[]}"#;
let serder =
SerderKERI::from_raw(sample_ked.as_ref(), None).expect("Failed to parse test Serder");
let keys = &["test_key".as_bytes()];
suber.put(keys, &serder)?;
let retrieved = suber.get(keys)?;
assert!(retrieved.is_some());
let retrieved_serder = retrieved.unwrap();
assert_eq!(retrieved_serder.raw(), serder.raw());
let sample_ked2 = r#"{"v":"KERI10JSON000160_","t":"rot","d":"EAg5uUuKVgvaz0vgEC7B-rQdsXHhDCXXbKdO5KRTDQFq","i":"EFa1wAk_coghxxGCID6jEN79Kmvyj0Y1wWN_ndUv3LjW","s":"1","p":"EFa1wAk_coghxxGCID6jEN79Kmvyj0Y1wWN_ndUv3LjW","kt":"1","k":["DAceoFXtYpYjyKGLLfv0Hs4YSGQtqmzKx64zfMI9fBUM"],"nt":"1","n":["EPwseSLvRsbjHDUGeZJSed0HF_Myw8qvZksRTQBC2cjO"],"bt":"0","br":[],"ba":[],"a":[]}"#;
let serder2 =
SerderKERI::from_raw(sample_ked2.as_ref(), None).expect("Failed to parse test Serder");
let result = suber.put(keys, &serder2)?;
assert!(!result);
let retrieved = suber.get(keys)?.unwrap();
assert_eq!(retrieved.raw(), serder.raw());
let result = suber.pin(keys, &serder2)?;
assert!(result);
let retrieved = suber.get(keys)?.unwrap();
assert_eq!(retrieved.raw(), serder2.raw());
let result = suber.rem(keys)?;
assert!(result);
let retrieved = suber.get(keys)?;
assert!(retrieved.is_none());
let serders = [
(vec!["a", "1"], serder.clone()),
(vec!["a", "2"], serder2.clone()),
];
for (k, s) in &serders {
let key_bytes: Vec<&[u8]> = k.iter().map(|s| s.as_bytes()).collect();
suber.put(&key_bytes, s)?;
}
let iter_keys = &["a".as_bytes()];
let items = suber.get_item_iter(iter_keys, true)?;
assert_eq!(items.len(), 2);
let count = suber.cnt_all()?;
assert_eq!(count, 2);
suber.trim(iter_keys, true)?;
let count = suber.cnt_all()?;
assert_eq!(count, 0);
Ok(())
}
}