use indexmap::IndexMap;
use crate::BlockId;
pub(crate) struct BlockStore<U, S, A> {
assigned: IndexMap<BlockId, A>,
staged: IndexMap<BlockId, S>,
unassigned: IndexMap<BlockId, U>,
}
impl<U, S, A> BlockStore<U, S, A> {
pub fn new() -> Self {
Self {
assigned: IndexMap::new(),
staged: IndexMap::new(),
unassigned: IndexMap::new(),
}
}
pub fn assigned_count(&self) -> usize {
self.assigned.len()
}
pub fn staged_count(&self) -> usize {
self.staged.len()
}
pub fn unassigned_count(&self) -> usize {
self.unassigned.len()
}
pub fn is_empty(&self) -> bool {
self.assigned.is_empty() && self.staged.is_empty() && self.unassigned.is_empty()
}
pub fn contains(&self, block_id: &BlockId) -> bool {
self.assigned.contains_key(block_id)
|| self.staged.contains_key(block_id)
|| self.unassigned.contains_key(block_id)
}
#[allow(dead_code)]
pub fn contains_assigned(&self, block_id: &BlockId) -> bool {
self.assigned.contains_key(block_id)
}
#[allow(dead_code)]
pub fn contains_staged(&self, block_id: &BlockId) -> bool {
self.staged.contains_key(block_id)
}
#[allow(dead_code)]
pub fn contains_unassigned(&self, block_id: &BlockId) -> bool {
self.unassigned.contains_key(block_id)
}
pub fn get_assigned(&self, index: usize) -> Option<(&BlockId, &A)> {
self.assigned.get_index(index)
}
pub fn get_staged(&self, index: usize) -> Option<(&BlockId, &S)> {
self.staged.get_index(index)
}
pub fn get_unassigned(&self, index: usize) -> Option<(&BlockId, &U)> {
self.unassigned.get_index(index)
}
pub fn assigned_iter(&self) -> impl Iterator<Item = (&BlockId, &A)> {
self.assigned.iter()
}
pub fn staged_iter(&self) -> impl Iterator<Item = (&BlockId, &S)> {
self.staged.iter()
}
pub fn unassigned_iter(&self) -> impl Iterator<Item = (&BlockId, &U)> {
self.unassigned.iter()
}
pub fn shift_unassigned(&mut self) -> Option<(BlockId, U)> {
self.unassigned.shift_remove_index(0)
}
pub fn shift_staged(&mut self) -> Option<(BlockId, S)> {
self.staged.shift_remove_index(0)
}
pub fn pop_unassigned(&mut self) -> Option<(BlockId, U)> {
self.unassigned.pop()
}
pub fn insert_assigned(&mut self, id: BlockId, val: A) {
self.assigned.insert(id, val);
}
pub fn insert_staged(&mut self, id: BlockId, val: S) {
self.staged.insert(id, val);
}
pub fn insert_unassigned(&mut self, id: BlockId, val: U) {
self.unassigned.insert(id, val);
}
pub fn all_block_ids(&self) -> impl Iterator<Item = &BlockId> {
self.assigned
.keys()
.chain(self.staged.keys())
.chain(self.unassigned.keys())
}
pub fn validate_no_duplicates(
&self,
ids: impl Iterator<Item = BlockId>,
count_hint: usize,
) -> Result<(), BlockId> {
let mut seen = indexmap::IndexSet::with_capacity(count_hint);
for id in ids {
if self.contains(&id) || !seen.insert(id) {
return Err(id);
}
}
Ok(())
}
pub fn clear(&mut self) {
self.assigned.clear();
self.staged.clear();
self.unassigned.clear();
}
pub fn take_assigned(&mut self) -> Vec<(BlockId, A)> {
std::mem::take(&mut self.assigned).into_iter().collect()
}
pub fn take_staged(&mut self) -> Vec<(BlockId, S)> {
std::mem::take(&mut self.staged).into_iter().collect()
}
pub fn take_unassigned(&mut self) -> Vec<(BlockId, U)> {
std::mem::take(&mut self.unassigned).into_iter().collect()
}
}