From e0ae0724e21c12b2b0cf3936ef210cfa0ed61ffd Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 14:17:11 +0300 Subject: [PATCH 01/17] initial commit --- ipc/codegen/src/lib.rs | 5 + ipc/codegen/src/lib.rs.in | 1 + ipc/codegen/src/serialization.rs | 202 +++++++++++++++++++++++++++++++ ipc/codegen/src/typegen.rs | 3 +- ipc/rpc/src/binary.rs | 25 ++++ ipc/rpc/src/lib.rs | 2 +- 6 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 ipc/codegen/src/serialization.rs create mode 100644 ipc/rpc/src/binary.rs diff --git a/ipc/codegen/src/lib.rs b/ipc/codegen/src/lib.rs index a29678df0..126aa3a85 100644 --- a/ipc/codegen/src/lib.rs +++ b/ipc/codegen/src/lib.rs @@ -54,6 +54,7 @@ pub fn register(reg: &mut syntex::Registry) { reg.add_attr("feature(custom_attribute)"); reg.add_decorator("derive_Ipc", codegen::expand_ipc_implementation); + reg.add_decorator("derive_Binary", serialization::expand_serialization_implementation); } #[cfg(not(feature = "with-syntex"))] @@ -62,4 +63,8 @@ pub fn register(reg: &mut rustc_plugin::Registry) { syntax::parse::token::intern("derive_Ipc"), syntax::ext::base::MultiDecorator( Box::new(codegen::expand_ipc_implementation))); + reg.register_syntax_extension( + syntax::parse::token::intern("derive_Binary"), + syntax::ext::base::MultiDecorator( + Box::new(serialization::expand_serialization_implementation))); } diff --git a/ipc/codegen/src/lib.rs.in b/ipc/codegen/src/lib.rs.in index 46a2c9ca5..08c8ad998 100644 --- a/ipc/codegen/src/lib.rs.in +++ b/ipc/codegen/src/lib.rs.in @@ -15,4 +15,5 @@ // along with Parity. If not, see . mod codegen; +mod serialization; pub mod typegen; diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs new file mode 100644 index 000000000..205b13f67 --- /dev/null +++ b/ipc/codegen/src/serialization.rs @@ -0,0 +1,202 @@ +// 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 . +use aster; + +use syntax::ast::{ + MetaItem, + Item, + ImplItemKind, + ImplItem, + MethodSig, + Arg, + PatKind, + FunctionRetTy, + Ty, + TraitRef, + Ident, + Generics, +}; + +use syntax::ast; +use syntax::codemap::Span; +use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax::ext::build::AstBuilder; +use syntax::ptr::P; + +pub struct Error; + +pub fn expand_serialization_implementation( + cx: &mut ExtCtxt, + span: Span, + meta_item: &MetaItem, + annotatable: &Annotatable, + push: &mut FnMut(Annotatable) +) { + let item = match *annotatable { + Annotatable::Item(ref item) => item, + _ => { + cx.span_err(meta_item.span, "`#[derive(Binary)]` may only be applied to structs and enums"); + return; + } + }; + + let builder = aster::AstBuilder::new().span(span); + + let impl_item = match serialize_item(cx, &builder, &item) { + Ok(item) => item, + Err(Error) => { + // An error occured, but it should have been reported already. + return; + } + }; + + push(Annotatable::Item(impl_item)) +} + +fn serialize_item( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + item: &Item, +) -> Result, Error> { + let generics = match item.node { + ast::ItemKind::Struct(_, ref generics) => generics, + ast::ItemKind::Enum(_, ref generics) => generics, + _ => { + cx.span_err( + item.span, + "`#[derive(Serialize)]` may only be applied to structs and enums"); + return Err(Error); + } + }; + + let impl_generics = build_impl_generics(cx, builder, item, generics); + + let ty = builder.ty().path() + .segment(item.ident).with_generics(impl_generics.clone()).build() + .build(); + + let where_clause = &impl_generics.where_clause; + + let binary_expressions = try!(binary_expr(cx, + &builder, + &item, + &impl_generics, + ty.clone())); + + Ok(quote_item!(cx, + impl $impl_generics ::ipc::BinaryConvertable for $ty $where_clause { + fn size(&self) -> usize { + $size_expr + } + + fn to_bytes(buffer: &mut [u8]) { + $write_expr + } + + fn from_bytes(buffer: &[u8]) -> Self { + $create_expr + } + } + ).unwrap()) +} + +fn binary_expr( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + item: &Item, + impl_generics: &ast::Generics, + ty: P, +) -> Result { + match item.node { + ast::ItemKind::Struct(ref variant_data, _) => { + binary_expr_struct( + cx, + builder, + impl_generics, + ty, + item.span, + variant_data, + ) + } + ast::ItemKind::Enum(ref enum_def, _) => { + binary_expr_enum( + cx, + builder, + item.ident, + impl_generics, + ty, + enum_def, + ) + } + _ => { + cx.span_bug(item.span, + "expected ItemStruct or ItemEnum in #[derive(Serialize)]"); + } + } +} + +struct BinaryExpressions { + size: P, + write: P, + read: P, +} + +fn serialize_tuple_struct( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + impl_generics: &ast::Generics, + ty: P, + fields: usize, +) -> Result, Error> { + let type_name = field.ty; + let id = field.id; + + Ok(BinaryExpressions { + size: quote_expr!(cx, self. $id .size() ), + write: quote_stmt!(cx, self. $id .write(buffer); ), + read: quote_expr!(cx, Self { $id: $type_name ::from_bytes(buffer) }), + }); +} + +fn binary_expr_struct( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + impl_generics: &ast::Generics, + ty: P, + span: Span, + variant_data: &ast::VariantData, +) -> Result { + match *variant_data { + ast::VariantData::Tuple(ref fields, _) => { + binary_expr_struct_tuple( + cx, + &builder, + impl_generics, + ty, + fields, + ) + } + ast::VariantData::Struct(ref fields, _) => { + binary_expr_struct_inner( + cx, + &builder, + impl_generics, + ty, + fields, + ) + } + } +} diff --git a/ipc/codegen/src/typegen.rs b/ipc/codegen/src/typegen.rs index e6e828ee7..0699bccb0 100644 --- a/ipc/codegen/src/typegen.rs +++ b/ipc/codegen/src/typegen.rs @@ -50,7 +50,8 @@ fn is_new_entry(path: &Path) -> Option { ident == "H256" || ident == "U256" || ident == "H2048" || - ident == "Address" + ident == "Address" || + ident == "Bytes" } }; diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs new file mode 100644 index 000000000..3b9b0a561 --- /dev/null +++ b/ipc/rpc/src/binary.rs @@ -0,0 +1,25 @@ +// 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 + +trait BinaryConvertable { + fn size(&self) -> usize; + + fn to_bytes(buffer: &mut [u8]); + + fn from_bytes(buffer: &[u8]) -> Self; +} diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index c2165b6e5..c771fb1b1 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -21,4 +21,4 @@ extern crate semver; extern crate nanomsg; pub mod interface; -pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket}; +pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket, BinaryConvertable}; From 59e18ad65970d519c44e70d2f0421aca723dedc5 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 15:55:08 +0300 Subject: [PATCH 02/17] making this work --- Cargo.lock | 8 ++ ipc/codegen/src/serialization.rs | 192 +++++++++++++++++++++++++++---- ipc/rpc/src/binary.rs | 2 +- ipc/rpc/src/lib.rs | 4 +- 4 files changed, 179 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39aed230f..453891fff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -237,11 +237,15 @@ dependencies = [ name = "ethcore" version = "1.1.0" dependencies = [ + "bincode 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.63 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.1.0", "ethcore-devtools 1.1.0", + "ethcore-ipc 1.1.0", + "ethcore-ipc-codegen 1.1.0", + "ethcore-ipc-nano 1.1.0", "ethcore-util 1.1.0", "ethjson 0.1.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -250,6 +254,10 @@ dependencies = [ "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 205b13f67..390f83170 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -122,7 +122,7 @@ fn binary_expr( ) -> Result { match item.node { ast::ItemKind::Struct(ref variant_data, _) => { - binary_expr_struct( + binary_expr_item_struct( cx, builder, impl_generics, @@ -149,29 +149,54 @@ fn binary_expr( } struct BinaryExpressions { - size: P, - write: P, - read: P, -} - -fn serialize_tuple_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - impl_generics: &ast::Generics, - ty: P, - fields: usize, -) -> Result, Error> { - let type_name = field.ty; - let id = field.id; - - Ok(BinaryExpressions { - size: quote_expr!(cx, self. $id .size() ), - write: quote_stmt!(cx, self. $id .write(buffer); ), - read: quote_expr!(cx, Self { $id: $type_name ::from_bytes(buffer) }), - }); + pub size: P, + pub write: P, + pub read: P, } fn binary_expr_struct( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + ty: P, + fields: &[ast::StructField], + value_ident: Option>, +) -> Result { + let type_name = field.ty; + let id = field.id; + + let mut size_exprs = Vec::new(); + fields.iter().enumerate(|(index, field)| { + let index_ident = builder.id(format!("{}", index)); + value_ident.and_then(|value_ident| size_exprs.push(quote_expr!(cx, $value_ident . $index_ident .size()))) + .unwrap_or_else(|| size_exprs.push(quote_expr!(cx, $index_ident .size()))); + }); + + let mut total_size_expr = size_exprs[0].clone(); + for index in 1..size_expr.len() { + let next_expr = size_exprs[i].clone(); + total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr); + } + + let mut write_stmts = Vec::new(); + write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;)); + fields.iter().enumerate(|(index, field)| { + 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; )); + value_ident.and_then(|x| + write_stmts.push(quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);)) + ).unwrap_or_else(|| write_stmts.push(quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);))); + write_stmts.push(quote_stmt!(cx, offset = next_line; )); + }); + + Ok(BinaryExpressions { + size: total_size_expr, + write: quote_stmt!(cx, { $write_stmts } ), + read: quote_expr!(cx, $ty { }), + }); +} + +fn binary_expr_item_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, impl_generics: &ast::Generics, @@ -181,22 +206,139 @@ fn binary_expr_struct( ) -> Result { match *variant_data { ast::VariantData::Tuple(ref fields, _) => { - binary_expr_struct_tuple( + binary_expr_struct( cx, &builder, - impl_generics, ty, fields, ) } ast::VariantData::Struct(ref fields, _) => { - binary_expr_struct_inner( + binary_expr_struct( cx, &builder, - impl_generics, ty, fields, ) } } } + +fn binary_expr_enum( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + type_ident: Ident, + impl_generics: &ast::Generics, + ty: P, + enum_def: &ast::EnumDef, +) -> Result { + let arms: Vec<_> = try!( + enum_def.variants.iter() + .enumerate() + .map(|(variant_index, variant)| { + binary_expr_variant( + cx, + builder, + type_ident, + impl_generics, + ty.clone(), + variant, + variant_index, + ) + }) + .collect() + ); + + let (size_arms, write_arms, read_arms) = ( + arms.iter().map(|x| x.size).collect::>>(), + arms.iter().map(|x| x.write).collect::>>(), + arms.iter().map(|x| x.read).collect::>>()); + + Ok(BinaryExpressions { + size: quote_expr!(cx, match *self { $size_arms }), + write: quote_stmt!(cx, match *self { $write_arms }; ), + read: quote_expr!(cx, match *self { $read_arms }), + }); + +} + +struct BinaryArm { + size: P, + write: P, + read: P, +} + +fn binary_expr_variant( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + type_ident: Ident, + generics: &ast::Generics, + ty: P, + variant: &ast::Variant, + variant_index: usize, +) -> Result { + let type_name = ty.name; + + let variant_ident = variant.node.name; + + match variant.node.data { + ast::VariantData::Tuple(ref fields, _) => { + let field_names: Vec = (0 .. fields.len()) + .map(|i| builder.id(format!("__field{}", i))) + .collect(); + + let pat = builder.pat().enum_() + .id(type_ident).id(variant_ident).build() + .with_pats( + field_names.iter() + .map(|field| builder.pat().ref_id(field)) + ) + .build(); + + let binary_expr = try!(binary_expr_struct( + cx, + &builder, + ty, + fields, + None, + )); + + let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + + Ok(BinaryArm { + size: P(quote_arm!(cx, $pat => { $size_expr } )), + write: P(quote_arm!(cx, $pat => { $write } )), + read: P(quote_arm!(cx, $pat => { $read_expr } )), + }) + } + ast::VariantData::Struct(ref fields, _) => { + let field_names: Vec<_> = (0 .. fields.len()) + .map(|i| builder.id(format!("__field{}", i))) + .collect(); + + let pat = builder.pat().struct_() + .id(type_ident).id(variant_ident).build() + .with_pats( + field_names.iter() + .zip(fields.iter()) + .map(|(id, field)|(name, builder.pat().ref_id(id)))) + .build(); + + + let binary_expr = try!(binary_expr_struct( + cx, + &builder, + ty, + fields, + None, + )); + + let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + Ok(BinaryArm { + size: P(quote_arm!(cx, $pat => { $size_expr } )), + write: P(quote_arm!(cx, $pat => { $write } )), + read: P(quote_arm!(cx, $pat => { $read_expr } )), + }) + } + } +} diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 3b9b0a561..2cc07f2d0 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -16,7 +16,7 @@ //! Binary representation of types -trait BinaryConvertable { +pub trait BinaryConvertable { fn size(&self) -> usize; fn to_bytes(buffer: &mut [u8]); diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index c771fb1b1..4d5902383 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -21,4 +21,6 @@ extern crate semver; extern crate nanomsg; pub mod interface; -pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket, BinaryConvertable}; +pub mod binary; +pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket}; +pub use binary::{BinaryConvertable}; From 3908ddf6091f6e68356e7426b2c223290217a11d Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 18:02:17 +0300 Subject: [PATCH 03/17] compilation fixed --- ipc/codegen/src/serialization.rs | 126 ++++++++++++++++++------------- ipc/rpc/src/binary.rs | 10 ++- ipc/tests/binary.rs | 17 +++++ ipc/tests/binary.rs.in | 21 ++++++ ipc/tests/build.rs | 9 +++ ipc/tests/run.rs | 1 + 6 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 ipc/tests/binary.rs create mode 100644 ipc/tests/binary.rs.in diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 390f83170..1f1799f34 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -77,27 +77,28 @@ fn serialize_item( _ => { cx.span_err( item.span, - "`#[derive(Serialize)]` may only be applied to structs and enums"); + "`#[derive(Binary)]` may only be applied to structs and enums"); return Err(Error); } }; - let impl_generics = build_impl_generics(cx, builder, item, generics); - let ty = builder.ty().path() - .segment(item.ident).with_generics(impl_generics.clone()).build() + .segment(item.ident).with_generics(generics.clone()).build() .build(); - let where_clause = &impl_generics.where_clause; + let where_clause = &generics.where_clause; let binary_expressions = try!(binary_expr(cx, &builder, &item, - &impl_generics, + &generics, ty.clone())); + let (size_expr, read_expr, write_expr) = + (binary_expressions.size, binary_expressions.read, binary_expressions.write); + Ok(quote_item!(cx, - impl $impl_generics ::ipc::BinaryConvertable for $ty $where_clause { + impl $generics ::ipc::BinaryConvertable for $ty $where_clause { fn size(&self) -> usize { $size_expr } @@ -107,7 +108,7 @@ fn serialize_item( } fn from_bytes(buffer: &[u8]) -> Self { - $create_expr + $read_expr } } ).unwrap()) @@ -138,19 +139,21 @@ fn binary_expr( item.ident, impl_generics, ty, + item.span, enum_def, ) } _ => { cx.span_bug(item.span, - "expected ItemStruct or ItemEnum in #[derive(Serialize)]"); + "expected ItemStruct or ItemEnum in #[derive(Binary)]"); + Err(Error) } } } struct BinaryExpressions { pub size: P, - pub write: P, + pub write: P, pub read: P, } @@ -159,41 +162,44 @@ fn binary_expr_struct( builder: &aster::AstBuilder, ty: P, fields: &[ast::StructField], - value_ident: Option>, + value_ident: Option, ) -> Result { - let type_name = field.ty; - let id = field.id; - - let mut size_exprs = Vec::new(); - fields.iter().enumerate(|(index, field)| { + let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { let index_ident = builder.id(format!("{}", index)); - value_ident.and_then(|value_ident| size_exprs.push(quote_expr!(cx, $value_ident . $index_ident .size()))) - .unwrap_or_else(|| size_exprs.push(quote_expr!(cx, $index_ident .size()))); - }); + value_ident.and_then(|x| Some(quote_expr!(cx, $x . $index_ident .size()))) + .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) + }).collect(); let mut total_size_expr = size_exprs[0].clone(); - for index in 1..size_expr.len() { - let next_expr = size_exprs[i].clone(); + for index in 1..size_exprs.len() { + let next_expr = size_exprs[index].clone(); total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr); } - let mut write_stmts = Vec::new(); - write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;)); - fields.iter().enumerate(|(index, field)| { + 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; )); - value_ident.and_then(|x| - write_stmts.push(quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);)) - ).unwrap_or_else(|| write_stmts.push(quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);))); - write_stmts.push(quote_stmt!(cx, offset = next_line; )); - }); + let size_expr = &size_exprs[index]; + write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap()); + match value_ident { + Some(x) => { + write_stmts.push( + quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);).unwrap()) + }, + None => { + write_stmts.push( + quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);).unwrap()) + } + } + write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); + }; Ok(BinaryExpressions { size: total_size_expr, - write: quote_stmt!(cx, { $write_stmts } ), + write: quote_expr!(cx, { write_stmts; Ok(()) } ), read: quote_expr!(cx, $ty { }), - }); + }) } fn binary_expr_item_struct( @@ -211,6 +217,7 @@ fn binary_expr_item_struct( &builder, ty, fields, + Some(builder.id("self")), ) } ast::VariantData::Struct(ref fields, _) => { @@ -219,8 +226,13 @@ fn binary_expr_item_struct( &builder, ty, fields, + Some(builder.id("self")), ) - } + }, + _ => { + cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct"); + Err(Error) + }, } } @@ -230,6 +242,7 @@ fn binary_expr_enum( type_ident: Ident, impl_generics: &ast::Generics, ty: P, + span: Span, enum_def: &ast::EnumDef, ) -> Result { let arms: Vec<_> = try!( @@ -242,6 +255,7 @@ fn binary_expr_enum( type_ident, impl_generics, ty.clone(), + span, variant, variant_index, ) @@ -250,22 +264,21 @@ fn binary_expr_enum( ); let (size_arms, write_arms, read_arms) = ( - arms.iter().map(|x| x.size).collect::>>(), - arms.iter().map(|x| x.write).collect::>>(), - arms.iter().map(|x| x.read).collect::>>()); + arms.iter().map(|x| x.size.clone()).collect::>(), + arms.iter().map(|x| x.write.clone()).collect::>(), + arms.iter().map(|x| x.read.clone()).collect::>()); Ok(BinaryExpressions { size: quote_expr!(cx, match *self { $size_arms }), - write: quote_stmt!(cx, match *self { $write_arms }; ), + write: quote_expr!(cx, match *self { $write_arms }; ), read: quote_expr!(cx, match *self { $read_arms }), - }); - + }) } struct BinaryArm { - size: P, - write: P, - read: P, + size: ast::Arm, + write: ast::Arm, + read: ast::Arm, } fn binary_expr_variant( @@ -274,10 +287,11 @@ fn binary_expr_variant( type_ident: Ident, generics: &ast::Generics, ty: P, + span: Span, variant: &ast::Variant, variant_index: usize, ) -> Result { - let type_name = ty.name; + let type_name = ::syntax::print::pprust::ty_to_string(&ty); let variant_ident = variant.node.name; @@ -303,12 +317,12 @@ fn binary_expr_variant( None, )); - let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); Ok(BinaryArm { - size: P(quote_arm!(cx, $pat => { $size_expr } )), - write: P(quote_arm!(cx, $pat => { $write } )), - read: P(quote_arm!(cx, $pat => { $read_expr } )), + size: quote_arm!(cx, $pat => { $size_expr } ), + write: quote_arm!(cx, $pat => { $write_expr } ), + read: quote_arm!(cx, $pat => { $read_expr } ), }) } ast::VariantData::Struct(ref fields, _) => { @@ -321,7 +335,7 @@ fn binary_expr_variant( .with_pats( field_names.iter() .zip(fields.iter()) - .map(|(id, field)|(name, builder.pat().ref_id(id)))) + .map(|(id, field)|(field.ident.unwrap(), builder.pat().ref_id(id)))) .build(); @@ -333,12 +347,16 @@ fn binary_expr_variant( None, )); - let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); Ok(BinaryArm { - size: P(quote_arm!(cx, $pat => { $size_expr } )), - write: P(quote_arm!(cx, $pat => { $write } )), - read: P(quote_arm!(cx, $pat => { $read_expr } )), + size: quote_arm!(cx, $pat => { $size_expr } ), + write: quote_arm!(cx, $pat => { $write_expr } ), + read: quote_arm!(cx, $pat => { $read_expr } ), }) - } + }, + _ => { + cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct"); + Err(Error) + }, } } diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 2cc07f2d0..08dd739df 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -16,10 +16,12 @@ //! Binary representation of types -pub trait BinaryConvertable { - fn size(&self) -> usize; +pub struct BinaryConvertError; - fn to_bytes(buffer: &mut [u8]); +pub trait BinaryConvertable : Sized { + fn size(&self) -> Result; - fn from_bytes(buffer: &[u8]) -> Self; + fn to_bytes(buffer: &mut [u8]) -> Result<(), BinaryConvertError>; + + fn from_bytes(buffer: &[u8]) -> Result; } diff --git a/ipc/tests/binary.rs b/ipc/tests/binary.rs new file mode 100644 index 000000000..87ac06d7e --- /dev/null +++ b/ipc/tests/binary.rs @@ -0,0 +1,17 @@ +// 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 . + +include!(concat!(env!("OUT_DIR"), "/binary.rs")); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in new file mode 100644 index 000000000..a3d52dfc9 --- /dev/null +++ b/ipc/tests/binary.rs.in @@ -0,0 +1,21 @@ +// 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 . + +#[derive(Binary)] +enum Root { + Top, + Middle(String) +} diff --git a/ipc/tests/build.rs b/ipc/tests/build.rs index 8515c14dd..c95868c67 100644 --- a/ipc/tests/build.rs +++ b/ipc/tests/build.rs @@ -60,4 +60,13 @@ pub fn main() { registry.expand("", &src, &dst).unwrap(); } + + // ipc pass + { + let src = Path::new("binary.rs.in"); + let dst = Path::new(&out_dir).join("binary.rs"); + let mut registry = syntex::Registry::new(); + codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } } diff --git a/ipc/tests/run.rs b/ipc/tests/run.rs index e694f32b0..c07145f77 100644 --- a/ipc/tests/run.rs +++ b/ipc/tests/run.rs @@ -29,3 +29,4 @@ pub mod service; mod examples; mod over_nano; mod nested; +mod binary; From 8b1197b33551d8dada568ba66ffd4b46fb2db71e Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 19:01:53 +0300 Subject: [PATCH 04/17] 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, + }, } From e3c20e1c64835e0da49f8db8cee72bc61c3d0b9e Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 19:10:41 +0300 Subject: [PATCH 05/17] fix for raw struct --- ipc/codegen/src/serialization.rs | 15 ++++++--------- ipc/tests/binary.rs.in | 7 +++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 596f54d1a..adcaaf2bf 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -167,7 +167,10 @@ fn binary_expr_struct( ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { let index_ident = builder.id(format!("__field{}", index)); - value_ident.and_then(|x| Some(quote_expr!(cx, $x . $index_ident .size()))) + value_ident.and_then(|x| { + let field_id = builder.id(field.ident.unwrap()); + Some(quote_expr!(cx, $x . $field_id .size())) + }) .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) }).collect(); @@ -184,9 +187,9 @@ fn binary_expr_struct( 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)); + let field_id = builder.id(field.ident.unwrap()); write_stmts.push( - quote_stmt!(cx, $x . $index_ident .to_bytes(&mut buffer[offset..next_line]);).unwrap()) + quote_stmt!(cx, $x . $field_id .to_bytes(&mut buffer[offset..next_line]);).unwrap()) }, None => { let index_ident = builder.id(format!("__field{}", index)); @@ -370,11 +373,5 @@ fn binary_expr_variant( read: quote_arm!(cx, $pat => { $read_expr } ), }) }, -// _ => { -// cx.span_bug(span, -// &format!("#[derive(Binary)] Unsupported enum variant content, expected tuple/struct, found: {:?}", -// variant)); -// Err(Error) -// }, } } diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index 875220535..a4f2b7538 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -25,3 +25,10 @@ enum Root { number2: u64, }, } + +#[derive(Binary)] +struct DoubleRoot { + x1: u32, + x2: u64, + x3: u32, +} From a61ab6d40f615febf27b7e5caaae7d6fc89c6ff0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 20:22:24 +0300 Subject: [PATCH 06/17] vec serialization --- ipc/codegen/src/serialization.rs | 19 +++++++--- ipc/rpc/src/binary.rs | 61 ++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index adcaaf2bf..bfaa8e7e0 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -301,6 +301,7 @@ fn binary_expr_variant( let type_name = ::syntax::print::pprust::ty_to_string(&ty); let variant_ident = variant.node.name; + let variant_index_ident = builder.id(format!("{}", variant_index)); match variant.node.data { ast::VariantData::Unit(_) => { @@ -310,7 +311,7 @@ fn binary_expr_variant( Ok(BinaryArm { size: quote_arm!(cx, $pat => { 0usize } ), - write: quote_arm!(cx, $pat => { Ok(()) } ), + write: quote_arm!(cx, $pat => { buffer[0] = $variant_index_ident; Ok(()) } ), read: quote_arm!(cx, $pat => { } ), }) }, @@ -336,11 +337,14 @@ 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 => { buffer[0] = $variant_index_ident; let buffer = &mut buffer[1..]; $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 } ), }) } @@ -369,7 +373,12 @@ fn binary_expr_variant( let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); 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 } ), }) }, diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 7f73c8242..02f0da954 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -27,6 +27,67 @@ pub trait BinaryConvertable : Sized { fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError>; fn from_bytes(buffer: &[u8]) -> Result; + + fn from_empty_bytes() -> Result { + Err(BinaryConvertError) + } + + 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]) -> Result<(), BinaryConvertError> { + match *self { None => Err(BinaryConvertError), Some(ref val) => val.to_bytes(buffer) } + } + + fn from_bytes(buffer: &[u8]) -> Result { + Ok(Some(try!(T::from_bytes(buffer)))) + } + + fn from_empty_bytes() -> Result { + Ok(None) + } + + 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]) -> Result<(), BinaryConvertError> { + let mut offset = 0usize; + for (index, item) in self.iter().enumerate() { + let item_end = offset + item.size(); + try!(item.to_bytes(&mut buffer[offset..item_end])); + offset = item_end; + } + Ok(()) + } + + fn from_bytes(buffer: &[u8]) -> Result { + Err(BinaryConvertError) + } + + fn from_empty_bytes() -> Result { + Ok(Self::new()) + } + + fn len_params() -> usize { + 1 + } } macro_rules! binary_fixed_size { From ffc10fec8ba85720d4623378597218151686be84 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 20 Apr 2016 23:02:29 +0300 Subject: [PATCH 07/17] read from bytes finished --- ipc/codegen/src/serialization.rs | 167 +++++++++++++++++++++++++++++-- ipc/tests/binary.rs.in | 5 +- 2 files changed, 161 insertions(+), 11 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index bfaa8e7e0..1af35422c 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -108,8 +108,7 @@ fn serialize_item( } fn from_bytes(buffer: &[u8]) -> Result { - //$read_expr - Err(::ipc::BinaryConvertError) + $read_expr } } ).unwrap()) @@ -164,6 +163,7 @@ fn binary_expr_struct( ty: P, fields: &[ast::StructField], value_ident: Option, + instance_ident: Option, ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { let index_ident = builder.id(format!("__field{}", index)); @@ -182,6 +182,11 @@ fn binary_expr_struct( let mut write_stmts = Vec::::new(); write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;).unwrap()); + + let mut map_stmts = Vec::::new(); + let field_amount = builder.id(&format!("{}",fields.len())); + map_stmts.push(quote_stmt!(cx, let mut map = vec![0usize; $field_amount];).unwrap()); + map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { let size_expr = &size_exprs[index]; write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap()); @@ -198,12 +203,26 @@ fn binary_expr_struct( } } write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); + + let field_index = builder.id(&format!("{}", index)); + let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); + map_stmts.push(quote_stmt!(cx, total = total + mem::size_of::<$field_type_ident>();).unwrap()); + }; + + let read_expr = if value_ident.is_some() { + let instance_create = named_fields_sequence(cx, &ty, fields); + quote_expr!(cx, { $map_stmts; $instance_create; Ok(result) }) + } + else { + let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); + quote_expr!(cx, { $map_stmts; Ok($map_variant) }) }; Ok(BinaryExpressions { size: total_size_expr, write: quote_expr!(cx, { $write_stmts; Ok(()) } ), - read: quote_expr!(cx, Err(::ipc::BinaryConvertError)), + read: read_expr, }) } @@ -223,6 +242,7 @@ fn binary_expr_item_struct( ty, fields, Some(builder.id("self")), + None, ) } ast::VariantData::Struct(ref fields, _) => { @@ -232,6 +252,7 @@ fn binary_expr_item_struct( ty, fields, Some(builder.id("self")), + None, ) }, _ => { @@ -270,15 +291,17 @@ fn binary_expr_enum( .collect() ); - let (size_arms, write_arms, read_arms) = ( + let (size_arms, write_arms, mut read_arms) = ( arms.iter().map(|x| x.size.clone()).collect::>(), arms.iter().map(|x| x.write.clone()).collect::>(), arms.iter().map(|x| x.read.clone()).collect::>()); + read_arms.push(quote_arm!(cx, _ => { Err(BinaryConvertError) } )); + Ok(BinaryExpressions { 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 }), + read: quote_expr!(cx, match buffer[0] { $read_arms }), }) } @@ -288,6 +311,132 @@ struct BinaryArm { read: ast::Arm, } +fn fields_sequence( + ext_cx: &ExtCtxt, + ty: &P, + fields: &[ast::StructField], + variant_ident: &ast::Ident, +) -> ast::Expr { + use syntax::parse::token; + use syntax::ast::TokenTree::Token; + + ::quasi::parse_expr_panic(&mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(Token(_sp, token::Ident(variant_ident.clone(), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + for (idx, field) in fields.iter().enumerate() { + if field.ident.is_some() { + tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap(), token::Plain))); + tt.push(Token(_sp, token::Colon)); + } + + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + token::Plain))); + tt.push(Token(_sp, token::ModSep)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + tt.push(Token(_sp, token::BinOp(token::And))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer"), token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::DotDot)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::Comma)); + } + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + + tt + }) + ).unwrap() +} + +fn named_fields_sequence( + ext_cx: &ExtCtxt, + ty: &P, + fields: &[ast::StructField], +) -> ast::Stmt { + use syntax::parse::token; + use syntax::ast::TokenTree::Token; + + ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("let"), token::Plain))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("result"), token::Plain))); + tt.push(Token(_sp, token::Eq)); + + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(ty)), + token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Brace))); + + for (idx, field) in fields.iter().enumerate() { + tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap(), token::Plain))); + tt.push(Token(_sp, token::Colon)); + + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + token::Plain))); + tt.push(Token(_sp, token::ModSep)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + tt.push(Token(_sp, token::BinOp(token::And))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer"), token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::DotDot)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::Comma)); + } + + tt.push(Token(_sp, token::CloseDelim(token::Brace))); + tt + }) + ).unwrap() +} + fn binary_expr_variant( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -309,10 +458,12 @@ fn binary_expr_variant( .id(type_ident).id(variant_ident) .build(); + let variant_val = builder.id(format!("{}::{}", type_ident, variant_ident)); + Ok(BinaryArm { size: quote_arm!(cx, $pat => { 0usize } ), write: quote_arm!(cx, $pat => { buffer[0] = $variant_index_ident; Ok(()) } ), - read: quote_arm!(cx, $pat => { } ), + read: quote_arm!(cx, $variant_index_ident => { Ok($variant_val) } ), }) }, ast::VariantData::Tuple(ref fields, _) => { @@ -334,6 +485,7 @@ fn binary_expr_variant( ty, fields, None, + Some(builder.id(format!("{}::{}", type_ident, variant_ident))), )); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); @@ -345,7 +497,7 @@ fn binary_expr_variant( let buffer = &mut buffer[1..]; $write_expr }), - read: quote_arm!(cx, $pat => { $read_expr } ), + read: quote_arm!(cx, $variant_index_ident => { $read_expr } ), }) } ast::VariantData::Struct(ref fields, _) => { @@ -368,6 +520,7 @@ fn binary_expr_variant( ty, fields, None, + Some(builder.id(format!("{}::{}", type_ident, variant_ident))), )); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index a4f2b7538..028fb9800 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -15,15 +15,12 @@ // along with Parity. If not, see . use ipc::*; +use std::mem; #[derive(Binary)] enum Root { Top, Middle(u32, u64), - Bottom { - number1: u32, - number2: u64, - }, } #[derive(Binary)] From bb6d47d0cd1fe59892569a7bc33fd731349bbb7a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 21 Apr 2016 22:18:13 +0300 Subject: [PATCH 08/17] finished with io --- ipc/codegen/src/serialization.rs | 38 ++++- ipc/rpc/src/binary.rs | 273 ++++++++++++++++++++++++++++--- 2 files changed, 284 insertions(+), 27 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 1af35422c..c2efc96c7 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -28,6 +28,7 @@ use syntax::ast::{ TraitRef, Ident, Generics, + TyKind, }; use syntax::ast; @@ -157,6 +158,23 @@ struct BinaryExpressions { pub read: P, } +fn is_variable_size(ty: &P) -> bool { + match ty.node { + TyKind::Vec(_) => true, + TyKind::FixedLengthVec(_, _) => false, + TyKind::Path(_, ref path) => { + path.segments[0].identifier.name.as_str() == "Option" || + path.segments[0].identifier.name.as_str() == "Result" || + path.segments[0].identifier.name.as_str() == "String" + }, + _ => { false } + } +} + +fn variable_sizes(cx: &ExtCtxt, fields: &[ast::StructField]) -> Vec { + fields.iter().map(|field| is_variable_size(&field.ty)).collect::>() +} + fn binary_expr_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -165,13 +183,21 @@ fn binary_expr_struct( value_ident: Option, instance_ident: Option, ) -> Result { + let variable_sizes = variable_size_indexes(fields); + let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { - let index_ident = builder.id(format!("__field{}", index)); - value_ident.and_then(|x| { - let field_id = builder.id(field.ident.unwrap()); - Some(quote_expr!(cx, $x . $field_id .size())) - }) - .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) + if variable_sizes[index] { + let index_ident = builder.id(format!("__field{}", index)); + value_ident.and_then(|x| { + let field_id = builder.id(field.ident.unwrap()); + Some(quote_expr!(cx, $x . $field_id .size())) + }) + .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) + } + else { + let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + quote_expr!(cx, mem::sizeof_of::()); + } }).collect(); let mut total_size_expr = size_exprs[0].clone(); diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 02f0da954..61eb9277f 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -16,17 +16,21 @@ //! Binary representation of types -use util::bytes::*; +use util::bytes::Populatable; use std::mem; +use std::collections::VecDeque; +#[derive(Debug)] pub struct BinaryConvertError; pub trait BinaryConvertable : Sized { - fn size(&self) -> usize; + fn size(&self) -> usize { + mem::size_of::() + } - fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError>; + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError>; - fn from_bytes(buffer: &[u8]) -> Result; + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result; fn from_empty_bytes() -> Result { Err(BinaryConvertError) @@ -42,12 +46,12 @@ impl BinaryConvertable for Option where T: BinaryConvertable { match * self { None => 0, Some(ref val) => val.size() } } - fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError> { - match *self { None => Err(BinaryConvertError), Some(ref val) => val.to_bytes(buffer) } + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + match *self { None => Err(BinaryConvertError), Some(ref val) => val.to_bytes(buffer, length_stack) } } - fn from_bytes(buffer: &[u8]) -> Result { - Ok(Some(try!(T::from_bytes(buffer)))) + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + Ok(Some(try!(T::from_bytes(buffer, length_stack)))) } fn from_empty_bytes() -> Result { @@ -67,18 +71,52 @@ impl BinaryConvertable for Vec where T: BinaryConvertable { } } - fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError> { + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { let mut offset = 0usize; - for (index, item) in self.iter().enumerate() { - let item_end = offset + item.size(); - try!(item.to_bytes(&mut buffer[offset..item_end])); - offset = item_end; + 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]) -> Result { - Err(BinaryConvertError) + 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, + }); + + loop { + let next_size = match T::len_params() { + 0 => mem::size_of::(), + _ => try!(length_stack.pop_front().ok_or(BinaryConvertError)), + }; + 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 > buffer.len() { + return Err(BinaryConvertError) + } + + } + + Ok(result) } fn from_empty_bytes() -> Result { @@ -90,14 +128,79 @@ impl BinaryConvertable for Vec where T: BinaryConvertable { } } +pub fn deserialize_from(r: &mut R) -> Result + where R: ::std::io::Read, + T: BinaryConvertable +{ + let mut fake_stack = VecDeque::new(); + let mut length_stack = VecDeque::::new(); + let mut size_buffer = [0u8; 8]; + try!(r.read(&mut size_buffer[..]).map_err(|_| BinaryConvertError)); + let stack_len = try!(u64::from_bytes(&mut size_buffer[..], &mut fake_stack)) as usize; + if stack_len > 0 { + let mut header_buffer = Vec::with_capacity(stack_len * 8); + unsafe { header_buffer.set_len(stack_len * 8); }; + + try!(r.read(&mut header_buffer[..]).map_err(|_| BinaryConvertError)); + for idx in 0..stack_len { + let stack_item = try!(u64::from_bytes(&header_buffer[idx*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(&size_buffer[..], &mut fake_stack)) as usize; + + let mut data = Vec::with_capacity(size); + unsafe { data.set_len(size) }; + try!(r.read(&mut data).map_err(|_| BinaryConvertError)); + + T::from_bytes(&data[..], &mut length_stack) +} + +pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryConvertError> + where W: ::std::io::Write, + T: BinaryConvertable +{ + let mut length_stack = VecDeque::::new(); + let mut fake_stack = VecDeque::new(); + let mut size_buffer = [0u8; 8]; + + let size = t.size(); + 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[..]).map_err(|_| BinaryConvertError)); + 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[..]).map_err(|_| BinaryConvertError)); + } + + try!((size as u64).to_bytes(&mut size_buffer[..], &mut fake_stack)); + try!(w.write(&size_buffer[..]).map_err(|_| BinaryConvertError)); + + try!(w.write(&buffer[..]).map_err(|_| BinaryConvertError)); + + Ok(()) +} + 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 { + fn from_bytes(bytes: &[u8], _length_stack: &mut VecDeque) -> 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), @@ -108,7 +211,7 @@ macro_rules! binary_fixed_size { Ok(res) } - fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError> { + 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 _; @@ -124,3 +227,131 @@ macro_rules! binary_fixed_size { binary_fixed_size!(u64); binary_fixed_size!(u32); binary_fixed_size!(bool); + +#[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::>::from_bytes(&data[..], &mut length_stack).unwrap(); + + assert_eq!(v, de_v); +} + +#[test] +fn serialize_into_ok() { + use std::io::Cursor; + let mut buff = Cursor::new(vec![0; 128]); + + let mut v = Vec::new(); + v.push(Some(5u64)); + v.push(None); + v.push(Some(10u64)); + v.push(None); + v.push(Some(12u64)); + + serialize_into(&v, &mut buff).unwrap(); + assert_eq!(5, buff.get_ref()[0]); + assert_eq!(8, buff.get_ref()[8]); + assert_eq!(0, buff.get_ref()[16]); + assert_eq!(8, buff.get_ref()[24]); +} + +#[test] +fn deserialize_from_ok() { + use std::io::Cursor; + let mut buff = Cursor::new(vec![ + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 16u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 10u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + ]); + + let vec = deserialize_from::, _>(&mut buff).unwrap(); + + assert_eq!(vec![10u64, 5u64], vec); +} + +#[test] +fn serialize_into_deserialize_from() { + use std::io::{Cursor, SeekFrom, Seek}; + + let mut buff = Cursor::new(vec![0u8; 1024]); + let mut v = Vec::new(); + v.push(Some(5u64)); + v.push(None); + v.push(Some(10u64)); + v.push(None); + v.push(Some(12u64)); + + serialize_into(&v, &mut buff).unwrap(); + buff.seek(SeekFrom::Start(0)).unwrap(); + let de_v = deserialize_from::>, _>(&mut buff).unwrap(); + assert_eq!(v, de_v); +} From 729f9c803dffb56a4e7e25a66818f61dc948b969 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 21 Apr 2016 23:03:05 +0300 Subject: [PATCH 09/17] codegen updated --- ipc/codegen/src/serialization.rs | 94 ++++++++++++++++++-------------- ipc/tests/binary.rs.in | 13 +++-- ipc/tests/examples.rs | 16 ++++++ 3 files changed, 75 insertions(+), 48 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index c2efc96c7..1c8fa32af 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -104,13 +104,17 @@ fn serialize_item( $size_expr } - fn to_bytes(&self, buffer: &mut [u8]) -> Result<(), BinaryConvertError> { + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { $write_expr } - fn from_bytes(buffer: &[u8]) -> Result { + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { $read_expr } + + fn len_params() -> usize { + 1 + } } ).unwrap()) } @@ -158,23 +162,6 @@ struct BinaryExpressions { pub read: P, } -fn is_variable_size(ty: &P) -> bool { - match ty.node { - TyKind::Vec(_) => true, - TyKind::FixedLengthVec(_, _) => false, - TyKind::Path(_, ref path) => { - path.segments[0].identifier.name.as_str() == "Option" || - path.segments[0].identifier.name.as_str() == "Result" || - path.segments[0].identifier.name.as_str() == "String" - }, - _ => { false } - } -} - -fn variable_sizes(cx: &ExtCtxt, fields: &[ast::StructField]) -> Vec { - fields.iter().map(|field| is_variable_size(&field.ty)).collect::>() -} - fn binary_expr_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -183,24 +170,26 @@ fn binary_expr_struct( value_ident: Option, instance_ident: Option, ) -> Result { - let variable_sizes = variable_size_indexes(fields); let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { - if variable_sizes[index] { - let index_ident = builder.id(format!("__field{}", index)); - value_ident.and_then(|x| { - let field_id = builder.id(field.ident.unwrap()); - Some(quote_expr!(cx, $x . $field_id .size())) - }) - .unwrap_or_else(|| quote_expr!(cx, $index_ident .size())) - } - else { - let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); - quote_expr!(cx, mem::sizeof_of::()); - } + let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + let index_ident = builder.id(format!("__field{}", index)); + value_ident.and_then(|x| { + let field_id = builder.id(field.ident.unwrap()); + Some(quote_expr!(cx, + match $field_type_ident::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => $x. $field_id .size() + })) + }) + .unwrap_or_else(|| quote_expr!(cx, match $field_type_ident::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => $index_ident .size() + })) }).collect(); - let mut total_size_expr = size_exprs[0].clone(); + let first_size_expr = size_exprs[0].clone(); + let mut total_size_expr = quote_expr!(cx, 0usize + $first_size_expr); for index in 1..size_exprs.len() { let next_expr = size_exprs[index].clone(); total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr); @@ -215,25 +204,36 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { let size_expr = &size_exprs[index]; - write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap()); - match value_ident { + let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + + let member_expr = match value_ident { Some(x) => { let field_id = builder.id(field.ident.unwrap()); - write_stmts.push( - quote_stmt!(cx, $x . $field_id .to_bytes(&mut buffer[offset..next_line]);).unwrap()) + quote_expr!(cx, $x . $field_id) }, None => { let index_ident = builder.id(format!("__field{}", index)); - write_stmts.push( - quote_stmt!(cx, $index_ident .to_bytes(&mut buffer[offset..next_line]);).unwrap()) + quote_expr!(cx, $index_ident) } - } + }; + + write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => { let size = $member_expr .size(); length_stack.push_back(size); size } + }).unwrap()); + + write_stmts.push(quote_stmt!(cx, + $member_expr .to_bytes(&mut buffer[offset..next_line], length_stack);).unwrap()); + write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); let field_index = builder.id(&format!("{}", index)); - let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); - map_stmts.push(quote_stmt!(cx, total = total + mem::size_of::<$field_type_ident>();).unwrap()); + map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => length_stack.pop_front().unwrap() + }).unwrap()); + map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); }; let read_expr = if value_ident.is_some() { @@ -386,6 +386,10 @@ fn fields_sequence( tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + + tt.push(Token(_sp, token::Comma)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("length_stack"), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); tt.push(Token(_sp, token::CloseDelim(token::Paren))); tt.push(Token(_sp, token::Comma)); @@ -450,8 +454,14 @@ fn named_fields_sequence( tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); tt.push(Token(_sp, token::OpenDelim(token::Bracket))); tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + + tt.push(Token(_sp, token::Comma)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("length_stack"), token::Plain))); + + tt.push(Token(_sp, token::CloseDelim(token::Paren))); tt.push(Token(_sp, token::CloseDelim(token::Paren))); tt.push(Token(_sp, token::Comma)); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index 028fb9800..c3dd224b2 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -16,16 +16,17 @@ use ipc::*; use std::mem; +use std::collections::VecDeque; #[derive(Binary)] -enum Root { +pub enum Root { Top, Middle(u32, u64), } -#[derive(Binary)] -struct DoubleRoot { - x1: u32, - x2: u64, - x3: u32, +#[derive(Binary, PartialEq, Debug)] +pub struct DoubleRoot { + pub x1: u32, + pub x2: u64, + pub x3: u32, } diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 5a4324ec4..f20cba793 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -18,6 +18,7 @@ mod tests { use super::super::service::*; + use super::super::binary::*; use super::super::nested::{DBClient,DBWriter}; use ipc::*; use devtools::*; @@ -143,4 +144,19 @@ mod tests { assert!(result.is_ok()); } + + #[test] + fn can_serialize_dummy_structs() { + let mut socket = TestSocket::new(); + + let struct_ = DoubleRoot { x1: 0, x2: 100, x3: 100000}; + let res = ::ipc::binary::serialize_into(&struct_, &mut socket); + + assert!(res.is_ok()); + + let mut read_socket = TestSocket::new_ready(socket.write_buffer.clone()); + let new_struct: DoubleRoot = ::ipc::binary::deserialize_from(&mut read_socket).unwrap(); + + assert_eq!(struct_, new_struct); + } } From 04e704603fba39225308b036580887665f515098 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 21 Apr 2016 23:23:06 +0300 Subject: [PATCH 10/17] fixed warnings --- ipc/codegen/src/serialization.rs | 43 +++++++++++++------------------- ipc/tests/binary.rs | 2 ++ ipc/tests/binary.rs.in | 1 + 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 1c8fa32af..8a5a8716a 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -18,17 +18,7 @@ use aster; use syntax::ast::{ MetaItem, Item, - ImplItemKind, - ImplItem, - MethodSig, - Arg, - PatKind, - FunctionRetTy, - Ty, - TraitRef, Ident, - Generics, - TyKind, }; use syntax::ast; @@ -203,7 +193,6 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, let mut map = vec![0usize; $field_amount];).unwrap()); map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { - let size_expr = &size_exprs[index]; let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); let member_expr = match value_ident { @@ -223,7 +212,7 @@ fn binary_expr_struct( }).unwrap()); write_stmts.push(quote_stmt!(cx, - $member_expr .to_bytes(&mut buffer[offset..next_line], length_stack);).unwrap()); + if let Err(e) = $member_expr .to_bytes(&mut buffer[offset..next_line], length_stack) { return Err(e) };).unwrap()); write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); @@ -339,7 +328,7 @@ struct BinaryArm { fn fields_sequence( ext_cx: &ExtCtxt, - ty: &P, + _ty: &P, fields: &[ast::StructField], variant_ident: &ast::Ident, ) -> ast::Expr { @@ -381,10 +370,14 @@ fn fields_sequence( tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::DotDot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + + if idx+1 != fields.len() { + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + } + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::Comma)); @@ -451,11 +444,13 @@ fn named_fields_sequence( tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::DotDot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + if idx + 1 != fields.len() { + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + } - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::CloseDelim(token::Bracket))); tt.push(Token(_sp, token::Comma)); @@ -477,14 +472,12 @@ fn binary_expr_variant( cx: &ExtCtxt, builder: &aster::AstBuilder, type_ident: Ident, - generics: &ast::Generics, + _generics: &ast::Generics, ty: P, - span: Span, + _span: Span, variant: &ast::Variant, variant_index: usize, ) -> Result { - let type_name = ::syntax::print::pprust::ty_to_string(&ty); - let variant_ident = variant.node.name; let variant_index_ident = builder.id(format!("{}", variant_index)); diff --git a/ipc/tests/binary.rs b/ipc/tests/binary.rs index 87ac06d7e..f6bf8d5b5 100644 --- a/ipc/tests/binary.rs +++ b/ipc/tests/binary.rs @@ -14,4 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +#![allow(dead_code, unused_assignments)] // codegen issues + include!(concat!(env!("OUT_DIR"), "/binary.rs")); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index c3dd224b2..689df8e27 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . + use ipc::*; use std::mem; use std::collections::VecDeque; From c97cb5d66572e31a0a068ad3f4c841f198369ae6 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 22 Apr 2016 16:37:22 +0300 Subject: [PATCH 11/17] struct with reference serialization --- ipc/codegen/src/codegen.rs | 4 ++-- ipc/codegen/src/serialization.rs | 33 +++++++++++++++++++++++--------- ipc/tests/binary.rs | 2 +- ipc/tests/binary.rs.in | 5 +++++ 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 1744f9a9c..9476c2d0e 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -298,14 +298,14 @@ fn implement_dispatch_arms( .map(|dispatch| { index = index + 1; implement_dispatch_arm(cx, builder, index as u32, dispatch, buffer, replacements) }).collect() } -fn strip_ptr(ty: &P) -> P { +pub fn strip_ptr(ty: &P) -> P { if let ast::TyKind::Rptr(_, ref ptr_mut) = ty.node { ptr_mut.ty.clone() } else { ty.clone() } } -fn has_ptr(ty: &P) -> bool { +pub fn has_ptr(ty: &P) -> bool { if let ast::TyKind::Rptr(_, ref ptr_mut) = ty.node { true } diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 8a5a8716a..a7e172ee1 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -29,6 +29,8 @@ use syntax::ptr::P; pub struct Error; +use super::codegen; + pub fn expand_serialization_implementation( cx: &mut ExtCtxt, span: Span, @@ -162,7 +164,9 @@ fn binary_expr_struct( ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { - let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + let field_type_ident = builder.id( + &::syntax::print::pprust::ty_to_string( + &codegen::strip_ptr(&field.ty))); let index_ident = builder.id(format!("__field{}", index)); value_ident.and_then(|x| { let field_id = builder.id(field.ident.unwrap()); @@ -193,7 +197,9 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, let mut map = vec![0usize; $field_amount];).unwrap()); map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { - let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + let field_type_ident = builder.id( + &::syntax::print::pprust::ty_to_string( + &codegen::strip_ptr(&field.ty))); let member_expr = match value_ident { Some(x) => { @@ -225,13 +231,21 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); }; - let read_expr = if value_ident.is_some() { - let instance_create = named_fields_sequence(cx, &ty, fields); - quote_expr!(cx, { $map_stmts; $instance_create; Ok(result) }) - } - else { - let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); - quote_expr!(cx, { $map_stmts; Ok($map_variant) }) + let read_expr = match fields.iter().any(|f| codegen::has_ptr(&f.ty)) { + true => { + // cannot create structs with pointers + quote_expr!(cx, Err(::ipc::binary::BinaryConvertError)) + }, + false => { + if value_ident.is_some() { + let instance_create = named_fields_sequence(cx, &ty, fields); + quote_expr!(cx, { $map_stmts; $instance_create; Ok(result) }) + } + else { + let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); + quote_expr!(cx, { $map_stmts; Ok($map_variant) }) + } + } }; Ok(BinaryExpressions { @@ -553,6 +567,7 @@ fn binary_expr_variant( )); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); + Ok(BinaryArm { size: quote_arm!(cx, $pat => { $size_expr } ), write: quote_arm!(cx, diff --git a/ipc/tests/binary.rs b/ipc/tests/binary.rs index f6bf8d5b5..ab4adee39 100644 --- a/ipc/tests/binary.rs +++ b/ipc/tests/binary.rs @@ -14,6 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -#![allow(dead_code, unused_assignments)] // codegen issues +#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues include!(concat!(env!("OUT_DIR"), "/binary.rs")); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index 689df8e27..710752237 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -31,3 +31,8 @@ pub struct DoubleRoot { pub x2: u64, pub x3: u32, } + +#[derive(Binary, PartialEq, Debug)] +pub struct ReferenceStruct<'a> { + pub ref_data: &'a u64, +} From 6b1db6a656090693702af87e3fda55fe1afa2f91 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 22 Apr 2016 16:46:09 +0300 Subject: [PATCH 12/17] merge bugs and fix warnings --- ipc/codegen/src/codegen.rs | 2 +- ipc/codegen/src/serialization.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 2f4e1608f..4709eceaf 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -305,7 +305,7 @@ pub fn strip_ptr(ty: &P) -> P { else { ty.clone() } } -fn has_ptr(ty: &P) -> bool { +pub fn has_ptr(ty: &P) -> bool { if let ast::TyKind::Rptr(_, ref _ptr_mut) = ty.node { true } diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index a7e172ee1..65d94d162 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -111,6 +111,7 @@ fn serialize_item( ).unwrap()) } +#[allow(unreachable_code)] fn binary_expr( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -128,7 +129,7 @@ fn binary_expr( item.span, variant_data, ) - } + }, ast::ItemKind::Enum(ref enum_def, _) => { binary_expr_enum( cx, @@ -139,7 +140,7 @@ fn binary_expr( item.span, enum_def, ) - } + }, _ => { cx.span_bug(item.span, "expected ItemStruct or ItemEnum in #[derive(Binary)]"); @@ -255,10 +256,11 @@ fn binary_expr_struct( }) } +#[allow(unreachable_code)] fn binary_expr_item_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, - impl_generics: &ast::Generics, + _impl_generics: &ast::Generics, ty: P, span: Span, variant_data: &ast::VariantData, From 53281a9454512263ae9e00cfc1c15c58910f6f72 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 23 Apr 2016 18:49:39 +0300 Subject: [PATCH 13/17] fixed spaces --- ipc/codegen/src/serialization.rs | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 65d94d162..f4f328dad 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -60,9 +60,9 @@ pub fn expand_serialization_implementation( } fn serialize_item( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, + cx: &ExtCtxt, + builder: &aster::AstBuilder, + item: &Item, ) -> Result, Error> { let generics = match item.node { ast::ItemKind::Struct(_, ref generics) => generics, @@ -296,13 +296,13 @@ fn binary_expr_item_struct( } fn binary_expr_enum( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - impl_generics: &ast::Generics, - ty: P, + cx: &ExtCtxt, + builder: &aster::AstBuilder, + type_ident: Ident, + impl_generics: &ast::Generics, + ty: P, span: Span, - enum_def: &ast::EnumDef, + enum_def: &ast::EnumDef, ) -> Result { let arms: Vec<_> = try!( enum_def.variants.iter() @@ -345,7 +345,7 @@ struct BinaryArm { fn fields_sequence( ext_cx: &ExtCtxt, _ty: &P, - fields: &[ast::StructField], + fields: &[ast::StructField], variant_ident: &ast::Ident, ) -> ast::Expr { use syntax::parse::token; @@ -413,7 +413,7 @@ fn fields_sequence( fn named_fields_sequence( ext_cx: &ExtCtxt, ty: &P, - fields: &[ast::StructField], + fields: &[ast::StructField], ) -> ast::Stmt { use syntax::parse::token; use syntax::ast::TokenTree::Token; @@ -485,14 +485,14 @@ fn named_fields_sequence( } fn binary_expr_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - _generics: &ast::Generics, - ty: P, + cx: &ExtCtxt, + builder: &aster::AstBuilder, + type_ident: Ident, + _generics: &ast::Generics, + ty: P, _span: Span, - variant: &ast::Variant, - variant_index: usize, + variant: &ast::Variant, + variant_index: usize, ) -> Result { let variant_ident = variant.node.name; let variant_index_ident = builder.id(format!("{}", variant_index)); From 4709edeffffe51d8a229c5848a053ebf4e89fb83 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 23 Apr 2016 18:50:12 +0300 Subject: [PATCH 14/17] another fixed spaces --- ipc/codegen/src/serialization.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index f4f328dad..3d8d42347 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -48,15 +48,15 @@ pub fn expand_serialization_implementation( let builder = aster::AstBuilder::new().span(span); - let impl_item = match serialize_item(cx, &builder, &item) { - Ok(item) => item, - Err(Error) => { - // An error occured, but it should have been reported already. - return; - } - }; + let impl_item = match serialize_item(cx, &builder, &item) { + Ok(item) => item, + Err(Error) => { + // An error occured, but it should have been reported already. + return; + } + }; - push(Annotatable::Item(impl_item)) + push(Annotatable::Item(impl_item)) } fn serialize_item( From 5d06b04e41882f86a6543bf1bc8f2f16b02e2711 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 23 Apr 2016 18:52:12 +0300 Subject: [PATCH 15/17] final space --- ipc/codegen/src/serialization.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 3d8d42347..2c86d4f93 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -159,7 +159,7 @@ fn binary_expr_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, ty: P, - fields: &[ast::StructField], + fields: &[ast::StructField], value_ident: Option, instance_ident: Option, ) -> Result { From 4670fd43ed1f01d57daea37e2ec0cb57086fe36b Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 23 Apr 2016 18:53:09 +0300 Subject: [PATCH 16/17] and some more spaces --- ipc/codegen/src/serialization.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 2c86d4f93..59af56ba5 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -113,11 +113,11 @@ fn serialize_item( #[allow(unreachable_code)] fn binary_expr( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, - impl_generics: &ast::Generics, - ty: P, + cx: &ExtCtxt, + builder: &aster::AstBuilder, + item: &Item, + impl_generics: &ast::Generics, + ty: P, ) -> Result { match item.node { ast::ItemKind::Struct(ref variant_data, _) => { From 2947a91c3ee96f2b43e19076a108bbcb65ec4912 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sun, 24 Apr 2016 21:34:19 +0300 Subject: [PATCH 17/17] commas --- ipc/codegen/src/serialization.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 59af56ba5..7f5bed5b1 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -43,7 +43,7 @@ pub fn expand_serialization_implementation( _ => { cx.span_err(meta_item.span, "`#[derive(Binary)]` may only be applied to structs and enums"); return; - } + }, }; let builder = aster::AstBuilder::new().span(span); @@ -53,7 +53,7 @@ pub fn expand_serialization_implementation( Err(Error) => { // An error occured, but it should have been reported already. return; - } + }, }; push(Annotatable::Item(impl_item)) @@ -72,7 +72,7 @@ fn serialize_item( item.span, "`#[derive(Binary)]` may only be applied to structs and enums"); return Err(Error); - } + }, }; let ty = builder.ty().path() @@ -145,7 +145,7 @@ fn binary_expr( cx.span_bug(item.span, "expected ItemStruct or ItemEnum in #[derive(Binary)]"); Err(Error) - } + }, } } @@ -174,12 +174,12 @@ fn binary_expr_struct( Some(quote_expr!(cx, match $field_type_ident::len_params() { 0 => mem::size_of::<$field_type_ident>(), - _ => $x. $field_id .size() + _ => $x. $field_id .size(), })) }) .unwrap_or_else(|| quote_expr!(cx, match $field_type_ident::len_params() { 0 => mem::size_of::<$field_type_ident>(), - _ => $index_ident .size() + _ => $index_ident .size(), })) }).collect(); @@ -210,12 +210,12 @@ fn binary_expr_struct( None => { let index_ident = builder.id(format!("__field{}", index)); quote_expr!(cx, $index_ident) - } + }, }; write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident::len_params() { 0 => mem::size_of::<$field_type_ident>(), - _ => { let size = $member_expr .size(); length_stack.push_back(size); size } + _ => { let size = $member_expr .size(); length_stack.push_back(size); size }, }).unwrap()); write_stmts.push(quote_stmt!(cx, @@ -227,7 +227,7 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident::len_params() { 0 => mem::size_of::<$field_type_ident>(), - _ => length_stack.pop_front().unwrap() + _ => length_stack.pop_front().unwrap(), }).unwrap()); map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); }; @@ -246,7 +246,7 @@ fn binary_expr_struct( let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); quote_expr!(cx, { $map_stmts; Ok($map_variant) }) } - } + }, }; Ok(BinaryExpressions { @@ -275,7 +275,7 @@ fn binary_expr_item_struct( Some(builder.id("self")), None, ) - } + }, ast::VariantData::Struct(ref fields, _) => { binary_expr_struct( cx, @@ -544,7 +544,7 @@ fn binary_expr_variant( }), read: quote_arm!(cx, $variant_index_ident => { $read_expr } ), }) - } + }, ast::VariantData::Struct(ref fields, _) => { let field_names: Vec<_> = (0 .. fields.len()) .map(|i| builder.id(format!("__field{}", i)))