use core::{fmt, iter::FusedIterator, ops::Range};
use crate::{BaoChunk, BlockSize, CHUNK_SIZE, traversal::RangeTraversal};
pub struct VerifiedProof<'a> {
proof: &'a [u8],
root: [u8; 32],
size: u64,
block: BlockSize,
request: Range<u64>,
}
impl<'a> VerifiedProof<'a> {
pub(super) fn new(
proof: &'a [u8],
root: [u8; 32],
size: u64,
block: BlockSize,
request: Range<u64>,
) -> Self {
Self {
proof,
root,
size,
block,
request,
}
}
pub fn root(&self) -> [u8; 32] {
self.root
}
pub fn size(&self) -> u64 {
self.size
}
pub fn block_size(&self) -> BlockSize {
self.block
}
pub fn request(&self) -> Range<u64> {
self.request.clone()
}
pub fn items(&self) -> ProofItems<'a> {
ProofItems {
proof: self.proof,
cursor: 8,
traversal: RangeTraversal::new(self.size, self.block, self.request.clone())
.expect("sealed geometry"),
}
}
}
pub enum ProofItem<'a> {
Parent,
Leaf {
file_offset: u64,
proof_offset: usize,
bytes: &'a [u8],
},
}
pub struct ProofItems<'a> {
proof: &'a [u8],
cursor: usize,
traversal: RangeTraversal,
}
impl ProofItems<'_> {
pub fn is_complete(&self) -> bool {
self.traversal.is_complete()
}
}
impl<'a> Iterator for ProofItems<'a> {
type Item = ProofItem<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.traversal.next()? {
BaoChunk::Parent { .. } => {
self.cursor += super::PAIR_BYTES;
Some(ProofItem::Parent)
}
BaoChunk::Leaf {
start_chunk, size, ..
} => {
let proof_offset = self.cursor;
self.cursor += size;
Some(ProofItem::Leaf {
file_offset: start_chunk * CHUNK_SIZE as u64,
proof_offset,
bytes: &self.proof[proof_offset..self.cursor],
})
}
}
}
}
impl FusedIterator for ProofItems<'_> {}
impl fmt::Debug for VerifiedProof<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VerifiedProof")
.field("proof_bytes", &self.proof.len())
.field("root", &self.root)
.field("size", &self.size)
.field("block", &self.block)
.field("request", &self.request)
.finish()
}
}
impl fmt::Debug for ProofItems<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ProofItems")
.field("proof_bytes", &self.proof.len())
.field("cursor", &self.cursor)
.field("complete", &self.is_complete())
.finish()
}
}
impl fmt::Debug for ProofItem<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Parent => f.write_str("Parent"),
Self::Leaf {
file_offset,
proof_offset,
bytes,
} => f
.debug_struct("Leaf")
.field("file_offset", file_offset)
.field("proof_offset", proof_offset)
.field("bytes", &bytes.len())
.finish(),
}
}
}