diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 62a3c43b0..f33d640f4 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -19,7 +19,7 @@ use util::bytes::Populatable; use util::numbers::{U256, U512, H256, H2048, Address}; use std::mem; -use std::collections::VecDeque; +use std::collections::{VecDeque, BTreeMap}; use std::ops::Range; #[derive(Debug)] @@ -139,6 +139,92 @@ impl BinaryConvertable for Result 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)), + }; + 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)), + }; + 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) + } + } + + 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() { @@ -652,3 +738,18 @@ fn serialize_err_opt_vec_in_out() { assert!(vec.is_ok()); } + +#[test] +fn serialize_btree() { + use std::io::{Cursor, SeekFrom, Seek}; + + let mut buff = Cursor::new(Vec::new()); + let mut btree = BTreeMap::new(); + btree.insert(1u64, 5u64); + serialize_into(&btree, &mut buff).unwrap(); + + buff.seek(SeekFrom::Start(0)).unwrap(); + let res = deserialize_from::, _>(&mut buff).unwrap(); + + assert_eq!(res[&1u64], 5u64); +}