use crate::comparator::SharedComparator;
use crate::table::block::{BlockType, Decoder, DecoderMeta, ParsedItem};
use crate::table::block_index::{BlockIndexIter, iter::OwnedIndexBlockIter};
use crate::table::index_block::IndexBlockParsedItem;
use crate::table::{IndexBlock, KeyedBlockHandle};
use crate::{SeqNo, Slice};
fn seek_index_block(
decoder: &mut Decoder<'_, KeyedBlockHandle, IndexBlockParsedItem>,
needle: &[u8],
seqno: SeqNo,
comparator: &SharedComparator,
) -> bool {
let landed = if comparator.is_lexicographic() {
decoder.seek(
|end_key, s| match end_key.cmp(needle) {
core::cmp::Ordering::Greater => false,
core::cmp::Ordering::Less => true,
core::cmp::Ordering::Equal => s >= seqno,
},
true,
)
} else {
decoder.seek(
|end_key, s| match comparator.compare(end_key, needle) {
core::cmp::Ordering::Greater => false,
core::cmp::Ordering::Less => true,
core::cmp::Ordering::Equal => s >= seqno,
},
true,
)
};
if !landed {
return false;
}
if decoder.restart_interval() > 1 {
decoder.advance_while(|item, bytes| {
match item.compare_key(needle, bytes, comparator.as_ref()) {
core::cmp::Ordering::Greater => false,
core::cmp::Ordering::Less => true,
core::cmp::Ordering::Equal => item.seqno() >= seqno,
}
});
}
true
}
pub struct FullBlockIndex {
block: IndexBlock,
comparator: SharedComparator,
meta: DecoderMeta,
}
impl FullBlockIndex {
pub fn new(block: IndexBlock, comparator: SharedComparator) -> crate::Result<Self> {
if block.inner.header.block_type != BlockType::Index {
return Err(crate::Error::InvalidTag((
"BlockType",
block.inner.header.block_type.into(),
)));
}
let meta = Decoder::<KeyedBlockHandle, IndexBlockParsedItem>::try_new(&block.inner)?.meta();
Ok(Self {
block,
comparator,
meta,
})
}
pub fn inner(&self) -> &IndexBlock {
&self.block
}
pub fn point_read_reader(&self, needle: &[u8], seqno: SeqNo) -> Option<PointReadIter<'_>> {
let mut decoder = Decoder::<KeyedBlockHandle, IndexBlockParsedItem>::from_meta(
&self.block.inner,
self.meta,
);
if seek_index_block(&mut decoder, needle, seqno, &self.comparator) {
Some(PointReadIter {
decoder,
data: &self.block.inner.data,
})
} else {
None
}
}
pub fn forward_reader(&self, needle: &[u8], seqno: SeqNo) -> Option<Iter> {
let mut it = self.iter();
if it.seek_lower(needle, seqno) {
Some(it)
} else {
None
}
}
pub fn iter(&self) -> Iter {
Iter(OwnedIndexBlockIter::from_validated_block(
self.block.clone(),
self.comparator.clone(),
))
}
}
pub struct PointReadIter<'a> {
decoder: Decoder<'a, KeyedBlockHandle, IndexBlockParsedItem>,
data: &'a Slice,
}
impl Iterator for PointReadIter<'_> {
type Item = crate::Result<KeyedBlockHandle>;
fn next(&mut self) -> Option<Self::Item> {
self.decoder
.next()
.map(|item| Ok(item.materialize(self.data)))
}
}
pub struct Iter(OwnedIndexBlockIter);
impl BlockIndexIter for Iter {
fn seek_lower(&mut self, key: &[u8], seqno: SeqNo) -> bool {
self.0.seek_lower(key, seqno)
}
fn seek_upper(&mut self, key: &[u8], seqno: SeqNo) -> bool {
self.0.seek_upper(key, seqno)
}
}
impl Iterator for Iter {
type Item = crate::Result<KeyedBlockHandle>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(Ok)
}
}
impl DoubleEndedIterator for Iter {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(Ok)
}
}