use crate::SequenceHash;
use kvbm_logical::blocks::{BlockMetadata, ImmutableBlock};
#[derive(Debug)]
pub struct BlockHolder<T: BlockMetadata> {
blocks: Vec<ImmutableBlock<T>>,
}
impl<T: BlockMetadata> BlockHolder<T> {
pub fn new(blocks: Vec<ImmutableBlock<T>>) -> Self {
Self { blocks }
}
pub fn empty() -> Self {
Self { blocks: Vec::new() }
}
pub fn blocks(&self) -> &[ImmutableBlock<T>] {
&self.blocks
}
pub fn count(&self) -> usize {
self.blocks.len()
}
pub fn is_empty(&self) -> bool {
self.blocks.is_empty()
}
pub fn extend(&mut self, blocks: impl IntoIterator<Item = ImmutableBlock<T>>) {
self.blocks.extend(blocks);
}
pub fn release(&mut self, hashes: &[SequenceHash]) {
self.blocks.retain(|b| !hashes.contains(&b.sequence_hash()));
}
pub fn retain(&mut self, hashes: &[SequenceHash]) {
self.blocks.retain(|b| hashes.contains(&b.sequence_hash()));
}
pub fn take_all(&mut self) -> Vec<ImmutableBlock<T>> {
std::mem::take(&mut self.blocks)
}
pub fn sequence_hashes(&self) -> Vec<SequenceHash> {
self.blocks.iter().map(|b| b.sequence_hash()).collect()
}
pub fn find(&self, hash: &SequenceHash) -> Option<&ImmutableBlock<T>> {
self.blocks.iter().find(|b| &b.sequence_hash() == hash)
}
pub fn contains(&self, hash: &SequenceHash) -> bool {
self.blocks.iter().any(|b| &b.sequence_hash() == hash)
}
pub fn iter(&self) -> impl Iterator<Item = &ImmutableBlock<T>> {
self.blocks.iter()
}
}
impl<T: BlockMetadata> Default for BlockHolder<T> {
fn default() -> Self {
Self::empty()
}
}
impl<T: BlockMetadata> FromIterator<ImmutableBlock<T>> for BlockHolder<T> {
fn from_iter<I: IntoIterator<Item = ImmutableBlock<T>>>(iter: I) -> Self {
Self::new(iter.into_iter().collect())
}
}
impl<T: BlockMetadata> IntoIterator for BlockHolder<T> {
type Item = ImmutableBlock<T>;
type IntoIter = std::vec::IntoIter<ImmutableBlock<T>>;
fn into_iter(self) -> Self::IntoIter {
self.blocks.into_iter()
}
}
impl<'a, T: BlockMetadata> IntoIterator for &'a BlockHolder<T> {
type Item = &'a ImmutableBlock<T>;
type IntoIter = std::slice::Iter<'a, ImmutableBlock<T>>;
fn into_iter(self) -> Self::IntoIter {
self.blocks.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_holder() {
let holder: BlockHolder<()> = BlockHolder::empty();
assert!(holder.is_empty());
assert_eq!(holder.count(), 0);
}
#[test]
fn test_default_is_empty() {
let holder: BlockHolder<()> = BlockHolder::default();
assert!(holder.is_empty());
}
}