// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
//! Binary representation of types
use util::bytes::Populatable;
use util::{U256, U512, H256, H2048, Address};
use std::mem;
use std::collections::{VecDeque, BTreeMap};
use std::ops::Range;
use super::Handshake;
#[derive(Debug)]
pub enum BinaryConvertErrorKind {
SizeMismatch {
expected: usize,
found: usize,
},
TargetPayloadEmpty,
UnexpectedVariant(u8),
MissingLengthValue,
InconsistentBoundaries,
NotSupported,
}
#[derive(Debug)]
pub struct BinaryConvertError {
member_tree: Vec<&'static str>,
kind: BinaryConvertErrorKind,
}
impl BinaryConvertError {
pub fn size(expected: usize, found: usize) -> BinaryConvertError {
BinaryConvertError {
member_tree: Vec::new(),
kind: BinaryConvertErrorKind::SizeMismatch {
expected: expected,
found: found,
}
}
}
pub fn empty() -> BinaryConvertError {
BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::TargetPayloadEmpty }
}
pub fn variant(val: u8) -> BinaryConvertError {
BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::UnexpectedVariant(val) }
}
pub fn length() -> BinaryConvertError {
BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::MissingLengthValue }
}
pub fn boundaries() -> BinaryConvertError {
BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::InconsistentBoundaries }
}
pub fn not_supported() -> BinaryConvertError {
BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::NotSupported }
}
pub fn named(mut self, name: &'static str) -> BinaryConvertError {
self.member_tree.push(name);
self
}
}
#[derive(Debug)]
pub enum BinaryError {
Serialization(BinaryConvertError),
Io(::std::io::Error),
}
impl From<::std::io::Error> for BinaryError {
fn from(err: ::std::io::Error) -> Self { BinaryError::Io(err) }
}
impl From for BinaryError {
fn from(err: BinaryConvertError) -> Self { BinaryError::Serialization(err) }
}
pub trait BinaryConvertable : Sized {
fn size(&self) -> usize {
mem::size_of::()
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError>;
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result;
fn from_empty_bytes() -> Result {
Err(BinaryConvertError::size(mem::size_of::(), 0))
}
fn len_params() -> usize {
0
}
}
impl BinaryConvertable for Option where T: BinaryConvertable {
fn size(&self) -> usize {
match * self { None => 0, Some(ref val) => val.size() }
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
match *self { None => Err(BinaryConvertError::empty()), Some(ref val) => val.to_bytes(buffer, length_stack) }
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
if buffer.len() == 0 { return Self::from_empty_bytes(); }
Ok(Some(try!(T::from_bytes(buffer, length_stack))))
}
fn from_empty_bytes() -> Result {
Ok(None)
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for Result<(), E> {
fn size(&self) -> usize {
match *self {
Ok(_) => 0,
Err(ref e) => e.size(),
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
match *self {
Ok(_) => Err(BinaryConvertError::empty()),
Err(ref e) => Ok(try!(e.to_bytes(buffer, length_stack))),
}
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
Ok(Err(try!(E::from_bytes(&buffer, length_stack))))
}
fn from_empty_bytes() -> Result {
Ok(Ok(()))
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for Result {
fn size(&self) -> usize {
match *self {
Ok(ref r) => r.size(),
Err(_) => 0,
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
match *self {
Ok(ref r) => Ok(try!(r.to_bytes(buffer, length_stack))),
Err(_) => Err(BinaryConvertError::empty()),
}
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
Ok(Ok(try!(R::from_bytes(&buffer, length_stack))))
}
fn from_empty_bytes() -> Result {
Ok(Err(()))
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for Result {
fn size(&self) -> usize {
1usize + match *self {
Ok(ref r) => r.size(),
Err(ref e) => e.size(),
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
match *self {
Ok(ref r) => {
buffer[0] = 0;
if r.size() > 0 {
Ok(try!(r.to_bytes(&mut buffer[1..], length_stack)))
}
else { Ok(()) }
},
Err(ref e) => {
buffer[0] = 1;
if e.size() > 0 {
Ok(try!(e.to_bytes(&mut buffer[1..], length_stack)))
}
else { Ok(()) }
},
}
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
match buffer[0] {
0 => {
match buffer.len() {
1 => Ok(Ok(try!(R::from_empty_bytes()))),
_ => Ok(Ok(try!(R::from_bytes(&buffer[1..], length_stack)))),
}
}
1 => Ok(Err(try!(E::from_bytes(&buffer[1..], length_stack)))),
_ => Err(BinaryConvertError::variant(buffer[0]))
}
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for BTreeMap where K : BinaryConvertable + Ord, V: BinaryConvertable {
fn size(&self) -> usize {
0usize + match K::len_params() {
0 => mem::size_of::() * self.len(),
_ => self.iter().fold(0usize, |acc, (k, _)| acc + k.size())
} + match V::len_params() {
0 => mem::size_of::() * self.len(),
_ => self.iter().fold(0usize, |acc, (_, v)| acc + v.size())
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
let mut offset = 0usize;
for (key, val) in self.iter() {
let key_size = match K::len_params() {
0 => mem::size_of::(),
_ => { let size = key.size(); length_stack.push_back(size); size }
};
let val_size = match K::len_params() {
0 => mem::size_of::(),
_ => { let size = val.size(); length_stack.push_back(size); size }
};
if key_size > 0 {
let item_end = offset + key_size;
try!(key.to_bytes(&mut buffer[offset..item_end], length_stack));
offset = item_end;
}
if val_size > 0 {
let item_end = offset + key_size;
try!(val.to_bytes(&mut buffer[offset..item_end], length_stack));
offset = item_end;
}
}
Ok(())
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
let mut index = 0;
let mut result = Self::new();
if buffer.len() == 0 { return Ok(result); }
loop {
let key_size = match K::len_params() {
0 => mem::size_of::(),
_ => try!(length_stack.pop_front().ok_or(BinaryConvertError::length())),
};
let key = if key_size == 0 {
try!(K::from_empty_bytes())
} else {
try!(K::from_bytes(&buffer[index..index+key_size], length_stack))
};
index = index + key_size;
let val_size = match V::len_params() {
0 => mem::size_of::(),
_ => try!(length_stack.pop_front().ok_or(BinaryConvertError::length())),
};
let val = if val_size == 0 {
try!(V::from_empty_bytes())
} else {
try!(V::from_bytes(&buffer[index..index+val_size], length_stack))
};
result.insert(key, val);
index = index + val_size;
if index == buffer.len() { break; }
if index > buffer.len() {
return Err(BinaryConvertError::boundaries())
}
}
Ok(result)
}
fn from_empty_bytes() -> Result {
Ok(Self::new())
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for VecDeque where T: BinaryConvertable {
fn size(&self) -> usize {
match T::len_params() {
0 => mem::size_of::() * self.len(),
_ => self.iter().fold(0usize, |acc, t| acc + t.size()),
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
let mut offset = 0usize;
for item in self.iter() {
let next_size = match T::len_params() {
0 => mem::size_of::(),
_ => { let size = item.size(); length_stack.push_back(size); size },
};
if next_size > 0 {
let item_end = offset + next_size;
try!(item.to_bytes(&mut buffer[offset..item_end], length_stack));
offset = item_end;
}
}
Ok(())
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
let mut index = 0;
let mut result = Self::with_capacity(
match T::len_params() {
0 => buffer.len() / mem::size_of::(),
_ => 128,
});
if buffer.len() == 0 { return Ok(result); }
loop {
let next_size = match T::len_params() {
0 => mem::size_of::(),
_ => try!(length_stack.pop_front().ok_or(BinaryConvertError::length())),
};
let item = if next_size == 0 {
try!(T::from_empty_bytes())
}
else {
try!(T::from_bytes(&buffer[index..index+next_size], length_stack))
};
result.push_back(item);
index = index + next_size;
if index == buffer.len() { break; }
if index + next_size > buffer.len() {
return Err(BinaryConvertError::boundaries())
}
}
Ok(result)
}
fn from_empty_bytes() -> Result {
Ok(Self::new())
}
fn len_params() -> usize {
1
}
}
//
impl BinaryConvertable for Vec where T: BinaryConvertable {
fn size(&self) -> usize {
match T::len_params() {
0 => mem::size_of::() * self.len(),
_ => self.iter().fold(0usize, |acc, t| acc + t.size()),
}
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
let mut offset = 0usize;
for item in self.iter() {
let next_size = match T::len_params() {
0 => mem::size_of::(),
_ => { let size = item.size(); length_stack.push_back(size); size },
};
if next_size > 0 {
let item_end = offset + next_size;
try!(item.to_bytes(&mut buffer[offset..item_end], length_stack));
offset = item_end;
}
}
Ok(())
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
let mut index = 0;
let mut result = Self::with_capacity(
match T::len_params() {
0 => buffer.len() / mem::size_of::(),
_ => 128,
});
if buffer.len() == 0 { return Ok(result); }
loop {
let next_size = match T::len_params() {
0 => mem::size_of::(),
_ => try!(length_stack.pop_front().ok_or(BinaryConvertError::length())),
};
let item = if next_size == 0 {
try!(T::from_empty_bytes())
}
else {
try!(T::from_bytes(&buffer[index..index+next_size], length_stack))
};
result.push(item);
index = index + next_size;
if index == buffer.len() { break; }
if index + next_size > buffer.len() {
return Err(BinaryConvertError::boundaries())
}
}
Ok(result)
}
fn from_empty_bytes() -> Result {
Ok(Self::new())
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for String {
fn size(&self) -> usize {
self.as_bytes().len()
}
fn from_empty_bytes() -> Result {
Ok(String::new())
}
fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
buffer[..].clone_from_slice(self.as_bytes());
Ok(())
}
fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result {
Ok(::std::str::from_utf8(buffer).unwrap().to_owned())
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for Range where T: BinaryConvertable {
fn size(&self) -> usize {
mem::size_of::() * 2
}
fn from_empty_bytes() -> Result {
Err(BinaryConvertError::empty())
}
fn to_bytes(&self, buffer: &mut[u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
try!(self.start.to_bytes(&mut buffer[..mem::size_of::()], length_stack));
try!(self.end.to_bytes(&mut buffer[mem::size_of::() + 1..], length_stack));
Ok(())
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
Ok(try!(T::from_bytes(&buffer[..mem::size_of::()], length_stack))..try!(T::from_bytes(&buffer[mem::size_of::()+1..], length_stack)))
}
fn len_params() -> usize {
assert_eq!(0, T::len_params());
0
}
}
impl BinaryConvertable for ::std::cell::RefCell where T: BinaryConvertable {
fn size(&self) -> usize {
self.borrow().size()
}
fn from_empty_bytes() -> Result {
Ok(::std::cell::RefCell::new(try!(T::from_empty_bytes())))
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
Ok(::std::cell::RefCell::new(try!(T::from_bytes(buffer, length_stack))))
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
try!(self.borrow().to_bytes(buffer, length_stack));
Ok(())
}
fn len_params() -> usize {
T::len_params()
}
}
impl BinaryConvertable for ::std::cell::Cell where T: BinaryConvertable + Copy {
fn size(&self) -> usize {
self.get().size()
}
fn from_empty_bytes() -> Result {
Ok(::std::cell::Cell::new(try!(T::from_empty_bytes())))
}
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result {
Ok(::std::cell::Cell::new(try!(T::from_bytes(buffer, length_stack))))
}
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
try!(self.get().to_bytes(buffer, length_stack));
Ok(())
}
fn len_params() -> usize {
T::len_params()
}
}
impl BinaryConvertable for Vec {
fn size(&self) -> usize {
self.len()
}
fn from_empty_bytes() -> Result {
Ok(Vec::new())
}
fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
buffer[..].clone_from_slice(&self[..]);
Ok(())
}
fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result {
let mut res = Self::with_capacity(buffer.len());
unsafe { res.set_len(buffer.len()) }
res[..].clone_from_slice(&buffer[..]);
Ok(res)
}
fn len_params() -> usize {
1
}
}
pub fn deserialize_from(r: &mut R) -> Result
where R: ::std::io::Read,
T: BinaryConvertable
{
let mut fake_stack = VecDeque::new();
match T::len_params() {
0 => {
let fixed_size = mem::size_of::();
let mut payload_buffer = Vec::with_capacity(fixed_size);
unsafe { payload_buffer.set_len(fixed_size); }
let bytes_read = try!(r.read(&mut payload_buffer));
if bytes_read != mem::size_of::() {
return Err(BinaryError::Serialization(BinaryConvertError::size(fixed_size, bytes_read)))
}
Ok(try!(T::from_bytes(&payload_buffer[..], &mut fake_stack)))
},
_ => {
let mut payload = Vec::new();
try!(r.read_to_end(&mut payload));
let stack_len = try!(u64::from_bytes(&payload[0..8], &mut fake_stack)) as usize;
let mut length_stack = VecDeque::::with_capacity(stack_len);
if stack_len > 0 {
for idx in 0..stack_len {
let stack_item = try!(u64::from_bytes(&payload[8 + idx*8..8 + (idx+1)*8], &mut fake_stack));
length_stack.push_back(stack_item as usize);
}
}
//try!(r.read(&mut size_buffer).map_err(|_| BinaryConvertError));
let size = try!(u64::from_bytes(&payload[8+stack_len*8..16+stack_len*8], &mut fake_stack)) as usize;
match size {
0 => {
Ok(try!(T::from_empty_bytes()))
},
_ => {
Ok(try!(T::from_bytes(&payload[16+stack_len*8..], &mut length_stack)))
}
}
},
}
}
pub fn deserialize(buffer: &[u8]) -> Result {
use std::io::Cursor;
let mut buff = Cursor::new(buffer);
deserialize_from::(&mut buff)
}
pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryError>
where W: ::std::io::Write,
T: BinaryConvertable
{
let mut fake_stack = VecDeque::new();
match T::len_params() {
0 => {
let fixed_size = mem::size_of::();
let mut buffer = Vec::with_capacity(fixed_size);
unsafe { buffer.set_len(fixed_size); }
try!(t.to_bytes(&mut buffer[..], &mut fake_stack));
try!(w.write(&buffer[..]));
Ok(())
},
_ => {
let mut length_stack = VecDeque::::new();
let mut size_buffer = [0u8; 8];
let size = t.size();
if size == 0 {
try!(w.write(&size_buffer));
try!(w.write(&size_buffer));
return Ok(());
}
let mut buffer = Vec::with_capacity(size);
unsafe { buffer.set_len(size); }
try!(t.to_bytes(&mut buffer[..], &mut length_stack));
let stack_len = length_stack.len();
try!((stack_len as u64).to_bytes(&mut size_buffer[..], &mut fake_stack));
try!(w.write(&size_buffer[..]));
if stack_len > 0 {
let mut header_buffer = Vec::with_capacity(stack_len * 8);
unsafe { header_buffer.set_len(stack_len * 8); };
try!((stack_len as u64).to_bytes(&mut header_buffer[0..8], &mut fake_stack));
let mut idx = 0;
loop {
match length_stack.pop_front() {
Some(val) => try!((val as u64).to_bytes(&mut header_buffer[idx * 8..(idx+1) * 8], &mut fake_stack)),
None => { break; }
}
idx = idx + 1;
}
try!(w.write(&header_buffer[..]));
}
try!((size as u64).to_bytes(&mut size_buffer[..], &mut fake_stack));
try!(w.write(&size_buffer[..]));
try!(w.write(&buffer[..]));
Ok(())
},
}
}
pub fn serialize(t: &T) -> Result, BinaryError> {
use std::io::Cursor;
let mut buff = Cursor::new(Vec::new());
try!(serialize_into(t, &mut buff));
let into_inner = buff.into_inner();
Ok(into_inner)
}
#[macro_export]
macro_rules! binary_fixed_size {
($target_ty: ty) => {
impl BinaryConvertable for $target_ty {
fn from_bytes(bytes: &[u8], _length_stack: &mut VecDeque) -> Result {
match bytes.len().cmp(&::std::mem::size_of::<$target_ty>()) {
::std::cmp::Ordering::Equal => (),
_ => return Err(BinaryConvertError::size(::std::mem::size_of::<$target_ty>(), bytes.len())),
};
let mut res: Self = unsafe { ::std::mem::uninitialized() };
res.copy_raw(bytes);
Ok(res)
}
fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> {
let sz = ::std::mem::size_of::<$target_ty>();
let ip: *const $target_ty = self;
let ptr: *const u8 = ip as *const _;
unsafe {
::std::ptr::copy(ptr, buffer.as_mut_ptr(), sz);
}
Ok(())
}
}
}
}
/// Fixed-sized version of Handshake struct
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BinHandshake {
api_version: BinVersion,
protocol_version: BinVersion,
}
/// Shorten version of semver Version without `pre` and `build` information
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BinVersion {
pub major: u64,
pub minor: u64,
pub patch: u64,
}
impl From for BinHandshake {
fn from(other: Handshake) -> Self {
BinHandshake {
api_version: BinVersion::from(other.api_version),
protocol_version: BinVersion::from(other.protocol_version),
}
}
}
impl BinHandshake {
pub fn to_semver(self) -> Handshake {
Handshake {
api_version: self.api_version.to_semver(),
protocol_version: self.protocol_version.to_semver(),
}
}
}
impl BinVersion {
pub fn to_semver(self) -> ::semver::Version {
::semver::Version {
major: self.major,
minor: self.minor,
patch: self.patch,
pre: vec![],
build: vec![],
}
}
}
impl From<::semver::Version> for BinVersion {
fn from(other: ::semver::Version) -> Self {
BinVersion {
major: other.major,
minor: other.minor,
patch: other.patch,
}
}
}
binary_fixed_size!(u16);
binary_fixed_size!(u64);
binary_fixed_size!(u32);
binary_fixed_size!(usize);
binary_fixed_size!(i32);
binary_fixed_size!(bool);
binary_fixed_size!(U256);
binary_fixed_size!(U512);
binary_fixed_size!(H256);
binary_fixed_size!(H2048);
binary_fixed_size!(Address);
binary_fixed_size!(BinHandshake);
#[test]
fn vec_serialize() {
let mut v = Vec::new();
v.push(5u64);
v.push(10u64);
let mut length_stack = VecDeque::new();
let mut data = Vec::with_capacity(v.size());
unsafe { data.set_len(v.size()); }
let result = v.to_bytes(&mut data[..], &mut length_stack);
assert!(result.is_ok());
assert_eq!(5, data[0]);
assert_eq!(0, data[1]);
assert_eq!(10, data[8]);
assert_eq!(0, data[12]);
}
#[test]
fn calculates_size() {
let mut v = Vec::new();
v.push(5u64);
v.push(10u64);
assert_eq!(16, v.size());
}
#[test]
fn vec_deserialize() {
let data = [
10u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
];
let mut length_stack = VecDeque::new();
let vec = Vec::::from_bytes(&data[..], &mut length_stack).unwrap();
assert_eq!(vec![10u64, 5u64], vec);
}
#[test]
fn vec_deserialize_chained() {
let mut v = Vec::new();
v.push(Some(5u64));
v.push(Some(10u64));
v.push(None);
v.push(Some(12u64));
let mut length_stack = VecDeque::new();
let mut data = Vec::with_capacity(v.size());
unsafe { data.set_len(v.size()); }
let result = v.to_bytes(&mut data[..], &mut length_stack);
assert!(result.is_ok());
assert_eq!(4, length_stack.len());
}
#[test]
fn vec_serialize_deserialize() {
let mut v = Vec::new();
v.push(Some(5u64));
v.push(None);
v.push(Some(10u64));
v.push(None);
v.push(Some(12u64));
let mut data = Vec::with_capacity(v.size());
unsafe { data.set_len(v.size()); }
let mut length_stack = VecDeque::new();
v.to_bytes(&mut data[..], &mut length_stack).unwrap();
let de_v = Vec::