From dcb7546d6d1263fcb34697ecd75971abaec1a13d Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 22 Apr 2016 19:45:09 +0300 Subject: [PATCH 1/6] refactored to new serialization --- ipc/codegen/src/codegen.rs | 114 ++++---------- ipc/codegen/src/lib.rs.in | 1 - ipc/codegen/src/serialization.rs | 25 ++-- ipc/codegen/src/typegen.rs | 247 ------------------------------- ipc/rpc/src/binary.rs | 120 +++++++++++++++ ipc/tests/build.rs | 4 +- ipc/tests/examples.rs | 18 ++- ipc/tests/nested.rs | 1 + ipc/tests/nested.rs.in | 6 +- ipc/tests/service.rs | 1 + ipc/tests/service.rs.in | 36 +---- 11 files changed, 192 insertions(+), 381 deletions(-) delete mode 100644 ipc/codegen/src/typegen.rs diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 4709eceaf..253b298f4 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -36,9 +36,6 @@ use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; -use super::typegen; -use std::collections::HashMap; - pub struct Error; const RESERVED_MESSAGE_IDS: u16 = 16; @@ -73,7 +70,7 @@ pub fn expand_ipc_implementation( fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) { let handshake_item = quote_item!(cx, - #[derive(Serialize, Deserialize)] + #[derive(Binary)] pub struct BinHandshake { api_version: String, protocol_version: String, @@ -95,7 +92,6 @@ fn push_invoke_signature_aster( builder: &aster::AstBuilder, implement: &ImplItem, signature: &MethodSig, - replacements: &HashMap>, push: &mut FnMut(Annotatable), ) -> Dispatch { let inputs = &signature.decl.inputs; @@ -113,12 +109,11 @@ fn push_invoke_signature_aster( let arg_ty = &inputs[skip-1].ty; let mut tree = builder.item() - .attr().word("derive(Serialize, Deserialize)") + .attr().word("derive(Binary)") .attr().word("allow(non_camel_case_types)") .struct_(name_str.as_str()) .field(arg_name.as_str()).ty() - .build(typegen::argument_replacement(builder, replacements, arg_ty) - .unwrap_or(strip_ptr(arg_ty))); + .build(strip_ptr(arg_ty)); arg_names.push(arg_name); arg_tys.push(arg_ty.clone()); @@ -126,9 +121,7 @@ fn push_invoke_signature_aster( let arg_name = format!("{}", field_name(builder, &arg)); let arg_ty = &arg.ty; - tree = tree.field(arg_name.as_str()).ty().build( - typegen::argument_replacement(builder, replacements, arg_ty).unwrap_or(strip_ptr(arg_ty)) - ); + tree = tree.field(arg_name.as_str()).ty().build(strip_ptr(arg_ty)); arg_names.push(arg_name); arg_tys.push(arg_ty.clone()); } @@ -145,7 +138,7 @@ fn push_invoke_signature_aster( FunctionRetTy::Ty(ref ty) => { let name_str = format!("{}_output", implement.ident.name.as_str()); let tree = builder.item() - .attr().word("derive(Serialize, Deserialize)") + .attr().word("derive(Binary)") .attr().word("allow(non_camel_case_types)") .struct_(name_str.as_str()) .field(format!("payload")).ty().build(ty.clone()); @@ -184,20 +177,13 @@ fn implement_dispatch_arm_invoke_stmt( cx: &ExtCtxt, builder: &aster::AstBuilder, dispatch: &Dispatch, - replacements: &HashMap>, ) -> ast::Stmt { let function_name = builder.id(dispatch.function_name.as_str()); let input_args_exprs = dispatch.input_arg_names.iter().enumerate().map(|(arg_index, arg_name)| { let arg_ident = builder.id(arg_name); - let expr = if typegen::argument_replacement(builder, replacements, &dispatch.input_arg_tys[arg_index]).is_some() { - quote_expr!(cx, input. $arg_ident .into()) - } - else { - quote_expr!(cx, input. $arg_ident) - }; - + let expr = quote_expr!(cx, input. $arg_ident); if has_ptr(&dispatch.input_arg_tys[arg_index]) { quote_expr!(cx, & $expr) } else { expr } }).collect::>>(); @@ -211,9 +197,9 @@ fn implement_dispatch_arm_invoke_stmt( let mut tt = ::std::vec::Vec::new(); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("bincode"), ::syntax::parse::token::ModName))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("ipc"), ::syntax::parse::token::ModName))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("serde"), ::syntax::parse::token::ModName))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("binary"), ::syntax::parse::token::ModName))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("serialize"), ::syntax::parse::token::Plain))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); @@ -229,13 +215,6 @@ fn implement_dispatch_arm_invoke_stmt( } tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Comma)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("bincode"), ::syntax::parse::token::ModName))); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("SizeLimit"), ::syntax::parse::token::ModName))); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("Infinite"), ::syntax::parse::token::Plain))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Dot)); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("unwrap"), ::syntax::parse::token::Plain))); @@ -251,16 +230,15 @@ fn implement_dispatch_arm_invoke( builder: &aster::AstBuilder, dispatch: &Dispatch, buffer: bool, - replacements: &HashMap>, ) -> P { let deserialize_expr = if buffer { - quote_expr!(cx, ::bincode::serde::deserialize(buf).expect("ipc deserialization error, aborting")) + quote_expr!(cx, ::ipc::binary::deserialize(buf).expect("ipc deserialization error, aborting")) } else { - quote_expr!(cx, ::bincode::serde::deserialize_from(r, ::bincode::SizeLimit::Infinite).expect("ipc deserialization error, aborting")) + quote_expr!(cx, ::ipc::binary::deserialize_from(r).expect("ipc deserialization error, aborting")) }; - let invoke_serialize_stmt = implement_dispatch_arm_invoke_stmt(cx, builder, dispatch, replacements); + let invoke_serialize_stmt = implement_dispatch_arm_invoke_stmt(cx, builder, dispatch); dispatch.input_type_name.as_ref().map(|val| { let input_type_id = builder.id(val.clone().as_str()); quote_expr!(cx, { @@ -277,11 +255,10 @@ fn implement_dispatch_arm( index: u32, dispatch: &Dispatch, buffer: bool, - replacements: &HashMap>, ) -> ast::Arm { let index_ident = builder.id(format!("{}", index + (RESERVED_MESSAGE_IDS as u32)).as_str()); - let invoke_expr = implement_dispatch_arm_invoke(cx, builder, dispatch, buffer, replacements); + let invoke_expr = implement_dispatch_arm_invoke(cx, builder, dispatch, buffer); quote_arm!(cx, $index_ident => { $invoke_expr } ) } @@ -290,12 +267,11 @@ fn implement_dispatch_arms( builder: &aster::AstBuilder, dispatches: &[Dispatch], buffer: bool, - replacements: &HashMap>, ) -> Vec { let mut index = -1; dispatches.iter() - .map(|dispatch| { index = index + 1; implement_dispatch_arm(cx, builder, index as u32, dispatch, buffer, replacements) }).collect() + .map(|dispatch| { index = index + 1; implement_dispatch_arm(cx, builder, index as u32, dispatch, buffer) }).collect() } pub fn strip_ptr(ty: &P) -> P { @@ -349,10 +325,10 @@ fn implement_client_method_body( .ty().ref_() .lifetime("'a") .ty() - .build(typegen::argument_replacement(builder, &interface_map.replacements, &static_ty).unwrap_or(static_ty.clone())); + .build(static_ty.clone()); let mut tree = builder.item() - .attr().word("derive(Serialize)") + .attr().word("derive(Binary)") .struct_("Request") .generics() .lifetime_name("'a") @@ -368,7 +344,7 @@ fn implement_client_method_body( .ty().ref_() .lifetime("'a") .ty() - .build(typegen::argument_replacement(builder, &interface_map.replacements, &static_ty).unwrap_or(static_ty)); + .build(static_ty); tree = tree.field(arg_name).ty().build(arg_ty); } @@ -395,28 +371,12 @@ fn implement_client_method_body( tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("Request"), ::syntax::parse::token::Plain))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); - for (idx, arg) in dispatch.input_arg_names.iter().enumerate() { + for arg in dispatch.input_arg_names.iter() { tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg.as_str()), ::syntax::parse::token::Plain))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Colon)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::BinOp(::syntax::parse::token::And))); - let arg_ty = &dispatch.input_arg_tys[idx]; - let replacement = typegen::argument_replacement(builder, &interface_map.replacements, arg_ty); - if let Some(ref replacement_ty) = replacement { - let replacor_ident = ::syntax::print::pprust::ty_to_string(replacement_ty); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(&replacor_ident), ::syntax::parse::token::Plain))); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("from"), ::syntax::parse::token::Plain))); - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - } - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg.as_str()), ::syntax::parse::token::Plain))); - - if replacement.is_some() { - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - } - tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Comma)); } @@ -432,7 +392,7 @@ fn implement_client_method_body( quote_stmt!(cx, let mut socket = socket_ref.deref_mut())); request_serialization_statements.push( - quote_stmt!(cx, let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap())); + quote_stmt!(cx, let serialized_payload = ::ipc::binary::serialize(&payload).unwrap())); request_serialization_statements.push( quote_stmt!(cx, ::ipc::invoke($index_ident, &Some(serialized_payload), &mut socket))); @@ -453,7 +413,7 @@ fn implement_client_method_body( if let Some(ref return_ty) = dispatch.return_type_ty { let return_expr = quote_expr!(cx, - ::bincode::serde::deserialize_from::<_, $return_ty>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() + ::ipc::binary::deserialize_from::<$return_ty, _>(&mut socket).unwrap() ); quote_expr!(cx, { $request @@ -632,7 +592,7 @@ fn push_client_implementation( let mut socket = socket_ref.deref_mut(); ::ipc::invoke( 0, - &Some(::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap()), + &Some(::ipc::binary::serialize(&payload).unwrap()), &mut socket); let mut result = vec![0u8; 1]; @@ -696,18 +656,18 @@ fn implement_handshake_arm( ) -> (ast::Arm, ast::Arm) { let handshake_deserialize = quote_stmt!(&cx, - let handshake_payload = ::bincode::serde::deserialize_from::<_, BinHandshake>(r, ::bincode::SizeLimit::Infinite).unwrap(); + let handshake_payload = ::ipc::binary::deserialize_from::(r).unwrap(); ); let handshake_deserialize_buf = quote_stmt!(&cx, - let handshake_payload = ::bincode::serde::deserialize::(buf).unwrap(); + let handshake_payload = ::ipc::binary::deserialize::(buf).unwrap(); ); let handshake_serialize = quote_expr!(&cx, - ::bincode::serde::serialize::(&Self::handshake(&::ipc::Handshake { + ::ipc::binary::serialize::(&Self::handshake(&::ipc::Handshake { api_version: ::semver::Version::parse(&handshake_payload.api_version).unwrap(), protocol_version: ::semver::Version::parse(&handshake_payload.protocol_version).unwrap(), - }), ::bincode::SizeLimit::Infinite).unwrap() + })).unwrap() ); ( @@ -722,22 +682,11 @@ fn implement_handshake_arm( ) } -fn collect_tys(items: &[&MethodSig]) -> Vec> { - let mut result = Vec::new(); - for signature in items { - result.extend(signature.decl.inputs.iter().map(|input_arg| input_arg.ty.clone())); - if let FunctionRetTy::Ty(ref ty) = signature.decl.output { - result.push(ty.clone()) - }; - } - result -} struct InterfaceMap { pub original_item: Item, pub item: P, pub dispatches: Vec, - pub replacements: HashMap>, pub generics: Generics, pub impl_trait: Option, pub ident_map: IdentMap, @@ -796,20 +745,12 @@ fn implement_interface( } } - let all_tys = collect_tys( - &method_signatures - .iter() - .map(|&(_, signature)| signature) - .collect::>()); - - let replacements = typegen::match_unknown_tys(cx, builder, &all_tys, push); - let dispatch_table = method_signatures.iter().map(|&(impl_item, signature)| - push_invoke_signature_aster(builder, impl_item, signature, &replacements, push)) + push_invoke_signature_aster(builder, impl_item, signature, push)) .collect::>(); - let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false, &replacements); - let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true, &replacements); + let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false); + let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true); let (handshake_arm, handshake_arm_buf) = implement_handshake_arm(cx); @@ -852,7 +793,6 @@ fn implement_interface( original_item: item.clone(), item: ipc_item, dispatches: dispatch_table, - replacements: replacements, generics: generics.clone(), impl_trait: impl_trait.clone(), }) diff --git a/ipc/codegen/src/lib.rs.in b/ipc/codegen/src/lib.rs.in index 08c8ad998..169bd2a82 100644 --- a/ipc/codegen/src/lib.rs.in +++ b/ipc/codegen/src/lib.rs.in @@ -16,4 +16,3 @@ mod codegen; mod serialization; -pub mod typegen; diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 65d94d162..c9f6b847c 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -166,18 +166,21 @@ fn binary_expr_struct( let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { let field_type_ident = builder.id( - &::syntax::print::pprust::ty_to_string( - &codegen::strip_ptr(&field.ty))); + &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); + + let field_type_ident_qualified = builder.id( + &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)).replace("<", "::<")); + 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() { + match $field_type_ident_qualified::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() { + .unwrap_or_else(|| quote_expr!(cx, match $field_type_ident_qualified::len_params() { 0 => mem::size_of::<$field_type_ident>(), _ => $index_ident .size() })) @@ -199,8 +202,10 @@ fn binary_expr_struct( 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( - &codegen::strip_ptr(&field.ty))); + &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); + + let field_type_ident_qualified = builder.id( + &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)).replace("<", "::<")); let member_expr = match value_ident { Some(x) => { @@ -213,7 +218,7 @@ fn binary_expr_struct( } }; - write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident::len_params() { + write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident_qualified::len_params() { 0 => mem::size_of::<$field_type_ident>(), _ => { let size = $member_expr .size(); length_stack.push_back(size); size } }).unwrap()); @@ -225,7 +230,7 @@ fn binary_expr_struct( let field_index = builder.id(&format!("{}", index)); 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() { + map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident_qualified::len_params() { 0 => mem::size_of::<$field_type_ident>(), _ => length_stack.pop_front().unwrap() }).unwrap()); @@ -371,7 +376,7 @@ fn fields_sequence( tt.push(Token( _sp, token::Ident( - ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty).replace("<", "::<")), token::Plain))); tt.push(Token(_sp, token::ModSep)); tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); @@ -445,7 +450,7 @@ fn named_fields_sequence( tt.push(Token( _sp, token::Ident( - ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty).replace("<", "::<")), token::Plain))); tt.push(Token(_sp, token::ModSep)); tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); diff --git a/ipc/codegen/src/typegen.rs b/ipc/codegen/src/typegen.rs deleted file mode 100644 index 0066eb2bc..000000000 --- a/ipc/codegen/src/typegen.rs +++ /dev/null @@ -1,247 +0,0 @@ -// 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::{ - Ty, - TyKind, - Path, - DUMMY_NODE_ID, -}; - -use syntax::ast; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; - -use std::collections::{HashMap, HashSet}; -use std::ops::Deref; - -fn is_new_entry(path: &Path) -> Option { - let known = { - if path.segments.len() > 1 { - false - } else { - let ident = format!("{}", path.segments[0].identifier.name.as_str()); - ident == "u8" || - ident == "i8" || - ident == "u16" || - ident == "i16" || - ident == "u32" || - ident == "u64" || - ident == "usize" || - ident == "i32" || - ident == "i64" || - ident == "String" || - ident == "bool" || - ident == "H256" || - ident == "U256" || - ident == "H2048" || - ident == "Address" || - ident == "Bytes" - } - }; - - if known { None } - else { Some(::syntax::print::pprust::path_to_string(path)) } -} - -pub fn argument_replacement( - builder: &aster::AstBuilder, - replacements: &HashMap>, - ty: &P, -) -> Option> { - match ty.node { - TyKind::Vec(ref nested_ty) => { - argument_replacement(builder, replacements, nested_ty).and_then(|replaced_with| { - let mut inplace_ty = nested_ty.deref().clone(); - inplace_ty.node = TyKind::Vec(replaced_with); - inplace_ty.id = DUMMY_NODE_ID; - Some(P(inplace_ty)) - }) - }, - TyKind::FixedLengthVec(ref nested_ty, ref len_expr) => { - argument_replacement(builder, replacements, nested_ty).and_then(|replaced_with| { - let mut inplace_ty = nested_ty.deref().clone(); - inplace_ty.node = TyKind::FixedLengthVec(replaced_with, len_expr.clone()); - inplace_ty.id = DUMMY_NODE_ID; - Some(P(inplace_ty)) - }) - }, - TyKind::Path(_, ref path) => { - if path.segments.len() > 0 && path.segments[0].identifier.name.as_str() == "Option" || - path.segments[0].identifier.name.as_str() == "Result" { - - let nested_ty = &path.segments[0].parameters.types()[0]; - argument_replacement(builder, replacements, nested_ty).and_then(|replaced_with| { - let mut inplace_path = path.clone(); - match inplace_path.segments[0].parameters { - ast::PathParameters::AngleBracketed(ref mut data) => { - data.types = data.types.map(|_| replaced_with.clone()); - }, - _ => {} - } - let mut inplace_ty = nested_ty.deref().deref().clone(); - inplace_ty.node = TyKind::Path(None, inplace_path); - inplace_ty.id = DUMMY_NODE_ID; - Some(P(inplace_ty)) - }) - } - else { - replacements.get(&::syntax::print::pprust::path_to_string(path)).and_then(|replaced_with| { - Some(replaced_with.clone()) - }) - } - } - _ => { None } - } -} - -pub fn push_bin_box( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - ty: &Ty, - bbox_name: &str, - push: &mut FnMut(Annotatable), -) { - let ident = builder.id(bbox_name); - let bin_box_struct = quote_item!(cx, - struct $ident ($ty); - ).unwrap(); - push(Annotatable::Item(bin_box_struct)); - push(Annotatable::Item(quote_item!(cx, - impl From<$ty> for $ident { - fn from(val: $ty) -> $ident { - $ident(val) - } - }).unwrap())); - - push(Annotatable::Item(quote_item!(cx, - impl Into<$ty> for $ident { - fn into(self) -> $ty { - let $ident(val) = self; - val - } - }).unwrap())); - - let serialize_impl = quote_item!(cx, - impl ::serde::ser::Serialize for $ident { - fn serialize<__S>(&self, serializer: &mut __S) -> ::std::result::Result<(), __S::Error> - where __S: ::serde::ser::Serializer - { - let &$ident(ref val) = self; - serializer.serialize_bytes(val.as_slice()) - } - }).unwrap(); - - let ident_expr = builder.id(::syntax::print::pprust::ty_to_string(ty)); - - let deserialize_impl = quote_item!(cx, - impl ::serde::de::Deserialize for $ident { - fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<$ident, __D::Error> - where __D: ::serde::de::Deserializer - { - struct __Visitor<__D: ::serde::de::Deserializer>(::std::marker::PhantomData<__D>); - - impl <__D: ::serde::de::Deserializer> ::serde::de::Visitor for __Visitor<__D> { - type Value = $ident; - #[inline] - fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ident, __V::Error> - where __V: ::serde::de::SeqVisitor - { - let raw_bytes: Vec = try!(visitor.visit()).unwrap_or_else(|| Vec::new()); - let inner = $ident_expr ::from_bytes(&raw_bytes).unwrap(); - Ok($ident (inner)) - } - - } - deserializer.deserialize_bytes(__Visitor::<__D>(::std::marker::PhantomData)) - } - - }).unwrap(); - - push(Annotatable::Item(serialize_impl)); - push(Annotatable::Item(deserialize_impl)); -} - -pub fn match_unknown_tys( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - tys: &[P], - push: &mut FnMut(Annotatable), -) -> HashMap> -{ - let mut hash_map = HashMap::new(); - let mut fringe = Vec::new(); - fringe.extend(tys); - let mut stop_list = HashSet::new(); - let mut index = 0; - - loop { - if fringe.len() == 0 { break; } - let drained = fringe.drain(..1).collect::>>(); - let ty = drained[0]; - stop_list.insert(ty); - - match ty.node { - TyKind::Vec(ref nested_ty) => { - if !stop_list.contains(nested_ty) { - fringe.push(nested_ty); - } - }, - TyKind::FixedLengthVec(ref nested_ty, _) => { - if !stop_list.contains(nested_ty) { - fringe.push(nested_ty); - } - }, - TyKind::Rptr(_, ref nested_ty) => { - if !stop_list.contains(&nested_ty.ty) { - fringe.push(&nested_ty.ty); - } - }, - TyKind::Path(_, ref path) => { - if path.segments.len() > 0 && { - let first_segment = path.segments[0].identifier.name.as_str(); - first_segment == "Option" || first_segment == "Result" || first_segment == "Vec" - } - { - let extra_type = &path.segments[0].parameters.types()[0]; - if !stop_list.contains(extra_type) { - fringe.push(extra_type); - } - continue; - } - - match is_new_entry(path) { - Some(old_path) => { - if hash_map.get(&old_path).is_some() { - continue; - } - - let bin_box_name = format!("BinBox{}", index); - push_bin_box(cx, builder, &ty, &bin_box_name, push); - hash_map.insert(old_path, builder.ty().id(&bin_box_name)); - index = index + 1; - }, - None => {} - } - }, - _ => { } - } - } - - hash_map -} diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 61eb9277f..cfad9eeed 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -63,6 +63,63 @@ impl BinaryConvertable for Option where T: BinaryConvertable { } } +impl BinaryConvertable for Result<(), E> { + fn size(&self) -> usize { + 1usize + match *self { + Ok(ref r) => 0, + Err(ref e) => e.size(), + } + } + + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + match *self { + Ok(ref r) => Ok(()), + Err(ref e) => Ok(try!(e.to_bytes(buffer, length_stack))), + } + } + + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + match buffer[0] { + 0 => Ok(Ok(())), + 1 => Ok(Err(try!(E::from_bytes(&buffer[1..], length_stack)))), + _ => Err(BinaryConvertError) + } + } + + fn len_params() -> usize { + 1 + } +} + + +impl BinaryConvertable for Result { + fn size(&self) -> usize { + 1usize + match *self { + Ok(ref r) => r.size(), + Err(ref e) => e.size(), + } + } + + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + match *self { + Ok(ref r) => Ok(try!(r.to_bytes(buffer, length_stack))), + Err(ref e) => Ok(try!(e.to_bytes(buffer, length_stack))), + } + } + + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + match buffer[0] { + 0 => Ok(Ok(try!(R::from_bytes(&buffer[1..], length_stack)))), + 1 => Ok(Err(try!(E::from_bytes(&buffer[1..], length_stack)))), + _ => Err(BinaryConvertError) + } + } + + fn len_params() -> usize { + 1 + } +} + impl BinaryConvertable for Vec where T: BinaryConvertable { fn size(&self) -> usize { match T::len_params() { @@ -128,6 +185,55 @@ impl BinaryConvertable for Vec where T: BinaryConvertable { } } +impl BinaryConvertable for String { + fn size(&self) -> usize { + self.as_bytes().len() + } + + fn from_empty_bytes() -> Result { + Ok(String::new()) + } + + fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + buffer[..].clone_from_slice(self.as_bytes()); + Ok(()) + } + + fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result { + Ok(::std::str::from_utf8(buffer).unwrap().to_owned()) + } + + fn len_params() -> usize { + 1 + } +} + +impl BinaryConvertable for Vec { + fn size(&self) -> usize { + self.len() + } + + fn from_empty_bytes() -> Result { + Ok(Vec::new()) + } + + fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + buffer[..].clone_from_slice(&self[..]); + Ok(()) + } + + fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result { + let mut res = Self::with_capacity(buffer.len()); + unsafe { res.set_len(buffer.len()) } + res[..].clone_from_slice(&buffer[..]); + Ok(res) + } + + fn len_params() -> usize { + 1 + } +} + pub fn deserialize_from(r: &mut R) -> Result where R: ::std::io::Read, T: BinaryConvertable @@ -158,6 +264,12 @@ pub fn deserialize_from(r: &mut R) -> Result T::from_bytes(&data[..], &mut length_stack) } +pub fn deserialize(buffer: &[u8]) -> Result { + use std::io::Cursor; + let mut buff = Cursor::new(buffer); + deserialize_from::(&mut buff) +} + pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryConvertError> where W: ::std::io::Write, T: BinaryConvertable @@ -197,6 +309,13 @@ pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryConvertError> Ok(()) } +pub fn serialize(t: &T) -> Result, BinaryConvertError> { + use std::io::Cursor; + let mut buff = Cursor::new(Vec::new()); + try!(serialize_into(t, &mut buff)); + Ok(buff.into_inner()) +} + macro_rules! binary_fixed_size { ($target_ty: ident) => { impl BinaryConvertable for $target_ty { @@ -226,6 +345,7 @@ macro_rules! binary_fixed_size { binary_fixed_size!(u64); binary_fixed_size!(u32); +binary_fixed_size!(i32); binary_fixed_size!(bool); #[test] diff --git a/ipc/tests/build.rs b/ipc/tests/build.rs index c95868c67..3600ed7b9 100644 --- a/ipc/tests/build.rs +++ b/ipc/tests/build.rs @@ -38,7 +38,7 @@ pub fn main() { let src = Path::new(&out_dir).join("nested_ipc.rs"); let dst = Path::new(&out_dir).join("nested_cg.rs"); let mut registry = syntex::Registry::new(); - serde_codegen::register(&mut registry); + codegen::register(&mut registry); registry.expand("", &src, &dst).unwrap(); } @@ -56,7 +56,7 @@ pub fn main() { let src = Path::new(&out_dir).join("service_ipc.rs"); let dst = Path::new(&out_dir).join("service_cg.rs"); let mut registry = syntex::Registry::new(); - serde_codegen::register(&mut registry); + codegen::register(&mut registry); registry.expand("", &src, &dst).unwrap(); } diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index f20cba793..4a60354be 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -41,12 +41,20 @@ mod tests { #[test] fn call_service_handshake() { let mut socket = TestSocket::new_ready(vec![0, 0, - // protocol version - 0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0', - // api version - 0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0', - // reserved + // part count = 3 + 0, 0, 0, 0, 0, 0, 0, 3, + // part sizes + 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 64, + // total payload length + 0, 0, 0, 0, 0, 0, 0, 70, + // protocol version + b'1', b'.', b'0', b'.', b'0', + // api version + b'1', b'.', b'0', b'.', b'0', + // reserved + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/ipc/tests/nested.rs b/ipc/tests/nested.rs index 1deff75bb..5c7504ad8 100644 --- a/ipc/tests/nested.rs +++ b/ipc/tests/nested.rs @@ -14,4 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues include!(concat!(env!("OUT_DIR"), "/nested_cg.rs")); diff --git a/ipc/tests/nested.rs.in b/ipc/tests/nested.rs.in index 481acfdf7..355067689 100644 --- a/ipc/tests/nested.rs.in +++ b/ipc/tests/nested.rs.in @@ -17,6 +17,10 @@ use std::sync::RwLock; use std::ops::*; use ipc::IpcConfig; +use ipc::BinaryConvertable; +use std::mem; +use ipc::binary::BinaryConvertError; +use std::collections::VecDeque; pub struct DB { pub writes: RwLock, @@ -30,7 +34,7 @@ pub trait DBWriter { impl IpcConfig for DB {} -#[derive(Serialize, Deserialize)] +#[derive(Binary)] pub enum DBError { Write, Read } #[derive(Ipc)] diff --git a/ipc/tests/service.rs b/ipc/tests/service.rs index ecd977f61..7e778c615 100644 --- a/ipc/tests/service.rs +++ b/ipc/tests/service.rs @@ -14,4 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues include!(concat!(env!("OUT_DIR"), "/service_cg.rs")); diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 6bfa72680..2c58122bf 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -16,40 +16,20 @@ use std::sync::RwLock; use std::ops::*; -use std::convert::*; use ipc::IpcConfig; -use util::bytes::{FromRawBytes, BytesConvertable, FromBytesError}; +use std::mem; +use ipc::binary::BinaryConvertError; +use std::collections::VecDeque; pub struct Service { pub commits: RwLock, pub rollbacks: RwLock, } +#[derive(Binary)] pub struct CustomData { - pub a: usize, - pub b: usize, -} - -impl FromRawBytes for CustomData { - fn from_bytes(bytes: &[u8]) -> Result { - Ok(CustomData { - a: bytes[0] as usize * 256 + bytes[1] as usize, - b: bytes[2] as usize * 256 + bytes[3] as usize - }) - } -} - -impl BytesConvertable for CustomData { - fn bytes(&self) -> &[u8] { - let ip: *const CustomData = self; - let ptr: *const u8 = ip as *const _; - unsafe { - ::std::slice::from_raw_parts( - ptr, - ::std::mem::size_of::() - ) - } - } + pub a: u64, + pub b: u64, } #[derive(Ipc)] @@ -69,8 +49,8 @@ impl Service { let mut clock = self.commits.write().unwrap(); let mut rlock = self.commits.write().unwrap(); - *clock = data.a; - *rlock = data.b; + *clock = data.a as usize; + *rlock = data.b as usize; true } From fb82d185c734a4046f6648e360f415b8e51529a8 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 23 Apr 2016 18:15:50 +0300 Subject: [PATCH 2/6] refactored to new serialization --- ipc/rpc/src/binary.rs | 123 +++++++++++++++++++++++++---------------- ipc/tests/examples.rs | 51 ++++++++++++----- ipc/tests/over_nano.rs | 40 +------------- 3 files changed, 112 insertions(+), 102 deletions(-) diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index cfad9eeed..d16908146 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -66,14 +66,14 @@ impl BinaryConvertable for Option where T: BinaryConvertable { impl BinaryConvertable for Result<(), E> { fn size(&self) -> usize { 1usize + match *self { - Ok(ref r) => 0, + Ok(_) => 0, Err(ref e) => e.size(), } } fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { match *self { - Ok(ref r) => Ok(()), + Ok(_) => Ok(()), Err(ref e) => Ok(try!(e.to_bytes(buffer, length_stack))), } } @@ -239,29 +239,41 @@ pub fn deserialize_from(r: &mut R) -> Result 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); + match T::len_params() { + 0 => { + let fixed_size = mem::size_of::(); + let mut payload_buffer = Vec::with_capacity(fixed_size); + unsafe { payload_buffer.set_len(fixed_size); } + try!(r.read(&mut payload_buffer).map_err(|_| BinaryConvertError)); + T::from_bytes(&payload_buffer[..], &mut fake_stack) + }, + _ => { + 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) } } - - 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 deserialize(buffer: &[u8]) -> Result { @@ -274,39 +286,52 @@ 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)); + match T::len_params() { + 0 => { + let fixed_size = mem::size_of::(); + let mut buffer = Vec::with_capacity(fixed_size); + unsafe { buffer.set_len(fixed_size); } + try!(t.to_bytes(&mut buffer[..], &mut fake_stack)); + try!(w.write(&buffer[..]).map_err(|_| BinaryConvertError)); + Ok(()) + }, + _ => { + let mut length_stack = VecDeque::::new(); + let mut size_buffer = [0u8; 8]; - 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; } + 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)); } - idx = idx + 1; + + 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(()) } - 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(()) } pub fn serialize(t: &T) -> Result, BinaryConvertError> { diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 4a60354be..99cf385fa 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -27,7 +27,11 @@ mod tests { #[test] fn call_service() { // method_num = 0, f = 10 (method Service::commit) - let mut socket = TestSocket::new_ready(vec![0, 16, 0, 0, 0, 10]); + let mut socket = TestSocket::new_ready(vec![ + 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0]); let service = Service::new(); assert_eq!(0, *service.commits.read().unwrap()); @@ -42,13 +46,13 @@ mod tests { fn call_service_handshake() { let mut socket = TestSocket::new_ready(vec![0, 0, // part count = 3 - 0, 0, 0, 0, 0, 0, 0, 3, + 3, 0, 0, 0, 0, 0, 0, 0, // part sizes - 0, 0, 0, 0, 0, 0, 0, 5, - 0, 0, 0, 0, 0, 0, 0, 5, - 0, 0, 0, 0, 0, 0, 0, 64, + 5, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 0, 0, 0, // total payload length - 0, 0, 0, 0, 0, 0, 0, 70, + 70, 0, 0, 0, 0, 0, 0, 0, // protocol version b'1', b'.', b'0', b'.', b'0', // api version @@ -72,24 +76,34 @@ mod tests { #[test] fn call_service_client() { let mut socket = TestSocket::new(); - socket.read_buffer = vec![0, 0, 0, 10]; + socket.read_buffer = vec![10, 0, 0, 0]; let service_client = ServiceClient::init(socket); let result = service_client.commit(5); - assert_eq!(vec![0, 16, 0, 0, 0, 5], service_client.socket().borrow().write_buffer.clone()); + assert_eq!( + vec![0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0], + service_client.socket().borrow().write_buffer.clone()); assert_eq!(10, result); } #[test] fn call_service_client_optional() { let mut socket = TestSocket::new(); - socket.read_buffer = vec![0, 0, 0, 10]; + socket.read_buffer = vec![10, 0, 0, 0]; let service_client = ServiceClient::init(socket); let result = service_client.rollback(Some(5), 10); - assert_eq!(vec![0, 17, 1, 0, 0, 0, 5, 0, 0, 0, 10], service_client.socket().borrow().write_buffer.clone()); + assert_eq!(vec![ + 0, 17, + 1, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 10, 0, 0, 0], service_client.socket().borrow().write_buffer.clone()); assert_eq!(10, result); } @@ -123,9 +137,12 @@ mod tests { assert_eq!(vec![ // message num.. 0, 18, - // payload length - 0, 0, 0, 0, 0, 0, 0, 16, - // structure raw bytes (bigendians :( ) + // variable size length-s + 1, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + // total length + 16, 0, 0, 0, 0, 0, 0, 0, + // items 3, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0], service_client.socket().borrow().write_buffer.clone()); @@ -135,13 +152,19 @@ mod tests { #[test] fn can_invoke_generic_service() { let mut socket = TestSocket::new(); - socket.read_buffer = vec![0, 0, 0, 0]; + socket.read_buffer = vec![ + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, + ]; let db_client = DBClient::::init(socket); let result = db_client.write(vec![0u8; 100]); assert!(result.is_ok()); } + #[test] fn can_handshake_generic_service() { let mut socket = TestSocket::new(); diff --git a/ipc/tests/over_nano.rs b/ipc/tests/over_nano.rs index 0c0d40372..36ad17f2a 100644 --- a/ipc/tests/over_nano.rs +++ b/ipc/tests/over_nano.rs @@ -20,7 +20,7 @@ mod tests { use super::super::service::*; use nanoipc; use std::sync::Arc; - use std::io::{Write, Read}; + use std::io::Write; use std::sync::atomic::{Ordering, AtomicBool}; fn dummy_write(addr: &str, buf: &[u8]) -> (::nanomsg::Socket, ::nanomsg::Endpoint) { @@ -67,42 +67,4 @@ mod tests { worker_should_exit.store(true, Ordering::Relaxed); assert!(hs.is_ok()); } - - #[test] - fn can_receive_dummy_writes_in_thread() { - let url = "ipc:///tmp/parity-test-nano-30.ipc"; - let worker_should_exit = Arc::new(AtomicBool::new(false)); - let worker_is_ready = Arc::new(AtomicBool::new(false)); - let c_worker_should_exit = worker_should_exit.clone(); - let c_worker_is_ready = worker_is_ready.clone(); - - ::std::thread::spawn(move || { - let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { - worker.poll(); - c_worker_is_ready.store(true, Ordering::Relaxed); - } - }); - while !worker_is_ready.load(Ordering::Relaxed) { } - - let (mut _s, _e) = dummy_write(url, &vec![0, 0, - // protocol version - 0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0', - // api version - 0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0', - // reserved - 0, 0, 0, 0, 0, 0, 0, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]); - - let mut buf = vec![0u8;1]; - _s.read(&mut buf).unwrap(); - assert_eq!(1, buf.len()); - assert_eq!(1, buf[0]); - - worker_should_exit.store(true, Ordering::Relaxed); - } } From 020b490a72cf78c8685797aa7422de82dee3fd89 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 25 Apr 2016 02:43:21 +0300 Subject: [PATCH 3/6] some commas --- ipc/codegen/src/codegen.rs | 6 +++--- ipc/rpc/src/binary.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 253b298f4..582aa9332 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -52,14 +52,14 @@ pub fn expand_ipc_implementation( _ => { cx.span_err(meta_item.span, "`#[derive(Ipc)]` may only be applied to struct implementations"); return; - } + }, }; let builder = aster::AstBuilder::new().span(span); let interface_map = match implement_interface(cx, &builder, &item, push) { Ok(interface_map) => interface_map, - Err(Error) => { return; } + Err(Error) => { return; }, }; push_client(cx, &builder, &interface_map, push); @@ -733,7 +733,7 @@ fn implement_interface( item.span, "`#[derive(Ipc)]` may only be applied to item implementations"); return Err(Error); - } + }, }; let impl_generics = builder.from_generics(generics.clone()).build(); let where_clause = &impl_generics.where_clause; diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index d16908146..3ace31b2f 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -272,7 +272,7 @@ pub fn deserialize_from(r: &mut R) -> Result try!(r.read(&mut data).map_err(|_| BinaryConvertError)); T::from_bytes(&data[..], &mut length_stack) - } + }, } } @@ -330,7 +330,7 @@ pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryConvertError> try!(w.write(&buffer[..]).map_err(|_| BinaryConvertError)); Ok(()) - } + }, } } From 7cacdba19146e8803a055188f0c5047506772abe Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 25 Apr 2016 06:29:20 +0300 Subject: [PATCH 4/6] fixing codegen links --- Cargo.toml | 1 - build.rs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27b15e23a..e0d13422b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ build = "build.rs" [build-dependencies] rustc_version = "0.1" syntex = "*" -serde_codegen = "0.7.0" "ethcore-ipc-codegen" = { path = "ipc/codegen" } [dependencies] diff --git a/build.rs b/build.rs index 9bb9ec249..25764f4be 100644 --- a/build.rs +++ b/build.rs @@ -17,7 +17,6 @@ extern crate rustc_version; extern crate syntex; extern crate ethcore_ipc_codegen as codegen; -extern crate serde_codegen; use std::env; use std::path::Path; @@ -39,12 +38,12 @@ fn main() { registry.expand("", &src, &dst).unwrap(); } - // serde pass + // serialization pass { let src = Path::new(&out_dir).join("hypervisor_service_ipc.rs"); let dst = Path::new(&out_dir).join("hypervisor_service_cg.rs"); let mut registry = syntex::Registry::new(); - serde_codegen::register(&mut registry); + codegen::register(&mut registry); registry.expand("", &src, &dst).unwrap(); } } From 9a3e6a61357801555c17b353bc77aeba37da2f8b Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 25 Apr 2016 06:34:11 +0300 Subject: [PATCH 5/6] hypervisor fix --- Cargo.lock | 10 +--------- parity/hypervisor/service.rs | 1 + parity/hypervisor/service.rs.in | 4 ++++ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fda878eac..3914af455 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,7 +28,6 @@ dependencies = [ "rustc_version 0.1.7 (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)", ] @@ -237,15 +236,11 @@ 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)", @@ -254,10 +249,6 @@ 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)", ] @@ -273,6 +264,7 @@ name = "ethcore-ipc" version = "1.1.0" dependencies = [ "ethcore-devtools 1.1.0", + "ethcore-util 1.1.0", "nanomsg 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/parity/hypervisor/service.rs b/parity/hypervisor/service.rs index 3171fa11c..75830d213 100644 --- a/parity/hypervisor/service.rs +++ b/parity/hypervisor/service.rs @@ -15,5 +15,6 @@ // along with Parity. If not, see . //! Parity interprocess hypervisor IPC service +#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues include!(concat!(env!("OUT_DIR"), "/hypervisor_service_cg.rs")); diff --git a/parity/hypervisor/service.rs.in b/parity/hypervisor/service.rs.in index 2efef6ffd..a8ad90e12 100644 --- a/parity/hypervisor/service.rs.in +++ b/parity/hypervisor/service.rs.in @@ -18,6 +18,10 @@ use std::sync::{RwLock,Arc}; use std::ops::*; use ipc::IpcConfig; use std::collections::HashMap; +use ipc::BinaryConvertable; +use std::mem; +use ipc::binary::BinaryConvertError; +use std::collections::VecDeque; pub type IpcModuleId = u64; From 922400f1919d11b686ff65b32809a44595ec40cf Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 25 Apr 2016 17:20:38 +0300 Subject: [PATCH 6/6] ipc fixes --- ipc/codegen/src/serialization.rs | 18 ++++++++++++++---- ipc/rpc/src/binary.rs | 29 +++++++++++++++++++++++++++++ ipc/tests/Cargo.toml | 2 -- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index c9f6b847c..79608b8f4 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -155,6 +155,16 @@ struct BinaryExpressions { pub read: P, } +fn replace_qualified(s: &str) -> String { + if let Some(pos) = s.find("<") { + let mut source = s.to_owned(); + source.insert(pos, ':'); + source.insert(pos, ':'); + source + } + else { s.to_owned() } +} + fn binary_expr_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -169,7 +179,7 @@ fn binary_expr_struct( &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); let field_type_ident_qualified = builder.id( - &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)).replace("<", "::<")); + replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)))); let index_ident = builder.id(format!("__field{}", index)); value_ident.and_then(|x| { @@ -205,7 +215,7 @@ fn binary_expr_struct( &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); let field_type_ident_qualified = builder.id( - &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)).replace("<", "::<")); + replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)))); let member_expr = match value_ident { Some(x) => { @@ -376,7 +386,7 @@ fn fields_sequence( tt.push(Token( _sp, token::Ident( - ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty).replace("<", "::<")), + ext_cx.ident_of(&replace_qualified(&::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))); @@ -450,7 +460,7 @@ fn named_fields_sequence( tt.push(Token( _sp, token::Ident( - ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty).replace("<", "::<")), + ext_cx.ident_of(&replace_qualified(&::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))); diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 3ace31b2f..3ba172c6e 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -17,6 +17,7 @@ //! Binary representation of types use util::bytes::Populatable; +use util::numbers::{U256, H256, H2048, Address}; use std::mem; use std::collections::VecDeque; @@ -208,6 +209,29 @@ impl BinaryConvertable for String { } } +impl BinaryConvertable for ::std::cell::RefCell where T: BinaryConvertable { + fn size(&self) -> usize { + self.borrow().size() + } + + fn from_empty_bytes() -> Result { + Ok(::std::cell::RefCell::new(try!(T::from_empty_bytes()))) + } + + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + Ok(::std::cell::RefCell::new(try!(T::from_bytes(buffer, length_stack)))) + } + + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + try!(self.borrow().to_bytes(buffer, length_stack)); + Ok(()) + } + + fn len_params() -> usize { + T::len_params() + } +} + impl BinaryConvertable for Vec { fn size(&self) -> usize { self.len() @@ -370,8 +394,13 @@ macro_rules! binary_fixed_size { binary_fixed_size!(u64); binary_fixed_size!(u32); +binary_fixed_size!(usize); binary_fixed_size!(i32); binary_fixed_size!(bool); +binary_fixed_size!(U256); +binary_fixed_size!(H256); +binary_fixed_size!(H2048); +binary_fixed_size!(Address); #[test] fn vec_serialize() { diff --git a/ipc/tests/Cargo.toml b/ipc/tests/Cargo.toml index 286fffd18..bde5b4c62 100644 --- a/ipc/tests/Cargo.toml +++ b/ipc/tests/Cargo.toml @@ -9,8 +9,6 @@ path = "run.rs" [dependencies] "ethcore-ipc" = { path = "../rpc" } -bincode = "*" -serde = "0.7.0" ethcore-devtools = { path = "../../devtools" } semver = "0.2.0" nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }