use crate::storage_engine::constants::*;
use crate::storage_engine::digest::*;
use memmap2::Mmap;
use simd_r_drive_entry_handle::{EntryHandle, EntryMetadata};
use std::collections::HashSet;
use std::sync::Arc;
pub struct EntryIterator {
mmap: Arc<Mmap>, cursor: u64,
seen_keys: HashSet<u64, Xxh3BuildHasher>,
}
impl EntryIterator {
pub fn new(mmap: Arc<Mmap>, tail_offset: u64) -> Self {
Self {
mmap,
cursor: tail_offset,
seen_keys: HashSet::with_hasher(Xxh3BuildHasher),
}
}
}
impl Iterator for EntryIterator {
type Item = EntryHandle;
fn next(&mut self) -> Option<Self::Item> {
if self.cursor < METADATA_SIZE as u64 || self.mmap.is_empty() {
return None;
}
let metadata_offset = (self.cursor - METADATA_SIZE as u64) as usize;
let metadata_bytes = &self.mmap[metadata_offset..metadata_offset + METADATA_SIZE];
let metadata = EntryMetadata::deserialize(metadata_bytes);
let entry_start = metadata.prev_offset as usize;
let entry_end = metadata_offset;
if entry_start >= entry_end || entry_end > self.mmap.len() {
return None;
}
self.cursor = metadata.prev_offset;
if !self.seen_keys.insert(metadata.key_hash) {
return self.next(); }
let entry_data = &self.mmap[entry_start..entry_end];
if entry_data == NULL_BYTE {
return self.next();
}
Some(EntryHandle {
mmap_arc: Arc::clone(&self.mmap),
range: entry_start..entry_end,
metadata,
})
}
}