use std::collections::BTreeSet;
use incrementalmerkletree::{Address, Position};
use crate::{LocatedPrunableTree, PrunableTree};
pub mod caching;
pub mod memory;
pub trait ShardStore {
type H;
type CheckpointId;
type Error: std::error::Error;
fn get_shard(
&self,
shard_root: Address,
) -> Result<Option<LocatedPrunableTree<Self::H>>, Self::Error>;
fn last_shard(&self) -> Result<Option<LocatedPrunableTree<Self::H>>, Self::Error>;
fn put_shard(&mut self, subtree: LocatedPrunableTree<Self::H>) -> Result<(), Self::Error>;
fn get_shard_roots(&self) -> Result<Vec<Address>, Self::Error>;
fn truncate_shards(&mut self, shard_index: u64) -> Result<(), Self::Error>;
fn get_cap(&self) -> Result<PrunableTree<Self::H>, Self::Error>;
fn put_cap(&mut self, cap: PrunableTree<Self::H>) -> Result<(), Self::Error>;
fn min_checkpoint_id(&self) -> Result<Option<Self::CheckpointId>, Self::Error>;
fn max_checkpoint_id(&self) -> Result<Option<Self::CheckpointId>, Self::Error>;
fn add_checkpoint(
&mut self,
checkpoint_id: Self::CheckpointId,
checkpoint: Checkpoint,
) -> Result<(), Self::Error>;
fn checkpoint_count(&self) -> Result<usize, Self::Error>;
fn get_checkpoint_at_depth(
&self,
checkpoint_depth: usize,
) -> Result<Option<(Self::CheckpointId, Checkpoint)>, Self::Error>;
fn get_checkpoint(
&self,
checkpoint_id: &Self::CheckpointId,
) -> Result<Option<Checkpoint>, Self::Error>;
fn with_checkpoints<F>(&mut self, limit: usize, callback: F) -> Result<(), Self::Error>
where
F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>;
fn for_each_checkpoint<F>(&self, limit: usize, callback: F) -> Result<(), Self::Error>
where
F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>;
fn update_checkpoint_with<F>(
&mut self,
checkpoint_id: &Self::CheckpointId,
update: F,
) -> Result<bool, Self::Error>
where
F: Fn(&mut Checkpoint) -> Result<(), Self::Error>;
fn remove_checkpoint(&mut self, checkpoint_id: &Self::CheckpointId) -> Result<(), Self::Error>;
fn truncate_checkpoints_retaining(
&mut self,
checkpoint_id: &Self::CheckpointId,
) -> Result<(), Self::Error>;
}
impl<S: ShardStore> ShardStore for &mut S {
type H = S::H;
type CheckpointId = S::CheckpointId;
type Error = S::Error;
fn get_shard(
&self,
shard_root: Address,
) -> Result<Option<LocatedPrunableTree<Self::H>>, Self::Error> {
S::get_shard(*self, shard_root)
}
fn last_shard(&self) -> Result<Option<LocatedPrunableTree<Self::H>>, Self::Error> {
S::last_shard(*self)
}
fn put_shard(&mut self, subtree: LocatedPrunableTree<Self::H>) -> Result<(), Self::Error> {
S::put_shard(*self, subtree)
}
fn get_shard_roots(&self) -> Result<Vec<Address>, Self::Error> {
S::get_shard_roots(*self)
}
fn get_cap(&self) -> Result<PrunableTree<Self::H>, Self::Error> {
S::get_cap(*self)
}
fn put_cap(&mut self, cap: PrunableTree<Self::H>) -> Result<(), Self::Error> {
S::put_cap(*self, cap)
}
fn truncate_shards(&mut self, shard_index: u64) -> Result<(), Self::Error> {
S::truncate_shards(*self, shard_index)
}
fn min_checkpoint_id(&self) -> Result<Option<Self::CheckpointId>, Self::Error> {
S::min_checkpoint_id(self)
}
fn max_checkpoint_id(&self) -> Result<Option<Self::CheckpointId>, Self::Error> {
S::max_checkpoint_id(self)
}
fn add_checkpoint(
&mut self,
checkpoint_id: Self::CheckpointId,
checkpoint: Checkpoint,
) -> Result<(), Self::Error> {
S::add_checkpoint(self, checkpoint_id, checkpoint)
}
fn checkpoint_count(&self) -> Result<usize, Self::Error> {
S::checkpoint_count(self)
}
fn get_checkpoint_at_depth(
&self,
checkpoint_depth: usize,
) -> Result<Option<(Self::CheckpointId, Checkpoint)>, Self::Error> {
S::get_checkpoint_at_depth(self, checkpoint_depth)
}
fn get_checkpoint(
&self,
checkpoint_id: &Self::CheckpointId,
) -> Result<Option<Checkpoint>, Self::Error> {
S::get_checkpoint(self, checkpoint_id)
}
fn with_checkpoints<F>(&mut self, limit: usize, callback: F) -> Result<(), Self::Error>
where
F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>,
{
S::with_checkpoints(self, limit, callback)
}
fn for_each_checkpoint<F>(&self, limit: usize, callback: F) -> Result<(), Self::Error>
where
F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>,
{
S::for_each_checkpoint(self, limit, callback)
}
fn update_checkpoint_with<F>(
&mut self,
checkpoint_id: &Self::CheckpointId,
update: F,
) -> Result<bool, Self::Error>
where
F: Fn(&mut Checkpoint) -> Result<(), Self::Error>,
{
S::update_checkpoint_with(self, checkpoint_id, update)
}
fn remove_checkpoint(&mut self, checkpoint_id: &Self::CheckpointId) -> Result<(), Self::Error> {
S::remove_checkpoint(self, checkpoint_id)
}
fn truncate_checkpoints_retaining(
&mut self,
checkpoint_id: &Self::CheckpointId,
) -> Result<(), Self::Error> {
S::truncate_checkpoints_retaining(self, checkpoint_id)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TreeState {
Empty,
AtPosition(Position),
}
#[derive(Clone, Debug)]
pub struct Checkpoint {
tree_state: TreeState,
marks_removed: BTreeSet<Position>,
}
impl Checkpoint {
pub fn tree_empty() -> Self {
Checkpoint {
tree_state: TreeState::Empty,
marks_removed: BTreeSet::new(),
}
}
pub fn at_position(position: Position) -> Self {
Checkpoint {
tree_state: TreeState::AtPosition(position),
marks_removed: BTreeSet::new(),
}
}
pub fn from_parts(tree_state: TreeState, marks_removed: BTreeSet<Position>) -> Self {
Checkpoint {
tree_state,
marks_removed,
}
}
pub fn tree_state(&self) -> TreeState {
self.tree_state
}
pub fn marks_removed(&self) -> &BTreeSet<Position> {
&self.marks_removed
}
pub fn is_tree_empty(&self) -> bool {
matches!(self.tree_state, TreeState::Empty)
}
pub fn position(&self) -> Option<Position> {
match self.tree_state {
TreeState::Empty => None,
TreeState::AtPosition(pos) => Some(pos),
}
}
pub(crate) fn mark_removed(&mut self, position: Position) {
self.marks_removed.insert(position);
}
}