use crate::{Appender, Error};
use std::{mem::size_of, path::PathBuf};
pub(crate) struct SeqNoIndex {
inner: Appender,
}
impl SeqNoIndex {
pub fn new(path: Option<PathBuf>) -> Result<Self, Error> {
Appender::new(path).map(|inner| Self { inner })
}
pub fn append(&self, records: &[u64]) -> Result<(), Error> {
if records.is_empty() {
return Ok(());
}
let size_inc: usize = records.len() * size_of::<u64>();
self.inner.append(size_inc, move |mut mmap| {
for record in records {
mmap[..size_of::<u64>()].copy_from_slice(&record.to_le_bytes()[..]);
mmap = &mut mmap[size_of::<u64>()..];
}
})
}
pub fn get_pointer_to_value(&self, seqno: usize) -> Option<u64> {
let offset = seqno * size_of::<u64>();
self.inner.get_data(offset, |mmap| {
let mut key_length_bytes = [0u8; size_of::<u64>()];
key_length_bytes.copy_from_slice(&mmap.as_ref()[..size_of::<u64>()]);
Some(u64::from_le_bytes(key_length_bytes))
})
}
}
#[cfg(test)]
mod tests {
use super::SeqNoIndex;
#[quickcheck]
fn test_read_write(records: Vec<u64>) {
if records.is_empty() {
return;
}
let tmp = tempfile::NamedTempFile::new().unwrap();
let index = SeqNoIndex::new(Some(tmp.path().to_path_buf())).unwrap();
index.append(&records).unwrap();
for (i, record) in records.iter().enumerate() {
let drive_record = index.get_pointer_to_value(i).unwrap();
assert_eq!(*record, drive_record);
}
}
}