use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use index::config::{IndexType, IndexTypeId};
use index::tree::{Leaf, LeafEntry, Node, Nodes, Value};
use persy::{PRes, PersyError, RecRef};
use std::io::{Cursor, Read, Write};
use std::str;
use PersyId;
macro_rules! impl_index_type {
($t:ident, $v:expr,$v1:expr) => {
impl IndexType for $t {
fn get_id() -> u8 {
$v
}
fn get_type_id() -> IndexTypeId {
$v1
}
}
};
}
impl_index_type!(u8, 1, IndexTypeId::U8);
impl_index_type!(u16, 2, IndexTypeId::U16);
impl_index_type!(u32, 3, IndexTypeId::U32);
impl_index_type!(u64, 4, IndexTypeId::U64);
impl_index_type!(i8, 5, IndexTypeId::I8);
impl_index_type!(i16, 6, IndexTypeId::I16);
impl_index_type!(i32, 7, IndexTypeId::I32);
impl_index_type!(i64, 8, IndexTypeId::I64);
impl_index_type!(String, 12, IndexTypeId::STRING);
impl_index_type!(PersyId, 13, IndexTypeId::PERSYID);
pub trait IndexSerialization: Sized {
fn serialize(&self, buffer: &mut Write) -> PRes<()>;
fn deserialize(value: &mut Read) -> PRes<Self>;
}
pub fn deserialize<K: IndexType, V: IndexType>(value: &[u8]) -> PRes<Node<K, V>> {
let mut reader = Cursor::new(value);
let t = reader.read_u8()?;
match t {
1 => {
let size = reader.read_u32::<BigEndian>()?;
let mut entries = Vec::with_capacity(size as usize);
for _ in 0..size {
let key = K::deserialize(&mut reader)?;
let value_type = reader.read_u8()?;
if value_type == 1 {
let val_size = reader.read_u32::<BigEndian>()?;
let mut value = Vec::with_capacity(val_size as usize);
for _ in 0..val_size {
value.push(V::deserialize(&mut reader)?);
}
entries.push(LeafEntry {
key,
value: Value::CLUSTER(value),
});
} else {
let value = V::deserialize(&mut reader)?;
entries.push(LeafEntry {
key,
value: Value::SINGLE(value),
});
}
}
let page = reader.read_u64::<BigEndian>()?;
let pos = reader.read_u32::<BigEndian>()?;
let prev = if page == 0 && pos == 0 {
None
} else {
Some(RecRef::new(page, pos))
};
let page = reader.read_u64::<BigEndian>()?;
let pos = reader.read_u32::<BigEndian>()?;
let next = if page == 0 && pos == 0 {
None
} else {
Some(RecRef::new(page, pos))
};
Ok(Node::LEAF(Leaf { entries, prev, next }))
}
2 => {
let size = reader.read_u32::<BigEndian>()?;
let mut keys = Vec::with_capacity(size as usize);
for _ in 0..size {
let key = K::deserialize(&mut reader)?;
keys.push(key);
}
let size = reader.read_u32::<BigEndian>()?;
let mut pointers = Vec::with_capacity(size as usize);
for _ in 0..size {
let page = reader.read_u64::<BigEndian>()?;
let pos = reader.read_u32::<BigEndian>()?;
pointers.push(RecRef::new(page, pos));
}
Ok(Node::NODE(Nodes { keys, pointers }))
}
_ => panic!("error on index node deserialization"),
}
}
pub fn serialize<K: IndexType, V: IndexType>(node: Node<K, V>) -> PRes<Vec<u8>> {
let mut dest = Vec::new();
match node {
Node::LEAF(leaf) => {
dest.write_u8(1)?;
dest.write_u32::<BigEndian>(leaf.entries.len() as u32)?;
for entry in leaf.entries {
entry.key.serialize(&mut dest)?;
match entry.value {
Value::CLUSTER(cluster) => {
dest.write_u8(1)?;
dest.write_u32::<BigEndian>(cluster.len() as u32)?;
for val in cluster {
val.serialize(&mut dest)?;
}
}
Value::SINGLE(val) => {
dest.write_u8(2)?;
val.serialize(&mut dest)?;
}
}
}
if let Some(prev) = leaf.prev {
dest.write_u64::<BigEndian>(prev.page)?;
dest.write_u32::<BigEndian>(prev.pos)?;
} else {
dest.write_u64::<BigEndian>(0)?;
dest.write_u32::<BigEndian>(0)?;
}
if let Some(next) = leaf.next {
dest.write_u64::<BigEndian>(next.page)?;
dest.write_u32::<BigEndian>(next.pos)?;
} else {
dest.write_u64::<BigEndian>(0)?;
dest.write_u32::<BigEndian>(0)?;
}
}
Node::NODE(node) => {
dest.write_u8(2)?;
dest.write_u32::<BigEndian>(node.keys.len() as u32)?;
for k in node.keys {
k.serialize(&mut dest)?;
}
dest.write_u32::<BigEndian>(node.pointers.len() as u32)?;
for p in node.pointers {
dest.write_u64::<BigEndian>(p.page)?;
dest.write_u32::<BigEndian>(p.pos)?;
}
}
}
Ok(dest)
}
impl IndexSerialization for u8 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u8(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_u8().map_err(PersyError::from)
}
}
impl IndexSerialization for u16 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u16::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_u16::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for u32 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u32::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_u32::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for u64 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u64::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_u64::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for i8 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_i8(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_i8().map_err(PersyError::from)
}
}
impl IndexSerialization for i16 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_i16::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_i16::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for i32 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_i32::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_i32::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for i64 {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_i64::<BigEndian>(*self).map_err(PersyError::from)
}
fn deserialize(value: &mut Read) -> PRes<Self> {
value.read_i64::<BigEndian>().map_err(PersyError::from)
}
}
impl IndexSerialization for PersyId {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u64::<BigEndian>(self.0.page)?;
buffer.write_u32::<BigEndian>(self.0.pos)?;
Ok(())
}
fn deserialize(value: &mut Read) -> PRes<Self> {
let page = value.read_u64::<BigEndian>()?;
let pos = value.read_u32::<BigEndian>()?;
Ok(PersyId(RecRef::new(page, pos)))
}
}
impl IndexSerialization for String {
fn serialize(&self, buffer: &mut Write) -> PRes<()> {
buffer.write_u16::<BigEndian>(self.len() as u16)?;
buffer.write_all(self.as_bytes())?;
Ok(())
}
fn deserialize(value: &mut Read) -> PRes<Self> {
let string_size = value.read_u16::<BigEndian>()?;
let mut slice: Vec<u8> = Vec::new();
value.take(u64::from(string_size)).read_to_end(&mut slice)?;
Ok(str::from_utf8(&slice[0..string_size as usize])?.into())
}
}
#[cfg(test)]
mod tests {
extern crate rand;
use self::rand::random;
use super::{deserialize, serialize};
use index::config::{IndexType, ValueMode};
use index::tree::{Leaf, Node, NodeRef, Nodes, Value};
use persy::RecRef;
use std::fmt::Debug;
fn random_pointer() -> NodeRef {
RecRef::new(random::<u64>(), random::<u32>())
}
#[test]
fn test_serialization_deserialization_nodes() {
let val1 = random_pointer();
let val2 = random_pointer();
let val3 = random_pointer();
let mut node = Nodes::new_from_split(val1, &vec![(0, val2)]);
let pos = node.find(&2).pos;
node.add(pos, &2, val3.clone());
let value = serialize::<u8, u8>(Node::NODE(node)).expect("serialization works");
let read = deserialize::<u8, u8>(&value).expect("deserialzie successfully");
match read {
Node::NODE(n) => {
assert_eq!(n.keys.len(), 2);
assert_eq!(n.pointers.len(), 3);
}
_ => panic!("expected a node"),
}
}
fn single_type_leaf_test<K: IndexType + Debug, V: IndexType + Debug>(key: K, value: V, value1: V) {
let mut leaf = Leaf::new();
leaf.insert_or_update(&key, &value, ValueMode::REPLACE, "deserialization error")
.expect("insert work");
let binary = serialize::<K, V>(Node::LEAF(leaf)).expect("serialization works");
let read = deserialize::<K, V>(&binary).expect("deserialize successfully");
match read {
Node::LEAF(n) => {
assert_eq!(n.entries.len(), 1);
match n.entries[0].value {
Value::SINGLE(ref iv) => assert_eq!(iv, &value),
_ => panic!("expected SINGLE"),
}
}
_ => panic!("expected a leaf"),
}
let mut leaf_many = Leaf::new();
leaf_many
.insert_or_update(&key, &value, ValueMode::CLUSTER, "deserialization error")
.expect("insert work");
leaf_many
.insert_or_update(&key, &value1, ValueMode::CLUSTER, "deserialization error")
.expect("insert work");
let binary = serialize::<K, V>(Node::LEAF(leaf_many)).expect("serialization works");
let read = deserialize::<K, V>(&binary).expect("deserialize successfully");
match read {
Node::LEAF(n) => {
assert_eq!(n.entries.len(), 1);
match n.entries[0].value {
Value::CLUSTER(ref iv) => {
assert_eq!(iv, &vec![value, value1]);
}
_ => panic!("expected CLUSTER"),
}
}
_ => panic!("expected a leaf"),
}
}
#[test]
fn test_serialization_deserialization_leafs() {
single_type_leaf_test::<u8, u8>(20, 10, 20);
single_type_leaf_test::<u16, u16>(20, 10, 20);
single_type_leaf_test::<u32, u32>(20, 10, 20);
single_type_leaf_test::<u64, u64>(20, 10, 20);
single_type_leaf_test::<i8, i8>(20, 10, 20);
single_type_leaf_test::<i16, i16>(20, 10, 20);
single_type_leaf_test::<i32, i32>(20, 10, 20);
single_type_leaf_test::<i64, i64>(20, 10, 20);
single_type_leaf_test::<String, String>("o".to_string(), "a".to_string(), "b".to_string());
single_type_leaf_test::<i32, String>(10, "a".to_string(), "b".to_string());
single_type_leaf_test::<String, i32>("a".to_string(), 10, 20);
}
}