refactored to new serialization

This commit is contained in:
Nikolay Volf 2016-04-22 19:45:09 +03:00
parent 6b1db6a656
commit dcb7546d6d
11 changed files with 192 additions and 381 deletions

View File

@ -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<String, P<Ty>>,
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<String, P<Ty>>,
) -> 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::<Vec<P<ast::Expr>>>();
@ -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<String, P<Ty>>,
) -> P<ast::Expr>
{
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<String, P<Ty>>,
) -> 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<String, P<Ty>>,
) -> Vec<ast::Arm>
{
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<ast::Ty>) -> P<ast::Ty> {
@ -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::<BinHandshake, _>(r).unwrap();
);
let handshake_deserialize_buf = quote_stmt!(&cx,
let handshake_payload = ::bincode::serde::deserialize::<BinHandshake>(buf).unwrap();
let handshake_payload = ::ipc::binary::deserialize::<BinHandshake>(buf).unwrap();
);
let handshake_serialize = quote_expr!(&cx,
::bincode::serde::serialize::<bool>(&Self::handshake(&::ipc::Handshake {
::ipc::binary::serialize::<bool>(&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<P<Ty>> {
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<ast::Item>,
pub dispatches: Vec<Dispatch>,
pub replacements: HashMap<String, P<Ty>>,
pub generics: Generics,
pub impl_trait: Option<TraitRef>,
pub ident_map: IdentMap,
@ -796,20 +745,12 @@ fn implement_interface(
}
}
let all_tys = collect_tys(
&method_signatures
.iter()
.map(|&(_, signature)| signature)
.collect::<Vec<&MethodSig>>());
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::<Vec<Dispatch>>();
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(),
})

View File

@ -16,4 +16,3 @@
mod codegen;
mod serialization;
pub mod typegen;

View File

@ -166,18 +166,21 @@ fn binary_expr_struct(
let size_exprs: Vec<P<ast::Expr>> = 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)));

View File

@ -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 <http://www.gnu.org/licenses/>.
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<String> {
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<String, P<Ty>>,
ty: &P<Ty>,
) -> Option<P<Ty>> {
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<u8> = 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<Ty>],
push: &mut FnMut(Annotatable),
) -> HashMap<String, P<Ty>>
{
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::<Vec<&P<Ty>>>();
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
}

View File

@ -63,6 +63,63 @@ impl<T> BinaryConvertable for Option<T> where T: BinaryConvertable {
}
}
impl<E: BinaryConvertable> 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<usize>) -> 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<usize>) -> Result<Self, BinaryConvertError> {
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<R: BinaryConvertable, E: BinaryConvertable> BinaryConvertable for Result<R, E> {
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<usize>) -> 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<usize>) -> Result<Self, BinaryConvertError> {
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<T> BinaryConvertable for Vec<T> where T: BinaryConvertable {
fn size(&self) -> usize {
match T::len_params() {
@ -128,6 +185,55 @@ impl<T> BinaryConvertable for Vec<T> where T: BinaryConvertable {
}
}
impl BinaryConvertable for String {
fn size(&self) -> usize {
self.as_bytes().len()
}
fn from_empty_bytes() -> Result<Self, BinaryConvertError> {
Ok(String::new())
}
fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque<usize>) -> Result<(), BinaryConvertError> {
buffer[..].clone_from_slice(self.as_bytes());
Ok(())
}
fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque<usize>) -> Result<Self, BinaryConvertError> {
Ok(::std::str::from_utf8(buffer).unwrap().to_owned())
}
fn len_params() -> usize {
1
}
}
impl BinaryConvertable for Vec<u8> {
fn size(&self) -> usize {
self.len()
}
fn from_empty_bytes() -> Result<Self, BinaryConvertError> {
Ok(Vec::new())
}
fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque<usize>) -> Result<(), BinaryConvertError> {
buffer[..].clone_from_slice(&self[..]);
Ok(())
}
fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque<usize>) -> Result<Self, BinaryConvertError> {
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<T, R>(r: &mut R) -> Result<T, BinaryConvertError>
where R: ::std::io::Read,
T: BinaryConvertable
@ -158,6 +264,12 @@ pub fn deserialize_from<T, R>(r: &mut R) -> Result<T, BinaryConvertError>
T::from_bytes(&data[..], &mut length_stack)
}
pub fn deserialize<T: BinaryConvertable>(buffer: &[u8]) -> Result<T, BinaryConvertError> {
use std::io::Cursor;
let mut buff = Cursor::new(buffer);
deserialize_from::<T, _>(&mut buff)
}
pub fn serialize_into<T, W>(t: &T, w: &mut W) -> Result<(), BinaryConvertError>
where W: ::std::io::Write,
T: BinaryConvertable
@ -197,6 +309,13 @@ pub fn serialize_into<T, W>(t: &T, w: &mut W) -> Result<(), BinaryConvertError>
Ok(())
}
pub fn serialize<T: BinaryConvertable>(t: &T) -> Result<Vec<u8>, 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]

View File

@ -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();
}

View File

@ -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,

View File

@ -14,4 +14,5 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
include!(concat!(env!("OUT_DIR"), "/nested_cg.rs"));

View File

@ -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<L: Sized> {
pub writes: RwLock<u64>,
@ -30,7 +34,7 @@ pub trait DBWriter {
impl<L: Sized> IpcConfig for DB<L> {}
#[derive(Serialize, Deserialize)]
#[derive(Binary)]
pub enum DBError { Write, Read }
#[derive(Ipc)]

View File

@ -14,4 +14,5 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
include!(concat!(env!("OUT_DIR"), "/service_cg.rs"));

View File

@ -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<usize>,
pub rollbacks: RwLock<usize>,
}
#[derive(Binary)]
pub struct CustomData {
pub a: usize,
pub b: usize,
}
impl FromRawBytes for CustomData {
fn from_bytes(bytes: &[u8]) -> Result<CustomData, FromBytesError> {
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::<CustomData>()
)
}
}
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
}