use crate::{Error, Result};
pub trait KnowledgeBase: Sync + Send + dyn_clone::DynClone + 'static
{
fn insert_data(&self, collection: String, key: String, data: Vec<u8>) -> Result<()>;
fn retrieve_data(&self, collection: String, key: String) -> Result<Vec<u8>>;
}
dyn_clone::clone_trait_object!(KnowledgeBase);
pub trait KnowledgeBaseInterface: KnowledgeBase
{
fn insert(
&self,
collection: impl Into<String>,
key: impl Into<String>,
data: &impl serde::Serialize,
) -> Result<()>;
fn retrieve<T: serde::de::DeserializeOwned>(
&self,
collection: impl Into<String>,
key: impl Into<String>,
) -> Result<T>;
}
impl<TKnowledgeBase: ?Sized + KnowledgeBase> KnowledgeBaseInterface for TKnowledgeBase
{
fn insert(
&self,
collection: impl Into<String>,
key: impl Into<String>,
data: &impl serde::Serialize,
) -> Result<()>
{
let mut data_u8 = Vec::<u8>::new();
ciborium::into_writer(data, &mut data_u8)?;
self.insert_data(collection.into(), key.into(), data_u8)
}
fn retrieve<T: serde::de::DeserializeOwned>(
&self,
collection: impl Into<String>,
key: impl Into<String>,
) -> Result<T>
{
let data = self.retrieve_data(collection.into(), key.into())?;
ciborium::from_reader::<T, &[u8]>(data.as_ref())
.map_err(|e| Error::DeserializationError(e.to_string()))
}
}
#[derive(Clone)]
pub struct InMemoryBase
{
storage: ccutils::sync::ArcMutex<
std::collections::HashMap<String, std::collections::HashMap<String, Vec<u8>>>,
>,
}
impl Default for InMemoryBase
{
fn default() -> Self
{
Self::new()
}
}
impl InMemoryBase
{
pub fn new() -> Self
{
Self {
storage: Default::default(),
}
}
}
impl KnowledgeBase for InMemoryBase
{
fn insert_data(&self, collection: String, key: String, data: Vec<u8>) -> Result<()>
{
let mut storage = self.storage.lock()?;
if !storage.contains_key(&collection)
{
storage.insert(collection.clone(), Default::default());
}
if let Some(v) = storage.get_mut(&collection)
{
v.insert(key, data);
Ok(())
}
else
{
Err(Error::InvalidCollection(collection))
}
}
fn retrieve_data(&self, collection: String, key: String) -> Result<Vec<u8>>
{
let storage = self.storage.lock()?;
if let Some(v) = storage.get(&collection)
&& let Some(v) = v.get(&key)
{
return Ok(v.to_owned());
}
Err(Error::UnknownValue(collection, key))
}
}