#![warn(missing_docs)]
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
mod varint;
use std::convert::{TryFrom, TryInto};
use std::io::{self, Error, ErrorKind::Other};
use std::iter::Fuse;
use std::marker::PhantomData;
use std::mem;
use self::varint::{varint_decode32, varint_encode32};
pub type KvWriterU8<W> = KvWriter<W, u8>;
pub type KvWriterU16<W> = KvWriter<W, u16>;
pub type KvWriterU32<W> = KvWriter<W, u32>;
pub type KvWriterU64<W> = KvWriter<W, u64>;
pub type KvReaderU8 = KvReader<u8>;
pub type KvReaderU16 = KvReader<u16>;
pub type KvReaderU32 = KvReader<u32>;
pub type KvReaderU64 = KvReader<u64>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct KvWriter<W, K> {
last_key: Option<K>,
writer: W,
}
impl<K> KvWriter<Vec<u8>, K> {
pub fn memory() -> KvWriter<Vec<u8>, K> {
KvWriter {
last_key: None,
writer: Vec::new(),
}
}
pub fn into_boxed(self) -> Box<KvReader<K>> {
self.writer.into_boxed_slice().into()
}
}
impl<W, K> KvWriter<W, K> {
pub fn new(writer: W) -> KvWriter<W, K> {
KvWriter {
last_key: None,
writer,
}
}
}
impl<W: io::Write, K: Key + PartialOrd> KvWriter<W, K> {
pub fn insert<A: AsRef<[u8]>>(&mut self, key: K, value: A) -> io::Result<()> {
if self.last_key.map_or(false, |last| key <= last) {
return Err(Error::new(
Other,
"keys must be inserted in order and only one time",
));
}
let val = value.as_ref();
let val_len = match val.len().try_into() {
Ok(len) => len,
Err(_) => return Err(Error::new(Other, "value length is bigger than u32 MAX")),
};
let mut buffer = [0; 5];
let len_bytes = varint_encode32(&mut buffer, val_len);
self.writer.write_all(key.to_be_bytes().as_ref())?;
self.writer.write_all(len_bytes)?;
self.writer.write_all(val)?;
self.last_key = Some(key);
Ok(())
}
pub fn extend<I, V>(&mut self, iter: I) -> io::Result<()>
where
I: IntoIterator<Item = (K, V)>,
V: AsRef<[u8]>,
{
for (k, v) in iter {
self.insert(k, v)?;
}
Ok(())
}
pub fn is_empty(&self) -> bool {
self.last_key.is_none()
}
pub fn into_inner(mut self) -> io::Result<W> {
self.writer.flush()?;
Ok(self.writer)
}
pub fn finish(self) -> io::Result<()> {
self.into_inner().map(drop)
}
}
impl<K: Key + PartialOrd> KvWriter<Vec<u8>, K> {
pub fn reserved_insert<F>(
&mut self,
key: K,
val_length: u32,
val_serialize: F,
) -> io::Result<()>
where
F: FnOnce(&mut [u8]) -> io::Result<()>,
{
if self.last_key.map_or(false, |last| key <= last) {
return Err(Error::new(
Other,
"keys must be inserted in order and only one time",
));
}
let mut buffer = [0; 5];
let len_bytes = varint_encode32(&mut buffer, val_length);
self.writer.extend_from_slice(key.to_be_bytes().as_ref());
self.writer.extend_from_slice(len_bytes);
let len = self.writer.len();
self.writer.resize(len + val_length as usize, 0);
(val_serialize)(&mut self.writer[len..])?;
self.last_key = Some(key);
Ok(())
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct KvReader<K> {
_phantom: PhantomData<K>,
bytes: [u8],
}
impl<K> KvReader<K> {
pub fn from_slice(bytes: &[u8]) -> &KvReader<K> {
bytes.into()
}
pub fn get(&self, requested_key: K) -> Option<&[u8]>
where
K: Key + PartialOrd,
{
self.iter()
.take_while(|(key, _)| *key <= requested_key)
.find(|(key, _)| *key == requested_key)
.map(|(_, val)| val)
}
pub fn iter(&self) -> Fuse<KvIter<'_, K>>
where
K: Key,
{
KvIter {
_phantom: PhantomData,
offset: 0,
bytes: self.as_bytes(),
}
.fuse()
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn boxed(&self) -> Box<Self> {
self.as_bytes().to_vec().into_boxed_slice().into()
}
}
impl<K> From<Box<[u8]>> for Box<KvReader<K>> {
fn from(boxed_bytes: Box<[u8]>) -> Self {
unsafe { mem::transmute(boxed_bytes) }
}
}
impl<K> From<Box<KvReader<K>>> for Box<[u8]> {
fn from(boxed_bytes: Box<KvReader<K>>) -> Self {
unsafe { mem::transmute(boxed_bytes) }
}
}
impl<'a, K> From<&'a [u8]> for &'a KvReader<K> {
fn from(bytes: &'a [u8]) -> Self {
unsafe { mem::transmute(bytes) }
}
}
impl<'a, K: Key> IntoIterator for &'a KvReader<K> {
type Item = (K, &'a [u8]);
type IntoIter = Fuse<KvIter<'a, K>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct KvIter<'a, K> {
_phantom: PhantomData<K>,
offset: usize,
bytes: &'a [u8],
}
impl<'a, K: Key> Iterator for KvIter<'a, K> {
type Item = (K, &'a [u8]);
fn next(&mut self) -> Option<Self::Item> {
let key = self
.bytes
.get(self.offset..self.offset + K::BYTES_SIZE)
.and_then(|s| s.try_into().ok())
.map(K::from_be_bytes)?;
self.offset += K::BYTES_SIZE;
let val_len = {
let mut val_len = 0;
let bytes = self.bytes.get(self.offset..)?;
self.offset += varint_decode32(bytes, &mut val_len)?;
val_len as usize
};
let val = self.bytes.get(self.offset..self.offset + val_len)?;
self.offset += val_len;
Some((key, val))
}
}
pub trait Key: Copy {
const BYTES_SIZE: usize;
type BYTES: AsRef<[u8]> + for<'a> TryFrom<&'a [u8]>;
fn to_be_bytes(&self) -> Self::BYTES;
fn from_be_bytes(array: Self::BYTES) -> Self;
}
macro_rules! impl_key {
($($t:ty),+) => {
$(impl Key for $t {
const BYTES_SIZE: usize = std::mem::size_of::<$t>();
type BYTES = [u8; Self::BYTES_SIZE];
fn to_be_bytes(&self) -> Self::BYTES {
<$t>::to_be_bytes(*self)
}
fn from_be_bytes(array: Self::BYTES) -> Self {
Self::from_be_bytes(array)
}
})+
};
}
impl_key!(u8, u16, u32, u64);
#[cfg(test)]
mod test {
use crate::{KvReaderU8, KvWriterU8};
fn reinterpret_box_u8_to_kvreader(boxed_bytes: Box<[u8]>) -> Box<KvReaderU8> {
unsafe { std::mem::transmute(boxed_bytes) }
}
#[test]
fn owned_kvreader() {
let mut writer = KvWriterU8::memory();
writer.insert(1, "hello").unwrap();
writer.insert(10, "world").unwrap();
writer.insert(20, "poupoupidoup").unwrap();
let buffer = writer.into_inner().unwrap();
let boxed = buffer.into_boxed_slice();
let _boxed: Box<KvReaderU8> = reinterpret_box_u8_to_kvreader(boxed);
}
}