use std::sync::Arc; use bytes::Buf; use super::Block; pub struct BlockIterator { block: Arc, key: Vec, value: Vec, idx: usize, } impl BlockIterator { fn new(block: Arc) -> Self { Self { block, key: Vec::new(), value: Vec::new(), idx: 0, } } pub fn create_and_seek_to_first(block: Arc) -> Self { let mut iter = Self::new(block); iter.seek_to_first(); iter } pub fn create_and_seek_to_key(block: Arc, key: &[u8]) -> Self { let mut iter = Self::new(block); iter.seek_to_key(key); iter } pub fn key(&self) -> &[u8] { debug_assert!(!self.key.is_empty(), "invalid iterator"); &self.key } pub fn value(&self) -> &[u8] { debug_assert!(!self.key.is_empty(), "invalid iterator"); &self.value } pub fn is_valid(&self) -> bool { !self.key.is_empty() } pub fn seek_to_first(&mut self) { self.seek_to(0); } pub fn len(&self) -> usize { self.block.offsets.len() } pub fn is_empty(&self) -> bool { self.block.offsets.is_empty() } pub fn seek_to(&mut self, idx: usize) { if idx >= self.block.offsets.len() { self.key.clear(); self.value.clear(); return; } let offset = self.block.offsets[idx] as usize; self.seek_to_offset(offset); self.idx = idx; } pub fn next(&mut self) { self.idx += 1; self.seek_to(self.idx); } fn seek_to_offset(&mut self, offset: usize) { let mut entry = &self.block.data[offset..]; let key_len = entry.get_u16() as usize; let key = entry[..key_len].to_vec(); entry.advance(key_len); self.key.clear(); self.key.extend(key); let value_len = entry.get_u16() as usize; let value = entry[..value_len].to_vec(); entry.advance(value_len); self.value.clear(); self.value.extend(value); } pub fn seek_to_key(&mut self, key: &[u8]) { let mut low = 0; let mut high = self.block.offsets.len(); while low < high { let mid = low + (high - low) / 2; self.seek_to(mid); assert!(self.is_valid()); match self.key().cmp(key) { std::cmp::Ordering::Less => low = mid + 1, std::cmp::Ordering::Greater => high = mid, std::cmp::Ordering::Equal => return, } } self.seek_to(low); } }