use crate::KvbmSequenceHashProvider;
use super::{Block, BlockError, BlockId, BlockMetadata};
use crate::registry::BlockRegistrationHandle;
use super::{SequenceHash, TokenBlock};
use std::marker::PhantomData;
#[derive(Debug)]
pub struct Reset;
#[derive(Debug)]
pub struct Staged {
sequence_hash: SequenceHash,
}
#[derive(Debug)]
pub struct Registered {
sequence_hash: SequenceHash,
registration_handle: BlockRegistrationHandle,
}
impl<T> Block<T, Reset> {
pub fn new(block_id: BlockId, block_size: usize) -> Self {
Self {
block_id,
block_size,
state: Reset,
marker: PhantomData,
}
}
pub fn complete(
self,
token_block: &TokenBlock,
) -> Result<Block<T, Staged>, BlockError<Block<T, Reset>>> {
if token_block.block_size() != self.block_size {
return Err(BlockError::BlockSizeMismatch {
expected: self.block_size,
actual: token_block.block_size(),
block: self, });
}
Ok(self.stage(token_block.kvbm_sequence_hash()))
}
pub fn stage(self, sequence_hash: SequenceHash) -> Block<T, Staged> {
Block {
block_id: self.block_id,
block_size: self.block_size,
state: Staged { sequence_hash },
marker: PhantomData,
}
}
}
impl<T: BlockMetadata> Block<T, Staged> {
pub(crate) fn register_with_handle(
self,
registration_handle: BlockRegistrationHandle,
) -> Block<T, Registered> {
into_registered(self.block_id, self.block_size, registration_handle)
}
pub fn sequence_hash(&self) -> SequenceHash {
self.state.sequence_hash
}
pub fn reset(self) -> Block<T, Reset> {
Block {
block_id: self.block_id,
block_size: self.block_size,
state: Reset,
marker: PhantomData,
}
}
}
fn into_registered<T: BlockMetadata>(
block_id: BlockId,
block_size: usize,
registration_handle: BlockRegistrationHandle,
) -> Block<T, Registered> {
registration_handle.mark_present::<T>();
Block {
block_id,
block_size,
state: Registered {
sequence_hash: registration_handle.seq_hash(),
registration_handle,
},
marker: PhantomData,
}
}
impl<T: BlockMetadata> Block<T, Registered> {
pub fn sequence_hash(&self) -> SequenceHash {
self.state.sequence_hash
}
pub(crate) fn registration_handle(&self) -> &BlockRegistrationHandle {
&self.state.registration_handle
}
pub fn reset(self) -> Block<T, Reset> {
self.state.registration_handle.mark_absent::<T>();
Block {
block_id: self.block_id,
block_size: self.block_size,
state: Reset,
marker: PhantomData,
}
}
}
impl<T, State> Block<T, State> {
#[inline]
pub fn block_id(&self) -> BlockId {
self.block_id
}
#[inline]
pub fn block_size(&self) -> usize {
self.block_size
}
}