use crate::cesr::prefixer::Prefixer;
use crate::cesr::signing::Cipher;
use crate::keri::app::keeping::creators::Algos;
use crate::keri::core::filing::{BaseFiler, Filer, FilerDefaults};
use crate::keri::db::dbing::LMDBer;
use crate::keri::db::errors::DBError;
use crate::keri::db::koming::{Komer, SerialKind};
use crate::keri::db::subing::cesr::CesrSuber;
use crate::keri::db::subing::signer::CryptSignerSuber;
use crate::keri::db::subing::Suber;
use serde::{Deserialize, Serialize};
use std::iter::IntoIterator;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PubLot {
#[serde(default)]
pub pubs: Vec<String>,
#[serde(default)]
pub ridx: usize,
#[serde(default)]
pub kidx: usize,
#[serde(default)]
pub dt: String,
}
impl Default for PubLot {
fn default() -> Self {
Self {
pubs: Vec::new(),
ridx: 0,
kidx: 0,
dt: String::new(),
}
}
}
impl IntoIterator for PubLot {
type Item = (String, serde_json::Value);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
let mut result = Vec::new();
result.push((
"pubs".to_string(),
serde_json::to_value(&self.pubs).unwrap(),
));
result.push((
"ridx".to_string(),
serde_json::to_value(&self.ridx).unwrap(),
));
result.push((
"kidx".to_string(),
serde_json::to_value(&self.kidx).unwrap(),
));
result.push(("dt".to_string(), serde_json::to_value(&self.dt).unwrap()));
result.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PreSit {
#[serde(default)]
pub old: Option<PubLot>,
#[serde(default)]
pub new: PubLot,
#[serde(default)]
pub nxt: PubLot,
}
impl Default for PreSit {
fn default() -> Self {
Self {
old: Some(PubLot::default()),
new: PubLot::default(),
nxt: PubLot::default(),
}
}
}
impl IntoIterator for PreSit {
type Item = (String, serde_json::Value);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
let mut result = Vec::new();
result.push(("old".to_string(), serde_json::to_value(&self.old).unwrap()));
result.push(("new".to_string(), serde_json::to_value(&self.new).unwrap()));
result.push(("nxt".to_string(), serde_json::to_value(&self.nxt).unwrap()));
result.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrePrm {
#[serde(default)]
pub pidx: usize,
#[serde(default = "default_algo")]
pub algo: String,
#[serde(default)]
pub salt: String,
#[serde(default)]
pub stem: String,
#[serde(default)]
pub tier: String,
}
fn default_algo() -> String {
Algos::Salty.to_string()
}
impl Default for PrePrm {
fn default() -> Self {
Self {
pidx: 0,
algo: Algos::Salty.to_string(),
salt: String::new(),
stem: String::new(),
tier: String::new(),
}
}
}
impl IntoIterator for PrePrm {
type Item = (String, serde_json::Value);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
let mut result = Vec::new();
result.push((
"pidx".to_string(),
serde_json::to_value(&self.pidx).unwrap(),
));
result.push((
"algo".to_string(),
serde_json::to_value(&self.algo).unwrap(),
));
result.push((
"salt".to_string(),
serde_json::to_value(&self.salt).unwrap(),
));
result.push((
"stem".to_string(),
serde_json::to_value(&self.stem).unwrap(),
));
result.push((
"tier".to_string(),
serde_json::to_value(&self.tier).unwrap(),
));
result.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PubSet {
#[serde(default)]
pub pubs: Vec<String>,
}
impl Default for PubSet {
fn default() -> Self {
Self { pubs: Vec::new() }
}
}
impl IntoIterator for PubSet {
type Item = (String, serde_json::Value);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
let mut result = Vec::new();
result.push((
"pubs".to_string(),
serde_json::to_value(&self.pubs).unwrap(),
));
result.into_iter()
}
}
pub struct Keeper<'db> {
lmdber: Arc<&'db LMDBer>,
pub gbls: Suber<'db>,
pub pris: CryptSignerSuber<'db>,
pub prxs: CesrSuber<'db, Cipher>,
pub nxts: CesrSuber<'db, Cipher>,
pub pres: CesrSuber<'db, Prefixer>,
pub prms: Komer<'db, PrePrm>,
pub sits: Komer<'db, PreSit>,
pub pubs: Komer<'db, PubSet>,
}
impl<'db> Filer for Keeper<'db> {
fn defaults() -> FilerDefaults {
BaseFiler::defaults()
}
#[cfg(target_os = "windows")]
const TAIL_DIR_PATH: &'static str = "keri\\ks";
#[cfg(not(target_os = "windows"))]
const TAIL_DIR_PATH: &'static str = "keri/ks";
#[cfg(target_os = "windows")]
const ALT_TAIL_DIR_PATH: &'static str = ".keri\\ks";
#[cfg(not(target_os = "windows"))]
const ALT_TAIL_DIR_PATH: &'static str = ".keri/ks";
const TEMP_PREFIX: &'static str = "keri_ks_";
}
impl<'db> Keeper<'db> {
pub const MAX_NAMED_DBS: u32 = 10;
pub fn new(lmdber: Arc<&'db LMDBer>) -> Result<Self, DBError> {
let keeper = Keeper {
lmdber: lmdber.clone(),
gbls: Suber::new(lmdber.clone(), "gbls.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
pris: CryptSignerSuber::new(lmdber.clone(), "pris.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
prxs: CesrSuber::new(lmdber.clone(), "prxs.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
nxts: CesrSuber::new(lmdber.clone(), "nxts.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
pres: CesrSuber::new(lmdber.clone(), "pres.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
prms: Komer::new(lmdber.clone(), "prms.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
sits: Komer::new(lmdber.clone(), "sits.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
pubs: Komer::new(lmdber.clone(), "pubs.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
};
Ok(keeper)
}
pub fn opened(&self) -> bool {
self.lmdber.opened()
}
pub fn name(&self) -> String {
self.lmdber.name()
}
pub fn path(&self) -> Option<PathBuf> {
self.lmdber.path()
}
pub fn temp(&self) -> bool {
self.lmdber.temp()
}
pub fn ri_key(pre: &str, ri: u64) -> String {
format!("{}.{:032x}", pre, ri)
}
}
impl<'db> Drop for Keeper<'db> {
fn drop(&mut self) {
}
}
pub trait KeeperTrait: Send + Sync {
fn opened(&self) -> bool;
fn name(&self) -> String;
fn path(&self) -> Option<PathBuf>;
fn temp(&self) -> bool;
fn ri_key(&self, pre: &str, ri: u64) -> String;
}
impl<'db> KeeperTrait for Keeper<'db> {
fn opened(&self) -> bool {
self.lmdber.opened()
}
fn name(&self) -> String {
self.lmdber.name()
}
fn path(&self) -> Option<PathBuf> {
self.lmdber.path()
}
fn temp(&self) -> bool {
self.lmdber.temp()
}
fn ri_key(&self, pre: &str, ri: u64) -> String {
Self::ri_key(pre, ri) }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cesr::Parsable;
use crate::Matter;
#[test]
fn test_keeper_basics() -> Result<(), DBError> {
let lmdber = LMDBer::builder().name("test_keeper").temp(true).build()?;
assert_eq!(lmdber.name(), "test_keeper");
assert!(lmdber.opened());
let keeper = Keeper::new(Arc::new(&lmdber))?;
assert!(keeper.opened());
assert_eq!(keeper.name(), "test_keeper");
assert!(keeper.opened());
assert!(keeper.temp());
let path = keeper.path().unwrap();
assert!(path.exists());
drop(keeper);
drop(lmdber);
Ok(())
}
#[test]
fn test_keeper_subdb() -> Result<(), DBError> {
let mut lmdber = LMDBer::builder()
.name("test_keeper_subdb")
.temp(true)
.build()?;
assert_eq!(lmdber.name(), "test_keeper_subdb");
assert!(lmdber.opened());
let keeper = Keeper::new(Arc::new(&lmdber))?;
let key = "aeid";
let val = "BDzwEHHzq7K0gzQPYGGwTmuupUhPx5_yZ-Wk1x4ejhcc";
keeper
.gbls
.put(&[key], &val.as_bytes())
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?;
let result: Option<Vec<u8>> = keeper
.gbls
.get(&[key])
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?;
assert!(result.is_some());
let val_bytes = result.unwrap();
let val_str = String::from_utf8(val_bytes).unwrap();
assert_eq!(val_str, val);
let pub_key = b"BDzwEHHzq7K0gzQPYGGwTmuupUhPx5_yZ-Wk1x4ejhcc";
let pre = Prefixer::from_qb64b(&mut pub_key.to_vec(), None).expect("Invalid prefix");
keeper
.pres
.put(&[pub_key], &pre)
.expect("Failed to put prefix");
let result = keeper.pres.get(&[pub_key]).expect("Failed to get prefix");
assert!(result.is_some());
let retrieved_pre = result.unwrap();
assert_eq!(retrieved_pre.qb64(), pre.qb64());
let prms = PrePrm::default();
let key = "prms.00000000000000000000000000000000";
let result = keeper.prms.put(&[key], &prms).expect("Failed to put prms");
assert!(result);
let result = keeper.prms.get(&[key]).expect("Failed to get prms");
assert!(result.is_some());
assert_eq!(result.unwrap().pidx, 0);
assert!(
keeper
.prms
.cnt_all()
.expect("there to be some values in the database")
> 0
);
Ok(())
}
#[test]
fn test_keeper_ri_key() {
let pre = "EBfxc1UdwEMYy_g8Ldekf-aQEzBSkb3A5-vASBrV0qs4";
let ri = 0;
assert_eq!(
Keeper::ri_key(pre, ri),
"EBfxc1UdwEMYy_g8Ldekf-aQEzBSkb3A5-vASBrV0qs4.00000000000000000000000000000000"
);
let ri = 1;
assert_eq!(
Keeper::ri_key(pre, ri),
"EBfxc1UdwEMYy_g8Ldekf-aQEzBSkb3A5-vASBrV0qs4.00000000000000000000000000000001"
);
}
}