use crate::core::error::Result;
use byteorder::{LittleEndian, WriteBytesExt};
use bytes::{BufMut, Bytes, BytesMut};
pub struct BlockBuilder {
buffer: BytesMut,
offsets: Vec<u32>,
last_key: Option<Bytes>,
max_size: usize,
}
impl BlockBuilder {
pub fn new(max_size: usize) -> Self {
Self {
buffer: BytesMut::with_capacity(max_size),
offsets: Vec::new(),
last_key: None,
max_size,
}
}
pub fn add(&mut self, key: &[u8], value: &[u8]) -> bool {
let entry_size = 4 + key.len() + 4 + value.len();
if !self.is_empty() && self.buffer.len() + entry_size > self.max_size {
return false;
}
self.offsets.push(self.buffer.len() as u32);
self.buffer.put_u32_le(key.len() as u32);
self.buffer.put_slice(key);
self.buffer.put_u32_le(value.len() as u32);
self.buffer.put_slice(value);
self.last_key = Some(Bytes::copy_from_slice(key));
true
}
pub fn is_empty(&self) -> bool {
self.offsets.is_empty()
}
pub fn last_key(&self) -> Option<Bytes> {
self.last_key.clone()
}
pub fn size(&self) -> usize {
self.buffer.len()
}
pub fn finish(&mut self) -> Vec<u8> {
let mut result = Vec::with_capacity(self.buffer.len() + self.offsets.len() * 4 + 4);
result.extend_from_slice(&self.buffer);
for offset in &self.offsets {
result.write_u32::<LittleEndian>(*offset).unwrap();
}
result
.write_u32::<LittleEndian>(self.offsets.len() as u32)
.unwrap();
self.buffer.clear();
self.offsets.clear();
self.last_key = None;
result
}
}
pub struct IndexBuilder {
entries: Vec<IndexEntry>,
pending_key: Option<Bytes>,
}
#[derive(Debug, Clone)]
pub(crate) struct IndexEntry {
pub(crate) last_key: Bytes,
pub(crate) block_offset: u64,
pub(crate) block_size: u32,
}
impl IndexBuilder {
pub fn new() -> Self {
Self {
entries: Vec::new(),
pending_key: None,
}
}
pub fn set_pending_key(&mut self, key: &[u8]) {
self.pending_key = Some(Bytes::copy_from_slice(key));
}
pub fn has_pending_key(&self) -> bool {
self.pending_key.is_some()
}
pub fn add(&mut self, last_key: &[u8], block_offset: u64, block_size: u32) -> Result<()> {
self.entries.push(IndexEntry {
last_key: Bytes::copy_from_slice(last_key),
block_offset,
block_size,
});
self.pending_key = None;
Ok(())
}
pub fn finish(&mut self) -> Vec<u8> {
let mut buffer = Vec::new();
for entry in &self.entries {
buffer
.write_u32::<LittleEndian>(entry.last_key.len() as u32)
.unwrap();
buffer.extend_from_slice(&entry.last_key);
buffer
.write_u64::<LittleEndian>(entry.block_offset)
.unwrap();
buffer.write_u32::<LittleEndian>(entry.block_size).unwrap();
}
buffer
.write_u32::<LittleEndian>(self.entries.len() as u32)
.unwrap();
buffer
}
pub(crate) fn entries(&self) -> &[IndexEntry] {
&self.entries
}
}