use std::ops::Bound; use anyhow::Result; use bytes::Bytes; use crate::iterators::impls::StorageIterator; use crate::iterators::merge_iterator::MergeIterator; use crate::iterators::two_merge_iterator::TwoMergeIterator; use crate::mem_table::MemTableIterator; use crate::table::SsTableIterator; type LsmIteratorInner = TwoMergeIterator, MergeIterator>; pub struct LsmIterator { iter: LsmIteratorInner, end_bound: Bound, is_valid: bool, } impl LsmIterator { pub(crate) fn new(iter: LsmIteratorInner, end_bound: Bound) -> Result { let mut iter = Self { is_valid: iter.is_valid(), iter, end_bound, }; iter.move_to_non_delete()?; Ok(iter) } fn next_inner(&mut self) -> Result<()> { self.iter.next()?; if !self.iter.is_valid() { self.is_valid = false; return Ok(()); } match self.end_bound.as_ref() { Bound::Unbounded => {} Bound::Included(key) => self.is_valid = self.iter.key() <= key.as_ref(), Bound::Excluded(key) => self.is_valid = self.iter.key() < key.as_ref(), } Ok(()) } fn move_to_non_delete(&mut self) -> Result<()> { while self.is_valid() && self.iter.value().is_empty() { self.next_inner()?; } Ok(()) } } impl StorageIterator for LsmIterator { fn is_valid(&self) -> bool { self.is_valid } fn key(&self) -> &[u8] { self.iter.key() } fn value(&self) -> &[u8] { self.iter.value() } fn next(&mut self) -> Result<()> { self.next_inner()?; self.move_to_non_delete()?; Ok(()) } } /// A wrapper around existing iterator, will prevent users from calling `next` when the iterator is /// invalid. pub struct FusedIterator { iter: I, } impl FusedIterator { pub fn new(iter: I) -> Self { Self { iter } } } impl StorageIterator for FusedIterator { fn is_valid(&self) -> bool { self.iter.is_valid() } fn key(&self) -> &[u8] { self.iter.key() } fn value(&self) -> &[u8] { self.iter.value() } fn next(&mut self) -> Result<()> { // only move when the iterator is valid if self.iter.is_valid() { self.iter.next()?; } Ok(()) } }