use std::marker;
use crate::core::hash::Hash;
use crate::core::pmmr::pmmr::{bintree_rightmost, ReadablePMMR};
use crate::core::pmmr::{is_leaf, Backend};
use crate::ser::PMMRable;
pub struct ReadonlyPMMR<'a, T, B>
where
T: PMMRable,
B: Backend<T>,
{
size: u64,
backend: &'a B,
_marker: marker::PhantomData<T>,
}
impl<'a, T, B> ReadonlyPMMR<'a, T, B>
where
T: PMMRable,
B: 'a + Backend<T>,
{
pub fn new(backend: &'a B) -> ReadonlyPMMR<'_, T, B> {
ReadonlyPMMR {
backend,
size: 0,
_marker: marker::PhantomData,
}
}
pub fn at(backend: &'a B, size: u64) -> ReadonlyPMMR<'_, T, B> {
ReadonlyPMMR {
backend,
size,
_marker: marker::PhantomData,
}
}
pub fn elements_from_pmmr_index(
&self,
pmmr_index1: u64,
max_count: u64,
max_pmmr_pos1: Option<u64>,
) -> (u64, Vec<T::E>) {
let mut return_vec = vec![];
let size = match max_pmmr_pos1 {
Some(p) => p,
None => self.size,
};
let mut pmmr_index = pmmr_index1.saturating_sub(1);
while return_vec.len() < max_count as usize && pmmr_index < size {
if let Some(t) = self.get_data(pmmr_index) {
return_vec.push(t);
}
pmmr_index += 1;
}
(pmmr_index, return_vec)
}
pub fn get_last_n_insertions(&self, n: u64) -> Vec<(Hash, T::E)> {
let mut return_vec = vec![];
let mut last_leaf = self.size;
while return_vec.len() < n as usize && last_leaf > 0 {
last_leaf = bintree_rightmost(last_leaf - 1);
if let Some(hash) = self.backend.get_hash(last_leaf) {
if let Some(data) = self.backend.get_data(last_leaf) {
return_vec.push((hash, data));
}
}
}
return_vec
}
}
impl<'a, T, B> ReadablePMMR for ReadonlyPMMR<'a, T, B>
where
T: PMMRable,
B: 'a + Backend<T>,
{
type Item = T::E;
fn get_hash(&self, pos0: u64) -> Option<Hash> {
if pos0 >= self.size {
None
} else if is_leaf(pos0) {
self.backend.get_hash(pos0)
} else {
self.backend.get_from_file(pos0)
}
}
fn get_data(&self, pos0: u64) -> Option<Self::Item> {
if pos0 >= self.size {
None
} else if is_leaf(pos0) {
self.backend.get_data(pos0)
} else {
None
}
}
fn get_from_file(&self, pos0: u64) -> Option<Hash> {
if pos0 >= self.size {
None
} else {
self.backend.get_from_file(pos0)
}
}
fn get_peak_from_file(&self, pos0: u64) -> Option<Hash> {
if pos0 >= self.size {
None
} else {
self.backend.get_peak_from_file(pos0)
}
}
fn get_data_from_file(&self, pos0: u64) -> Option<Self::Item> {
if pos0 >= self.size {
None
} else {
self.backend.get_data_from_file(pos0)
}
}
fn unpruned_size(&self) -> u64 {
self.size
}
fn leaf_pos_iter(&self) -> Box<dyn Iterator<Item = u64> + '_> {
self.backend.leaf_pos_iter()
}
fn leaf_idx_iter(&self, from_idx: u64) -> Box<dyn Iterator<Item = u64> + '_> {
self.backend.leaf_idx_iter(from_idx)
}
fn n_unpruned_leaves(&self) -> u64 {
self.backend.n_unpruned_leaves()
}
fn n_unpruned_leaves_to_index(&self, to_index: u64) -> u64 {
self.backend.n_unpruned_leaves_to_index(to_index)
}
}