From 8b1197b33551d8dada568ba66ffd4b46fb2db71e Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 19:01:53 +0300 Subject: [PATCH] working serialization gen --- ipc/codegen/src/serialization.rs | 50 ++++++++++++++++++++++---------- ipc/rpc/Cargo.toml | 1 + ipc/rpc/src/binary.rs | 42 +++++++++++++++++++++++++-- ipc/rpc/src/lib.rs | 3 +- ipc/tests/binary.rs.in | 8 ++++- 5 files changed, 84 insertions(+), 20 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 1f1799f34..596f54d1a 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -103,12 +103,13 @@ fn serialize_item( $size_expr } - fn to_bytes(buffer: &mut [u8]) { + fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError> { $write_expr } - fn from_bytes(buffer: &[u8]) -> Self { - $read_expr + fn from_bytes(buffer: &[u8]) -> Result { + //$read_expr + Err(::ipc::BinaryConvertError) } } ).unwrap()) @@ -165,7 +166,7 @@ fn binary_expr_struct( value_ident: Option, ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { - let index_ident = builder.id(format!("{}", index)); + let index_ident = builder.id(format!("__field{}", index)); value_ident.and_then(|x| Some(quote_expr!(cx, $x . $index_ident .size()))) .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) }).collect(); @@ -179,17 +180,18 @@ fn binary_expr_struct( let mut write_stmts = Vec::::new(); write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { - let index_ident = builder.id(format!("{}", index)); let size_expr = &size_exprs[index]; write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap()); match value_ident { Some(x) => { + let index_ident = builder.id(format!("{}", index)); write_stmts.push( - quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);).unwrap()) + quote_stmt!(cx, $x . $index_ident .to_bytes(&mut buffer[offset..next_line]);).unwrap()) }, None => { + let index_ident = builder.id(format!("__field{}", index)); write_stmts.push( - quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);).unwrap()) + quote_stmt!(cx, $index_ident .to_bytes(&mut buffer[offset..next_line]);).unwrap()) } } write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); @@ -197,8 +199,8 @@ fn binary_expr_struct( Ok(BinaryExpressions { size: total_size_expr, - write: quote_expr!(cx, { write_stmts; Ok(()) } ), - read: quote_expr!(cx, $ty { }), + write: quote_expr!(cx, { $write_stmts; Ok(()) } ), + read: quote_expr!(cx, Err(::ipc::BinaryConvertError)), }) } @@ -230,7 +232,9 @@ fn binary_expr_item_struct( ) }, _ => { - cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct"); + cx.span_bug(span, + &format!("#[derive(Binary)] Unsupported struct content, expected tuple/struct, found: {:?}", + variant_data)); Err(Error) }, } @@ -269,7 +273,7 @@ fn binary_expr_enum( arms.iter().map(|x| x.read.clone()).collect::>()); Ok(BinaryExpressions { - size: quote_expr!(cx, match *self { $size_arms }), + size: quote_expr!(cx, 1usize + match *self { $size_arms }), write: quote_expr!(cx, match *self { $write_arms }; ), read: quote_expr!(cx, match *self { $read_arms }), }) @@ -296,6 +300,17 @@ fn binary_expr_variant( let variant_ident = variant.node.name; match variant.node.data { + ast::VariantData::Unit(_) => { + let pat = builder.pat().path() + .id(type_ident).id(variant_ident) + .build(); + + Ok(BinaryArm { + size: quote_arm!(cx, $pat => { 0usize } ), + write: quote_arm!(cx, $pat => { Ok(()) } ), + read: quote_arm!(cx, $pat => { } ), + }) + }, ast::VariantData::Tuple(ref fields, _) => { let field_names: Vec = (0 .. fields.len()) .map(|i| builder.id(format!("__field{}", i))) @@ -319,9 +334,10 @@ fn binary_expr_variant( let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + let variant_index_ident = builder.id(format!("{}", variant_index)); Ok(BinaryArm { size: quote_arm!(cx, $pat => { $size_expr } ), - write: quote_arm!(cx, $pat => { $write_expr } ), + write: quote_arm!(cx, $pat => { buffer[0] = $variant_index_ident; let buffer = &mut buffer[1..]; $write_expr } ), read: quote_arm!(cx, $pat => { $read_expr } ), }) } @@ -354,9 +370,11 @@ fn binary_expr_variant( read: quote_arm!(cx, $pat => { $read_expr } ), }) }, - _ => { - cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct"); - Err(Error) - }, +// _ => { +// cx.span_bug(span, +// &format!("#[derive(Binary)] Unsupported enum variant content, expected tuple/struct, found: {:?}", +// variant)); +// Err(Error) +// }, } } diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml index c07cb8ae3..b66de73db 100644 --- a/ipc/rpc/Cargo.toml +++ b/ipc/rpc/Cargo.toml @@ -10,3 +10,4 @@ license = "GPL-3.0" ethcore-devtools = { path = "../../devtools" } semver = "0.2.0" nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" } +ethcore-util = { path = "../../util" } diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 08dd739df..7f73c8242 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -16,12 +16,50 @@ //! Binary representation of types +use util::bytes::*; +use std::mem; + pub struct BinaryConvertError; pub trait BinaryConvertable : Sized { - fn size(&self) -> Result; + fn size(&self) -> usize; - fn to_bytes(buffer: &mut [u8]) -> Result<(), BinaryConvertError>; + fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError>; fn from_bytes(buffer: &[u8]) -> Result; } + +macro_rules! binary_fixed_size { + ($target_ty: ident) => { + impl BinaryConvertable for $target_ty { + fn size(&self) -> usize { + mem::size_of::<$target_ty>() + } + + fn from_bytes(bytes: &[u8]) -> Result { + match bytes.len().cmp(&::std::mem::size_of::<$target_ty>()) { + ::std::cmp::Ordering::Less => return Err(BinaryConvertError), + ::std::cmp::Ordering::Greater => return Err(BinaryConvertError), + ::std::cmp::Ordering::Equal => () + }; + let mut res: Self = unsafe { ::std::mem::uninitialized() }; + res.copy_raw(bytes); + Ok(res) + } + + fn to_bytes(&self, buffer: &mut [u8]) -> 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(()) + } + } + } +} + +binary_fixed_size!(u64); +binary_fixed_size!(u32); +binary_fixed_size!(bool); diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index 4d5902383..a19302fb2 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -19,8 +19,9 @@ extern crate ethcore_devtools as devtools; extern crate semver; extern crate nanomsg; +extern crate ethcore_util as util; pub mod interface; pub mod binary; pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket}; -pub use binary::{BinaryConvertable}; +pub use binary::{BinaryConvertable, BinaryConvertError}; diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index a3d52dfc9..875220535 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -14,8 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use ipc::*; + #[derive(Binary)] enum Root { Top, - Middle(String) + Middle(u32, u64), + Bottom { + number1: u32, + number2: u64, + }, }