@@ -10,6 +10,22 @@ pub struct BlockBuilder {
|
||||
data: Vec<u8>,
|
||||
/// The expected block size.
|
||||
block_size: usize,
|
||||
/// The first key in the block
|
||||
first_key: Vec<u8>,
|
||||
}
|
||||
|
||||
fn compute_overlap(first_key: &[u8], key: &[u8]) -> usize {
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if i >= first_key.len() || i >= key.len() {
|
||||
break;
|
||||
}
|
||||
if first_key[i] != key[i] {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
i
|
||||
}
|
||||
|
||||
impl BlockBuilder {
|
||||
@@ -19,6 +35,7 @@ impl BlockBuilder {
|
||||
offsets: Vec::new(),
|
||||
data: Vec::new(),
|
||||
block_size,
|
||||
first_key: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,14 +55,22 @@ impl BlockBuilder {
|
||||
}
|
||||
// Add the offset of the data into the offset array.
|
||||
self.offsets.push(self.data.len() as u16);
|
||||
let overlap = compute_overlap(&self.first_key, key);
|
||||
// Encode key overlap.
|
||||
self.data.put_u16(overlap as u16);
|
||||
// Encode key length.
|
||||
self.data.put_u16(key.len() as u16);
|
||||
self.data.put_u16((key.len() - overlap) as u16);
|
||||
// Encode key content.
|
||||
self.data.put(key);
|
||||
self.data.put(&key[overlap..]);
|
||||
// Encode value length.
|
||||
self.data.put_u16(value.len() as u16);
|
||||
// Encode value content.
|
||||
self.data.put(value);
|
||||
|
||||
if self.first_key.is_empty() {
|
||||
self.first_key = key.to_vec();
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::sync::Arc;
|
||||
|
||||
use bytes::Buf;
|
||||
|
||||
use crate::block::SIZEOF_U16;
|
||||
|
||||
use super::Block;
|
||||
|
||||
/// Iterates on a block.
|
||||
@@ -10,18 +12,31 @@ pub struct BlockIterator {
|
||||
block: Arc<Block>,
|
||||
/// the current key at the iterator position
|
||||
key: Vec<u8>,
|
||||
/// the current value at the iterator position
|
||||
value: Vec<u8>,
|
||||
/// the value range from the block
|
||||
value_range: (usize, usize),
|
||||
/// the current index at the iterator position
|
||||
idx: usize,
|
||||
/// the first key in the block
|
||||
first_key: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
fn get_first_key(&self) -> Vec<u8> {
|
||||
let mut buf = &self.data[..];
|
||||
buf.get_u16();
|
||||
let key_len = buf.get_u16();
|
||||
let key = &buf[..key_len as usize];
|
||||
key.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockIterator {
|
||||
fn new(block: Arc<Block>) -> Self {
|
||||
Self {
|
||||
first_key: block.get_first_key(),
|
||||
block,
|
||||
key: Vec::new(),
|
||||
value: Vec::new(),
|
||||
value_range: (0, 0),
|
||||
idx: 0,
|
||||
}
|
||||
}
|
||||
@@ -49,7 +64,7 @@ impl BlockIterator {
|
||||
/// Returns the value of the current entry.
|
||||
pub fn value(&self) -> &[u8] {
|
||||
debug_assert!(!self.key.is_empty(), "invalid iterator");
|
||||
&self.value
|
||||
&self.block.data[self.value_range.0..self.value_range.1]
|
||||
}
|
||||
|
||||
/// Returns true if the iterator is valid.
|
||||
@@ -66,7 +81,7 @@ impl BlockIterator {
|
||||
fn seek_to(&mut self, idx: usize) {
|
||||
if idx >= self.block.offsets.len() {
|
||||
self.key.clear();
|
||||
self.value.clear();
|
||||
self.value_range = (0, 0);
|
||||
return;
|
||||
}
|
||||
let offset = self.block.offsets[idx] as usize;
|
||||
@@ -86,16 +101,18 @@ impl BlockIterator {
|
||||
let mut entry = &self.block.data[offset..];
|
||||
// Since `get_u16()` will automatically move the ptr 2 bytes ahead here,
|
||||
// we don't need to manually advance it
|
||||
let overlap_len = entry.get_u16() as usize;
|
||||
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(&self.first_key[..overlap_len]);
|
||||
self.key.extend(key);
|
||||
let value_len = entry.get_u16() as usize;
|
||||
let value = entry[..value_len].to_vec();
|
||||
let value_offset_begin = offset + SIZEOF_U16 + SIZEOF_U16 + key_len + SIZEOF_U16;
|
||||
let value_offset_end = value_offset_begin + value_len;
|
||||
self.value_range = (value_offset_begin, value_offset_end);
|
||||
entry.advance(value_len);
|
||||
self.value.clear();
|
||||
self.value.extend(value);
|
||||
}
|
||||
|
||||
/// Seek to the first key that is >= `key`.
|
||||
|
||||
Reference in New Issue
Block a user