use crate::{journal::contiguous::Contiguous, mmr::Location};
use std::{future::Future, ops::Range};
pub trait Journal: Sized + Send {
type Context;
type Config;
type Op: Send;
type Error: std::error::Error
+ Send
+ 'static
+ Into<crate::qmdb::Error<crate::merkle::mmr::Family>>;
fn new(
context: Self::Context,
config: Self::Config,
range: Range<Location>,
) -> impl Future<Output = Result<Self, Self::Error>>;
fn resize(&mut self, start: Location) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn sync(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn size(&self) -> impl Future<Output = u64> + Send;
fn append(&mut self, op: Self::Op) -> impl Future<Output = Result<(), Self::Error>> + Send;
}
impl<E, V> Journal for crate::journal::contiguous::variable::Journal<E, V>
where
E: crate::Context,
V: commonware_codec::CodecShared,
{
type Context = E;
type Config = crate::journal::contiguous::variable::Config<V::Cfg>;
type Op = V;
type Error = crate::journal::Error;
async fn new(
context: Self::Context,
config: Self::Config,
range: Range<Location>,
) -> Result<Self, Self::Error> {
Self::init_sync(context, config.clone(), *range.start..*range.end).await
}
async fn resize(&mut self, start: Location) -> Result<(), Self::Error> {
if Contiguous::size(self).await <= start {
self.clear_to_size(*start).await
} else {
self.prune(*start).await.map(|_| ())
}
}
async fn sync(&mut self) -> Result<(), Self::Error> {
Self::sync(self).await
}
async fn size(&self) -> u64 {
Contiguous::size(self).await
}
async fn append(&mut self, op: Self::Op) -> Result<(), Self::Error> {
Self::append(self, &op).await.map(|_| ())
}
}
impl<E, A> Journal for crate::journal::contiguous::fixed::Journal<E, A>
where
E: crate::Context,
A: commonware_codec::CodecFixedShared,
{
type Context = E;
type Config = crate::journal::contiguous::fixed::Config;
type Op = A;
type Error = crate::journal::Error;
async fn new(
context: Self::Context,
config: Self::Config,
range: Range<Location>,
) -> Result<Self, Self::Error> {
assert!(!range.is_empty(), "range must not be empty");
let journal = Self::init(context, config).await?;
let size = Contiguous::size(&journal).await;
if size > *range.end {
return Err(crate::journal::Error::ItemOutOfRange(size));
}
if size <= *range.start {
if *range.start != 0 {
journal.clear_to_size(*range.start).await?;
}
} else {
journal.prune(*range.start).await?;
}
Ok(journal)
}
async fn resize(&mut self, start: Location) -> Result<(), Self::Error> {
if Contiguous::size(self).await <= start {
self.clear_to_size(*start).await
} else {
self.prune(*start).await.map(|_| ())
}
}
async fn sync(&mut self) -> Result<(), Self::Error> {
Self::sync(self).await
}
async fn size(&self) -> u64 {
Contiguous::size(self).await
}
async fn append(&mut self, op: Self::Op) -> Result<(), Self::Error> {
Self::append(self, &op).await.map(|_| ())
}
}