use std::collections::{HashMap};
use maybe_owned::MaybeOwned;
use std::fmt::Debug;
use serde::{Serialize,Deserialize};
pub use crate::base::*;
#[derive(Debug)]
pub struct InMemoryLog<T> {
data: Vec<T>,
hashes: Vec<Vec<String>>,
}
impl <T> Default for InMemoryLog<T>{
fn default() -> Self {
Self{data:Default::default(),hashes:Default::default()}
}
}
impl <'a, T: Serialize+Deserialize<'a>> TransparentLog<'a, T> for InMemoryLog<T> {
type LogSize = usize;
fn size(&self) -> anyhow::Result<Self::LogSize> {
Ok(self.data.len())
}
fn get(&self, index: Self::LogSize) ->anyhow::Result<Option<MaybeOwned<T>>> {
Ok(self.data.get(index).map(|t| t.into()))
}
fn add(&mut self, record: T) -> anyhow::Result<Self::LogSize> {
let id=self.data.len();
self.data.push(record);
Ok(id)
}
fn add_hash(&mut self,level: LogHeight, hash: String) -> anyhow::Result<Self::LogSize> {
if self.hashes.len()<=level{
self.hashes.push(vec![]);
}
let v= self.hashes.get_mut(level).unwrap();
v.push(hash);
Ok(v.len()-1)
}
fn get_hash(&self, level: LogHeight, index: Self::LogSize) -> anyhow::Result<MaybeOwned<String>> {
Ok(self.hashes.get(level).unwrap().get(index).unwrap().into())
}
}
pub struct InMemoryLogClient<'a, T: Serialize+Deserialize<'a>,TL: TransparentLog<'a, T>> {
latest: LogTree<TL::LogSize>,
cache: Option<HashMap<LogTreePosition<TL::LogSize>,String>>,
}
pub struct InMemoryLogClientBuilder<'a, T: Serialize+Deserialize<'a>,TL: TransparentLog<'a, T>>{
latest: LogTree<TL::LogSize>,
cache: bool,
}
impl <'a, T: Serialize+Deserialize<'a>,TL: TransparentLog<'a, T>> InMemoryLogClientBuilder<'a, T,TL>{
pub fn new(log: &TL) -> anyhow::Result<Self> {
let latest=log.latest()?;
Ok(Self {
latest,
cache: true,
})
}
pub fn open(latest: LogTree<TL::LogSize>) -> Self {
Self{latest,cache: true,}
}
pub fn no_cache<>(&mut self) -> &mut Self {
self.cache=false;
self
}
pub fn build(&self) -> InMemoryLogClient<'a, T,TL>{
InMemoryLogClient{latest:LogTree{size:self.latest.size,hash:self.latest.hash.clone()},
cache:if self.cache{
Some(HashMap::new())
} else {
None
}}
}
}
impl <'a, T: Serialize+Deserialize<'a>,TL: TransparentLog<'a, T>> LogClient<'a, T,TL> for InMemoryLogClient<'a, T,TL> {
fn latest(&self) -> &LogTree<TL::LogSize> {
&self.latest
}
fn set_latest(&mut self, latest: LogTree<TL::LogSize>) {
self.latest=latest
}
fn cached(&self, position: &LogTreePosition<TL::LogSize>) -> Option<String> {
if let Some(m) = &self.cache {
return m.get(position).cloned()
}
None
}
fn add_cached(&mut self, proofs: &HashMap<LogTreePosition<TL::LogSize>,String>) {
if let Some(m) = self.cache.as_mut() {
m.extend(proofs.clone());
}
}
}
#[cfg(test)]
mod tests {
use crate::test_helpers::*;
use crate::{InMemoryLog, InMemoryLogClientBuilder};
#[test]
fn memory_empty() -> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
empty(&mut ml)
}
#[test]
fn memory_add()-> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
add(&mut ml)
}
#[test]
fn memory_13()-> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
test_13(&mut ml)
}
#[test]
fn client_memory_13()-> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
let mut client= InMemoryLogClientBuilder::new(&ml)?.build();
client_13(&mut ml, &mut client)
}
#[test]
fn client_memory_13_no_cache()-> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
let mut client= InMemoryLogClientBuilder::new(&ml)?.no_cache().build();
client_13_nocache(&mut ml, &mut client)
}
#[test]
fn memory_verify_tree_prefix()-> anyhow::Result<()>{
let mut ml: InMemoryLog<LogRecord>=InMemoryLog::default();
test_verify_tree_prefix(&mut ml)
}
}