pub struct ExternalBlockAssignments { /* private fields */ }Expand description
Per-tier block_id tracking with an offset into the sequence.
Maintains an ordered mapping of BlockId → SequenceHash for assigned blocks,
a staging area for blocks whose hashes have been computed but not yet committed,
plus a FIFO queue of block_ids waiting for assignment. Index i in the assigned
map corresponds to sequence position offset + i.
The three-phase lifecycle is:
- Unassigned — block_ids queued for assignment (no hash yet).
- Staged — block_ids paired with their
SequenceHashbut not yet committed. - Assigned — committed
BlockId → SequenceHashpairs in positional order.
Multiple ExternalBlockAssignments instances can operate on the same &[TokenBlock] at
different offsets (multi-tier).
Implementations§
Source§impl ExternalBlockAssignments
impl ExternalBlockAssignments
Sourcepub fn new(offset: usize) -> Self
pub fn new(offset: usize) -> Self
Creates a new ExternalBlockAssignments starting at the given offset.
Sourcepub fn contains(&self, block_id: &BlockId) -> bool
pub fn contains(&self, block_id: &BlockId) -> bool
Checks whether a block_id is known (assigned, staged, or unassigned).
Sourcepub fn get_assigned(&self, index: usize) -> Option<(BlockId, SequenceHash)>
pub fn get_assigned(&self, index: usize) -> Option<(BlockId, SequenceHash)>
Positional access: returns (BlockId, SequenceHash) at the given index
(relative to offset) in the assigned collection.
Sourcepub fn assigned_count(&self) -> usize
pub fn assigned_count(&self) -> usize
Returns the number of assigned blocks.
Sourcepub fn staged_count(&self) -> usize
pub fn staged_count(&self) -> usize
Returns the number of staged blocks.
Sourcepub fn unassigned_count(&self) -> usize
pub fn unassigned_count(&self) -> usize
Returns the number of unassigned (pending) block_ids.
Sourcepub fn get_staged(&self, index: usize) -> Option<(BlockId, SequenceHash)>
pub fn get_staged(&self, index: usize) -> Option<(BlockId, SequenceHash)>
Positional access: returns (BlockId, SequenceHash) at the given index
(relative to the start of staged) in the staged collection.
Sourcepub fn assigned_iter(
&self,
) -> impl Iterator<Item = (BlockId, SequenceHash)> + '_
pub fn assigned_iter( &self, ) -> impl Iterator<Item = (BlockId, SequenceHash)> + '_
Iterates over assigned blocks in positional order, yielding (BlockId, SequenceHash).
Sourcepub fn staged_iter(&self) -> impl Iterator<Item = (BlockId, SequenceHash)> + '_
pub fn staged_iter(&self) -> impl Iterator<Item = (BlockId, SequenceHash)> + '_
Iterates over staged blocks in staging order, yielding (BlockId, SequenceHash).
Sourcepub fn unassigned_iter(&self) -> impl Iterator<Item = BlockId> + '_
pub fn unassigned_iter(&self) -> impl Iterator<Item = BlockId> + '_
Iterates over unassigned block_ids in FIFO order.
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears all assigned, staged, and unassigned blocks, preserving the offset.
Sourcepub fn take_staged(&mut self) -> Vec<(BlockId, SequenceHash)>
pub fn take_staged(&mut self) -> Vec<(BlockId, SequenceHash)>
Takes all staged blocks, returning them as a Vec.
Sourcepub fn next_position(&self) -> usize
pub fn next_position(&self) -> usize
Returns the next sequence position to be assigned:
offset + assigned_count + staged_count.
Sourcepub fn assigned_positions(&self) -> Range<usize>
pub fn assigned_positions(&self) -> Range<usize>
Absolute position range of assigned blocks: offset..offset + assigned_count.
Sourcepub fn staged_positions(&self) -> Range<usize>
pub fn staged_positions(&self) -> Range<usize>
Absolute position range of staged blocks:
offset + assigned_count .. offset + assigned_count + staged_count.
Sourcepub fn get_at_position(&self, abs_pos: usize) -> Option<(BlockId, SequenceHash)>
pub fn get_at_position(&self, abs_pos: usize) -> Option<(BlockId, SequenceHash)>
Get the assigned (BlockId, SequenceHash) at an absolute sequence position.
Returns None if abs_pos is outside assigned_positions().
Sourcepub fn pending_positions(&self) -> Range<usize>
pub fn pending_positions(&self) -> Range<usize>
Absolute position range that pending (unassigned) blocks will occupy once
flushed: next_position()..next_position() + unassigned_count().
Sourcepub fn get_pending_at_position(&self, abs_pos: usize) -> Option<BlockId>
pub fn get_pending_at_position(&self, abs_pos: usize) -> Option<BlockId>
Get the pending BlockId at an absolute sequence position (FIFO order).
Position next_position() maps to the first unassigned block,
next_position() + 1 to the second, etc.
Returns None if abs_pos is outside pending_positions().
Sourcepub fn extend_block_ids(
&mut self,
block_ids: impl IntoIterator<Item = BlockId>,
) -> Result<(), BlockSequenceError>
pub fn extend_block_ids( &mut self, block_ids: impl IntoIterator<Item = BlockId>, ) -> Result<(), BlockSequenceError>
Add new block_ids to the unassigned queue.
block_ids is the full, ordered list of block IDs allocated to this
assignment set. Known IDs (already in assigned, staged, or unassigned) must
form a contiguous prefix and are silently skipped. New IDs are appended to
the unassigned FIFO queue.
This method does not assign blocks — call
assign_pending to pair unassigned IDs with
available sequence blocks.
§Block ID rules
The list is partitioned into a known prefix and a new suffix:
- Known prefix — IDs already present in
assigned,staged, orunassigned. These are silently skipped. They must appear contiguously at the front of the list; interleaving a known ID after an unknown one is anOrderingViolation. - New suffix — IDs not yet seen. These are appended (in order) to the unassigned FIFO queue.
§Algorithm (two-phase, atomic)
- Validate & collect — iterate
block_ids. Known IDs must form a contiguous prefix (skip them). Unknown IDs are collected into a temp buffer. If a known ID appears after an unknown one →OrderingViolationerror. No state is mutated until validation passes. - Commit — push all new IDs to the unassigned queue.
Sourcepub fn extend_assigned(
&mut self,
items: impl IntoIterator<Item = (BlockId, SequenceHash)>,
) -> Result<usize, BlockSequenceError>
pub fn extend_assigned( &mut self, items: impl IntoIterator<Item = (BlockId, SequenceHash)>, ) -> Result<usize, BlockSequenceError>
Inserts pre-matched (BlockId, SequenceHash) pairs directly into the
assigned collection.
This is the entry point for blocks whose hashes are already known (e.g. cache hits). Two-phase atomic: collects all items, validates no duplicate BlockIds across all three collections, then commits to assigned.
Sourcepub fn stage_pending(
&mut self,
sequence_blocks: &[TokenBlock],
) -> Result<Range<usize>, BlockSequenceError>
pub fn stage_pending( &mut self, sequence_blocks: &[TokenBlock], ) -> Result<Range<usize>, BlockSequenceError>
FIFO drain from unassigned into staged, pairing each block_id with the
sequence hash from the corresponding TokenBlock.
Staging starts at sequence_blocks[self.next_position()] and proceeds
forward, consuming one unassigned ID per available block. The loop stops
when either the unassigned queue is empty or there are no more sequence
blocks.
Returns the range of newly staged indices (relative to the start of the staged collection before this call).
Each staged pair is validated: the position embedded in the block’s
kvbm_sequence_hash() must equal the expected sequence index.
A mismatch returns BlockSequenceError::PositionMismatch.
Sourcepub fn commit_staged(&mut self) -> Range<usize>
pub fn commit_staged(&mut self) -> Range<usize>
Moves all staged blocks into assigned (infallible).
Returns the range of newly assigned indices (relative to the start of the assigned collection before this call).
Sourcepub fn assign_pending(
&mut self,
sequence_blocks: &[TokenBlock],
) -> Result<Range<usize>, BlockSequenceError>
pub fn assign_pending( &mut self, sequence_blocks: &[TokenBlock], ) -> Result<Range<usize>, BlockSequenceError>
Drain the unassigned FIFO queue into assigned, pairing each block_id
with the next available TokenBlock starting at next_position().
This is a convenience method equivalent to calling
stage_pending followed by
commit_staged.
Returns the range of newly assigned indices (relative to offset). An empty range means no new assignments were made.