use crate::{
SeqNo,
comparator::SharedComparator,
table::{IndexBlock, KeyedBlockHandle, block::ParsedItem, index_block::Iter as IndexBlockIter},
};
use self_cell::self_cell;
self_cell!(
pub struct OwnedIndexBlockIter {
owner: IndexBlock,
#[covariant]
dependent: IndexBlockIter,
}
);
impl OwnedIndexBlockIter {
pub(crate) fn from_block(
block: IndexBlock,
comparator: SharedComparator,
) -> crate::Result<Self> {
Self::try_new(block, |b| b.try_iter(comparator))
}
pub(crate) fn from_validated_block(block: IndexBlock, comparator: SharedComparator) -> Self {
Self::new(block, |b| b.iter(comparator))
}
pub(crate) fn from_block_with_bounds(
block: IndexBlock,
comparator: SharedComparator,
lo: Option<(&[u8], SeqNo)>,
hi: Option<(&[u8], SeqNo)>,
) -> crate::Result<Option<Self>> {
if let (Some((lo_key, _)), Some((hi_key, _))) = (lo, hi)
&& comparator.compare(lo_key, hi_key) == core::cmp::Ordering::Greater
{
return Ok(None);
}
let mut iter = Self::from_block(block, comparator)?;
if let Some((key, seqno)) = lo
&& !iter.with_dependent_mut(|_, m| m.seek_lower_bound_cursor(key, seqno))?
{
return Ok(None);
}
if let Some((key, seqno)) = hi
&& !iter.with_dependent_mut(|_, m| m.seek_upper_bound_cursor(key, seqno))?
{
return Ok(None);
}
Ok(Some(iter))
}
pub fn seek_lower(&mut self, needle: &[u8], seqno: SeqNo) -> bool {
self.with_dependent_mut(|_, m| m.seek(needle, seqno))
}
pub fn seek_upper(&mut self, needle: &[u8], _seqno: SeqNo) -> bool {
self.with_dependent_mut(|_, m| {
m.seek_upper_impl(needle, false, true, false)
.unwrap_or(false)
})
}
}
impl Iterator for OwnedIndexBlockIter {
type Item = KeyedBlockHandle;
fn next(&mut self) -> Option<Self::Item> {
self.with_dependent_mut(|block, iter| {
iter.next().map(|item| item.materialize(&block.inner.data))
})
}
}
impl DoubleEndedIterator for OwnedIndexBlockIter {
fn next_back(&mut self) -> Option<Self::Item> {
self.with_dependent_mut(|block, iter| {
iter.next_back()
.map(|item| item.materialize(&block.inner.data))
})
}
}
#[cfg(test)]
#[expect(
clippy::unwrap_used,
clippy::doc_markdown,
clippy::cast_possible_truncation,
reason = "test code"
)]
mod tests;