Merge pull request #998 from ethcore/ipc-new-serialization
IPC with new serialization
This commit is contained in:
commit
3865e4cdba
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -28,7 +28,6 @@ dependencies = [
|
|||||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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 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)",
|
"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)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -9,7 +9,6 @@ build = "build.rs"
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
rustc_version = "0.1"
|
rustc_version = "0.1"
|
||||||
syntex = "*"
|
syntex = "*"
|
||||||
serde_codegen = "0.7.0"
|
|
||||||
"ethcore-ipc-codegen" = { path = "ipc/codegen" }
|
"ethcore-ipc-codegen" = { path = "ipc/codegen" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
5
build.rs
5
build.rs
@ -17,7 +17,6 @@
|
|||||||
extern crate rustc_version;
|
extern crate rustc_version;
|
||||||
extern crate syntex;
|
extern crate syntex;
|
||||||
extern crate ethcore_ipc_codegen as codegen;
|
extern crate ethcore_ipc_codegen as codegen;
|
||||||
extern crate serde_codegen;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -39,12 +38,12 @@ fn main() {
|
|||||||
registry.expand("", &src, &dst).unwrap();
|
registry.expand("", &src, &dst).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// serde pass
|
// serialization pass
|
||||||
{
|
{
|
||||||
let src = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
|
let src = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
|
||||||
let dst = Path::new(&out_dir).join("hypervisor_service_cg.rs");
|
let dst = Path::new(&out_dir).join("hypervisor_service_cg.rs");
|
||||||
let mut registry = syntex::Registry::new();
|
let mut registry = syntex::Registry::new();
|
||||||
serde_codegen::register(&mut registry);
|
codegen::register(&mut registry);
|
||||||
registry.expand("", &src, &dst).unwrap();
|
registry.expand("", &src, &dst).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,6 @@ use syntax::ext::base::{Annotatable, ExtCtxt};
|
|||||||
use syntax::ext::build::AstBuilder;
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
use super::typegen;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|
||||||
const RESERVED_MESSAGE_IDS: u16 = 16;
|
const RESERVED_MESSAGE_IDS: u16 = 16;
|
||||||
@ -55,14 +52,14 @@ pub fn expand_ipc_implementation(
|
|||||||
_ => {
|
_ => {
|
||||||
cx.span_err(meta_item.span, "`#[derive(Ipc)]` may only be applied to struct implementations");
|
cx.span_err(meta_item.span, "`#[derive(Ipc)]` may only be applied to struct implementations");
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let builder = aster::AstBuilder::new().span(span);
|
let builder = aster::AstBuilder::new().span(span);
|
||||||
|
|
||||||
let interface_map = match implement_interface(cx, &builder, &item, push) {
|
let interface_map = match implement_interface(cx, &builder, &item, push) {
|
||||||
Ok(interface_map) => interface_map,
|
Ok(interface_map) => interface_map,
|
||||||
Err(Error) => { return; }
|
Err(Error) => { return; },
|
||||||
};
|
};
|
||||||
|
|
||||||
push_client(cx, &builder, &interface_map, push);
|
push_client(cx, &builder, &interface_map, push);
|
||||||
@ -73,7 +70,7 @@ pub fn expand_ipc_implementation(
|
|||||||
|
|
||||||
fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) {
|
fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) {
|
||||||
let handshake_item = quote_item!(cx,
|
let handshake_item = quote_item!(cx,
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Binary)]
|
||||||
pub struct BinHandshake {
|
pub struct BinHandshake {
|
||||||
api_version: String,
|
api_version: String,
|
||||||
protocol_version: String,
|
protocol_version: String,
|
||||||
@ -95,7 +92,6 @@ fn push_invoke_signature_aster(
|
|||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
implement: &ImplItem,
|
implement: &ImplItem,
|
||||||
signature: &MethodSig,
|
signature: &MethodSig,
|
||||||
replacements: &HashMap<String, P<Ty>>,
|
|
||||||
push: &mut FnMut(Annotatable),
|
push: &mut FnMut(Annotatable),
|
||||||
) -> Dispatch {
|
) -> Dispatch {
|
||||||
let inputs = &signature.decl.inputs;
|
let inputs = &signature.decl.inputs;
|
||||||
@ -113,12 +109,11 @@ fn push_invoke_signature_aster(
|
|||||||
let arg_ty = &inputs[skip-1].ty;
|
let arg_ty = &inputs[skip-1].ty;
|
||||||
|
|
||||||
let mut tree = builder.item()
|
let mut tree = builder.item()
|
||||||
.attr().word("derive(Serialize, Deserialize)")
|
.attr().word("derive(Binary)")
|
||||||
.attr().word("allow(non_camel_case_types)")
|
.attr().word("allow(non_camel_case_types)")
|
||||||
.struct_(name_str.as_str())
|
.struct_(name_str.as_str())
|
||||||
.field(arg_name.as_str()).ty()
|
.field(arg_name.as_str()).ty()
|
||||||
.build(typegen::argument_replacement(builder, replacements, arg_ty)
|
.build(strip_ptr(arg_ty));
|
||||||
.unwrap_or(strip_ptr(arg_ty)));
|
|
||||||
|
|
||||||
arg_names.push(arg_name);
|
arg_names.push(arg_name);
|
||||||
arg_tys.push(arg_ty.clone());
|
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_name = format!("{}", field_name(builder, &arg));
|
||||||
let arg_ty = &arg.ty;
|
let arg_ty = &arg.ty;
|
||||||
|
|
||||||
tree = tree.field(arg_name.as_str()).ty().build(
|
tree = tree.field(arg_name.as_str()).ty().build(strip_ptr(arg_ty));
|
||||||
typegen::argument_replacement(builder, replacements, arg_ty).unwrap_or(strip_ptr(arg_ty))
|
|
||||||
);
|
|
||||||
arg_names.push(arg_name);
|
arg_names.push(arg_name);
|
||||||
arg_tys.push(arg_ty.clone());
|
arg_tys.push(arg_ty.clone());
|
||||||
}
|
}
|
||||||
@ -145,7 +138,7 @@ fn push_invoke_signature_aster(
|
|||||||
FunctionRetTy::Ty(ref ty) => {
|
FunctionRetTy::Ty(ref ty) => {
|
||||||
let name_str = format!("{}_output", implement.ident.name.as_str());
|
let name_str = format!("{}_output", implement.ident.name.as_str());
|
||||||
let tree = builder.item()
|
let tree = builder.item()
|
||||||
.attr().word("derive(Serialize, Deserialize)")
|
.attr().word("derive(Binary)")
|
||||||
.attr().word("allow(non_camel_case_types)")
|
.attr().word("allow(non_camel_case_types)")
|
||||||
.struct_(name_str.as_str())
|
.struct_(name_str.as_str())
|
||||||
.field(format!("payload")).ty().build(ty.clone());
|
.field(format!("payload")).ty().build(ty.clone());
|
||||||
@ -184,20 +177,13 @@ fn implement_dispatch_arm_invoke_stmt(
|
|||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
dispatch: &Dispatch,
|
dispatch: &Dispatch,
|
||||||
replacements: &HashMap<String, P<Ty>>,
|
|
||||||
) -> ast::Stmt
|
) -> ast::Stmt
|
||||||
{
|
{
|
||||||
let function_name = builder.id(dispatch.function_name.as_str());
|
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 input_args_exprs = dispatch.input_arg_names.iter().enumerate().map(|(arg_index, arg_name)| {
|
||||||
let arg_ident = builder.id(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() {
|
let expr = quote_expr!(cx, input. $arg_ident);
|
||||||
quote_expr!(cx, input. $arg_ident .into())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
quote_expr!(cx, input. $arg_ident)
|
|
||||||
};
|
|
||||||
|
|
||||||
if has_ptr(&dispatch.input_arg_tys[arg_index]) { quote_expr!(cx, & $expr) }
|
if has_ptr(&dispatch.input_arg_tys[arg_index]) { quote_expr!(cx, & $expr) }
|
||||||
else { expr }
|
else { expr }
|
||||||
}).collect::<Vec<P<ast::Expr>>>();
|
}).collect::<Vec<P<ast::Expr>>>();
|
||||||
@ -211,9 +197,9 @@ fn implement_dispatch_arm_invoke_stmt(
|
|||||||
let mut tt = ::std::vec::Vec::new();
|
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::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::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::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::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::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)));
|
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::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::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::Dot));
|
||||||
tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("unwrap"), ::syntax::parse::token::Plain)));
|
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,
|
builder: &aster::AstBuilder,
|
||||||
dispatch: &Dispatch,
|
dispatch: &Dispatch,
|
||||||
buffer: bool,
|
buffer: bool,
|
||||||
replacements: &HashMap<String, P<Ty>>,
|
|
||||||
) -> P<ast::Expr>
|
) -> P<ast::Expr>
|
||||||
{
|
{
|
||||||
let deserialize_expr = if buffer {
|
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 {
|
} 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| {
|
dispatch.input_type_name.as_ref().map(|val| {
|
||||||
let input_type_id = builder.id(val.clone().as_str());
|
let input_type_id = builder.id(val.clone().as_str());
|
||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
@ -277,11 +255,10 @@ fn implement_dispatch_arm(
|
|||||||
index: u32,
|
index: u32,
|
||||||
dispatch: &Dispatch,
|
dispatch: &Dispatch,
|
||||||
buffer: bool,
|
buffer: bool,
|
||||||
replacements: &HashMap<String, P<Ty>>,
|
|
||||||
) -> ast::Arm
|
) -> ast::Arm
|
||||||
{
|
{
|
||||||
let index_ident = builder.id(format!("{}", index + (RESERVED_MESSAGE_IDS as u32)).as_str());
|
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 } )
|
quote_arm!(cx, $index_ident => { $invoke_expr } )
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,12 +267,11 @@ fn implement_dispatch_arms(
|
|||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
dispatches: &[Dispatch],
|
dispatches: &[Dispatch],
|
||||||
buffer: bool,
|
buffer: bool,
|
||||||
replacements: &HashMap<String, P<Ty>>,
|
|
||||||
) -> Vec<ast::Arm>
|
) -> Vec<ast::Arm>
|
||||||
{
|
{
|
||||||
let mut index = -1;
|
let mut index = -1;
|
||||||
dispatches.iter()
|
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> {
|
pub fn strip_ptr(ty: &P<ast::Ty>) -> P<ast::Ty> {
|
||||||
@ -349,10 +325,10 @@ fn implement_client_method_body(
|
|||||||
.ty().ref_()
|
.ty().ref_()
|
||||||
.lifetime("'a")
|
.lifetime("'a")
|
||||||
.ty()
|
.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()
|
let mut tree = builder.item()
|
||||||
.attr().word("derive(Serialize)")
|
.attr().word("derive(Binary)")
|
||||||
.struct_("Request")
|
.struct_("Request")
|
||||||
.generics()
|
.generics()
|
||||||
.lifetime_name("'a")
|
.lifetime_name("'a")
|
||||||
@ -368,7 +344,7 @@ fn implement_client_method_body(
|
|||||||
.ty().ref_()
|
.ty().ref_()
|
||||||
.lifetime("'a")
|
.lifetime("'a")
|
||||||
.ty()
|
.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);
|
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::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)));
|
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::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::Colon));
|
||||||
|
|
||||||
tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::BinOp(::syntax::parse::token::And)));
|
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)));
|
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));
|
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()));
|
quote_stmt!(cx, let mut socket = socket_ref.deref_mut()));
|
||||||
|
|
||||||
request_serialization_statements.push(
|
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(
|
request_serialization_statements.push(
|
||||||
quote_stmt!(cx, ::ipc::invoke($index_ident, &Some(serialized_payload), &mut socket)));
|
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 {
|
if let Some(ref return_ty) = dispatch.return_type_ty {
|
||||||
let return_expr = quote_expr!(cx,
|
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, {
|
quote_expr!(cx, {
|
||||||
$request
|
$request
|
||||||
@ -632,7 +592,7 @@ fn push_client_implementation(
|
|||||||
let mut socket = socket_ref.deref_mut();
|
let mut socket = socket_ref.deref_mut();
|
||||||
::ipc::invoke(
|
::ipc::invoke(
|
||||||
0,
|
0,
|
||||||
&Some(::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap()),
|
&Some(::ipc::binary::serialize(&payload).unwrap()),
|
||||||
&mut socket);
|
&mut socket);
|
||||||
|
|
||||||
let mut result = vec![0u8; 1];
|
let mut result = vec![0u8; 1];
|
||||||
@ -696,18 +656,18 @@ fn implement_handshake_arm(
|
|||||||
) -> (ast::Arm, ast::Arm)
|
) -> (ast::Arm, ast::Arm)
|
||||||
{
|
{
|
||||||
let handshake_deserialize = quote_stmt!(&cx,
|
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_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,
|
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(),
|
api_version: ::semver::Version::parse(&handshake_payload.api_version).unwrap(),
|
||||||
protocol_version: ::semver::Version::parse(&handshake_payload.protocol_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 {
|
struct InterfaceMap {
|
||||||
pub original_item: Item,
|
pub original_item: Item,
|
||||||
pub item: P<ast::Item>,
|
pub item: P<ast::Item>,
|
||||||
pub dispatches: Vec<Dispatch>,
|
pub dispatches: Vec<Dispatch>,
|
||||||
pub replacements: HashMap<String, P<Ty>>,
|
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub impl_trait: Option<TraitRef>,
|
pub impl_trait: Option<TraitRef>,
|
||||||
pub ident_map: IdentMap,
|
pub ident_map: IdentMap,
|
||||||
@ -784,7 +733,7 @@ fn implement_interface(
|
|||||||
item.span,
|
item.span,
|
||||||
"`#[derive(Ipc)]` may only be applied to item implementations");
|
"`#[derive(Ipc)]` may only be applied to item implementations");
|
||||||
return Err(Error);
|
return Err(Error);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
let impl_generics = builder.from_generics(generics.clone()).build();
|
let impl_generics = builder.from_generics(generics.clone()).build();
|
||||||
let where_clause = &impl_generics.where_clause;
|
let where_clause = &impl_generics.where_clause;
|
||||||
@ -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)|
|
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>>();
|
.collect::<Vec<Dispatch>>();
|
||||||
|
|
||||||
let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false, &replacements);
|
let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false);
|
||||||
let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true, &replacements);
|
let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true);
|
||||||
|
|
||||||
let (handshake_arm, handshake_arm_buf) = implement_handshake_arm(cx);
|
let (handshake_arm, handshake_arm_buf) = implement_handshake_arm(cx);
|
||||||
|
|
||||||
@ -852,7 +793,6 @@ fn implement_interface(
|
|||||||
original_item: item.clone(),
|
original_item: item.clone(),
|
||||||
item: ipc_item,
|
item: ipc_item,
|
||||||
dispatches: dispatch_table,
|
dispatches: dispatch_table,
|
||||||
replacements: replacements,
|
|
||||||
generics: generics.clone(),
|
generics: generics.clone(),
|
||||||
impl_trait: impl_trait.clone(),
|
impl_trait: impl_trait.clone(),
|
||||||
})
|
})
|
||||||
|
@ -16,4 +16,3 @@
|
|||||||
|
|
||||||
mod codegen;
|
mod codegen;
|
||||||
mod serialization;
|
mod serialization;
|
||||||
pub mod typegen;
|
|
||||||
|
@ -155,6 +155,16 @@ struct BinaryExpressions {
|
|||||||
pub read: P<ast::Expr>,
|
pub read: P<ast::Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
fn binary_expr_struct(
|
||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
@ -166,18 +176,21 @@ fn binary_expr_struct(
|
|||||||
|
|
||||||
let size_exprs: Vec<P<ast::Expr>> = fields.iter().enumerate().map(|(index, field)| {
|
let size_exprs: Vec<P<ast::Expr>> = fields.iter().enumerate().map(|(index, field)| {
|
||||||
let field_type_ident = builder.id(
|
let field_type_ident = builder.id(
|
||||||
&::syntax::print::pprust::ty_to_string(
|
&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)));
|
||||||
&codegen::strip_ptr(&field.ty)));
|
|
||||||
|
let field_type_ident_qualified = builder.id(
|
||||||
|
replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))));
|
||||||
|
|
||||||
let index_ident = builder.id(format!("__field{}", index));
|
let index_ident = builder.id(format!("__field{}", index));
|
||||||
value_ident.and_then(|x| {
|
value_ident.and_then(|x| {
|
||||||
let field_id = builder.id(field.ident.unwrap());
|
let field_id = builder.id(field.ident.unwrap());
|
||||||
Some(quote_expr!(cx,
|
Some(quote_expr!(cx,
|
||||||
match $field_type_ident::len_params() {
|
match $field_type_ident_qualified::len_params() {
|
||||||
0 => mem::size_of::<$field_type_ident>(),
|
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() {
|
.unwrap_or_else(|| quote_expr!(cx, match $field_type_ident_qualified::len_params() {
|
||||||
0 => mem::size_of::<$field_type_ident>(),
|
0 => mem::size_of::<$field_type_ident>(),
|
||||||
_ => $index_ident .size(),
|
_ => $index_ident .size(),
|
||||||
}))
|
}))
|
||||||
@ -199,8 +212,10 @@ fn binary_expr_struct(
|
|||||||
map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap());
|
map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap());
|
||||||
for (index, field) in fields.iter().enumerate() {
|
for (index, field) in fields.iter().enumerate() {
|
||||||
let field_type_ident = builder.id(
|
let field_type_ident = builder.id(
|
||||||
&::syntax::print::pprust::ty_to_string(
|
&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)));
|
||||||
&codegen::strip_ptr(&field.ty)));
|
|
||||||
|
let field_type_ident_qualified = builder.id(
|
||||||
|
replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))));
|
||||||
|
|
||||||
let member_expr = match value_ident {
|
let member_expr = match value_ident {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
@ -213,7 +228,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>(),
|
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());
|
}).unwrap());
|
||||||
@ -225,7 +240,7 @@ fn binary_expr_struct(
|
|||||||
|
|
||||||
let field_index = builder.id(&format!("{}", index));
|
let field_index = builder.id(&format!("{}", index));
|
||||||
map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap());
|
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>(),
|
0 => mem::size_of::<$field_type_ident>(),
|
||||||
_ => length_stack.pop_front().unwrap(),
|
_ => length_stack.pop_front().unwrap(),
|
||||||
}).unwrap());
|
}).unwrap());
|
||||||
@ -371,7 +386,7 @@ fn fields_sequence(
|
|||||||
tt.push(Token(
|
tt.push(Token(
|
||||||
_sp,
|
_sp,
|
||||||
token::Ident(
|
token::Ident(
|
||||||
ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)),
|
ext_cx.ident_of(&replace_qualified(&::syntax::print::pprust::ty_to_string(&field.ty))),
|
||||||
token::Plain)));
|
token::Plain)));
|
||||||
tt.push(Token(_sp, token::ModSep));
|
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::Ident(ext_cx.ident_of("from_bytes"), token::Plain)));
|
||||||
@ -445,7 +460,7 @@ fn named_fields_sequence(
|
|||||||
tt.push(Token(
|
tt.push(Token(
|
||||||
_sp,
|
_sp,
|
||||||
token::Ident(
|
token::Ident(
|
||||||
ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)),
|
ext_cx.ident_of(&replace_qualified(&::syntax::print::pprust::ty_to_string(&field.ty))),
|
||||||
token::Plain)));
|
token::Plain)));
|
||||||
tt.push(Token(_sp, token::ModSep));
|
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::Ident(ext_cx.ident_of("from_bytes"), token::Plain)));
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -17,6 +17,7 @@
|
|||||||
//! Binary representation of types
|
//! Binary representation of types
|
||||||
|
|
||||||
use util::bytes::Populatable;
|
use util::bytes::Populatable;
|
||||||
|
use util::numbers::{U256, H256, H2048, Address};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
@ -63,6 +64,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(_) => 0,
|
||||||
|
Err(ref e) => e.size(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque<usize>) -> Result<(), BinaryConvertError> {
|
||||||
|
match *self {
|
||||||
|
Ok(_) => 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 {
|
impl<T> BinaryConvertable for Vec<T> where T: BinaryConvertable {
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
match T::len_params() {
|
match T::len_params() {
|
||||||
@ -128,11 +186,93 @@ 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<T> BinaryConvertable for ::std::cell::RefCell<T> where T: BinaryConvertable {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.borrow().size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_empty_bytes() -> Result<Self, BinaryConvertError> {
|
||||||
|
Ok(::std::cell::RefCell::new(try!(T::from_empty_bytes())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque<usize>) -> Result<Self, BinaryConvertError> {
|
||||||
|
Ok(::std::cell::RefCell::new(try!(T::from_bytes(buffer, length_stack))))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque<usize>) -> Result<(), BinaryConvertError> {
|
||||||
|
try!(self.borrow().to_bytes(buffer, length_stack));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len_params() -> usize {
|
||||||
|
T::len_params()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
pub fn deserialize_from<T, R>(r: &mut R) -> Result<T, BinaryConvertError>
|
||||||
where R: ::std::io::Read,
|
where R: ::std::io::Read,
|
||||||
T: BinaryConvertable
|
T: BinaryConvertable
|
||||||
{
|
{
|
||||||
let mut fake_stack = VecDeque::new();
|
let mut fake_stack = VecDeque::new();
|
||||||
|
|
||||||
|
match T::len_params() {
|
||||||
|
0 => {
|
||||||
|
let fixed_size = mem::size_of::<T>();
|
||||||
|
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::<usize>::new();
|
let mut length_stack = VecDeque::<usize>::new();
|
||||||
let mut size_buffer = [0u8; 8];
|
let mut size_buffer = [0u8; 8];
|
||||||
try!(r.read(&mut size_buffer[..]).map_err(|_| BinaryConvertError));
|
try!(r.read(&mut size_buffer[..]).map_err(|_| BinaryConvertError));
|
||||||
@ -156,14 +296,33 @@ pub fn deserialize_from<T, R>(r: &mut R) -> Result<T, BinaryConvertError>
|
|||||||
try!(r.read(&mut data).map_err(|_| BinaryConvertError));
|
try!(r.read(&mut data).map_err(|_| BinaryConvertError));
|
||||||
|
|
||||||
T::from_bytes(&data[..], &mut length_stack)
|
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>
|
pub fn serialize_into<T, W>(t: &T, w: &mut W) -> Result<(), BinaryConvertError>
|
||||||
where W: ::std::io::Write,
|
where W: ::std::io::Write,
|
||||||
T: BinaryConvertable
|
T: BinaryConvertable
|
||||||
{
|
{
|
||||||
let mut length_stack = VecDeque::<usize>::new();
|
|
||||||
let mut fake_stack = VecDeque::new();
|
let mut fake_stack = VecDeque::new();
|
||||||
|
|
||||||
|
match T::len_params() {
|
||||||
|
0 => {
|
||||||
|
let fixed_size = mem::size_of::<T>();
|
||||||
|
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::<usize>::new();
|
||||||
let mut size_buffer = [0u8; 8];
|
let mut size_buffer = [0u8; 8];
|
||||||
|
|
||||||
let size = t.size();
|
let size = t.size();
|
||||||
@ -195,6 +354,15 @@ pub fn serialize_into<T, W>(t: &T, w: &mut W) -> Result<(), BinaryConvertError>
|
|||||||
try!(w.write(&buffer[..]).map_err(|_| BinaryConvertError));
|
try!(w.write(&buffer[..]).map_err(|_| BinaryConvertError));
|
||||||
|
|
||||||
Ok(())
|
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 {
|
macro_rules! binary_fixed_size {
|
||||||
@ -226,7 +394,13 @@ macro_rules! binary_fixed_size {
|
|||||||
|
|
||||||
binary_fixed_size!(u64);
|
binary_fixed_size!(u64);
|
||||||
binary_fixed_size!(u32);
|
binary_fixed_size!(u32);
|
||||||
|
binary_fixed_size!(usize);
|
||||||
|
binary_fixed_size!(i32);
|
||||||
binary_fixed_size!(bool);
|
binary_fixed_size!(bool);
|
||||||
|
binary_fixed_size!(U256);
|
||||||
|
binary_fixed_size!(H256);
|
||||||
|
binary_fixed_size!(H2048);
|
||||||
|
binary_fixed_size!(Address);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vec_serialize() {
|
fn vec_serialize() {
|
||||||
|
@ -9,8 +9,6 @@ path = "run.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
"ethcore-ipc" = { path = "../rpc" }
|
"ethcore-ipc" = { path = "../rpc" }
|
||||||
bincode = "*"
|
|
||||||
serde = "0.7.0"
|
|
||||||
ethcore-devtools = { path = "../../devtools" }
|
ethcore-devtools = { path = "../../devtools" }
|
||||||
semver = "0.2.0"
|
semver = "0.2.0"
|
||||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||||
|
@ -38,7 +38,7 @@ pub fn main() {
|
|||||||
let src = Path::new(&out_dir).join("nested_ipc.rs");
|
let src = Path::new(&out_dir).join("nested_ipc.rs");
|
||||||
let dst = Path::new(&out_dir).join("nested_cg.rs");
|
let dst = Path::new(&out_dir).join("nested_cg.rs");
|
||||||
let mut registry = syntex::Registry::new();
|
let mut registry = syntex::Registry::new();
|
||||||
serde_codegen::register(&mut registry);
|
codegen::register(&mut registry);
|
||||||
registry.expand("", &src, &dst).unwrap();
|
registry.expand("", &src, &dst).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ pub fn main() {
|
|||||||
let src = Path::new(&out_dir).join("service_ipc.rs");
|
let src = Path::new(&out_dir).join("service_ipc.rs");
|
||||||
let dst = Path::new(&out_dir).join("service_cg.rs");
|
let dst = Path::new(&out_dir).join("service_cg.rs");
|
||||||
let mut registry = syntex::Registry::new();
|
let mut registry = syntex::Registry::new();
|
||||||
serde_codegen::register(&mut registry);
|
codegen::register(&mut registry);
|
||||||
registry.expand("", &src, &dst).unwrap();
|
registry.expand("", &src, &dst).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn call_service() {
|
fn call_service() {
|
||||||
// method_num = 0, f = 10 (method Service::commit)
|
// 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();
|
let service = Service::new();
|
||||||
assert_eq!(0, *service.commits.read().unwrap());
|
assert_eq!(0, *service.commits.read().unwrap());
|
||||||
@ -41,12 +45,20 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn call_service_handshake() {
|
fn call_service_handshake() {
|
||||||
let mut socket = TestSocket::new_ready(vec![0, 0,
|
let mut socket = TestSocket::new_ready(vec![0, 0,
|
||||||
|
// part count = 3
|
||||||
|
3, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
// part sizes
|
||||||
|
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
|
||||||
|
70, 0, 0, 0, 0, 0, 0, 0,
|
||||||
// protocol version
|
// protocol version
|
||||||
0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0',
|
b'1', b'.', b'0', b'.', b'0',
|
||||||
// api version
|
// api version
|
||||||
0, 0, 0, 0, 0, 0, 0, 5, b'1', b'.', b'0', b'.', b'0',
|
b'1', b'.', b'0', b'.', b'0',
|
||||||
// reserved
|
// 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,
|
||||||
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,
|
||||||
@ -64,24 +76,34 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn call_service_client() {
|
fn call_service_client() {
|
||||||
let mut socket = TestSocket::new();
|
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 service_client = ServiceClient::init(socket);
|
||||||
|
|
||||||
let result = service_client.commit(5);
|
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);
|
assert_eq!(10, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn call_service_client_optional() {
|
fn call_service_client_optional() {
|
||||||
let mut socket = TestSocket::new();
|
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 service_client = ServiceClient::init(socket);
|
||||||
|
|
||||||
let result = service_client.rollback(Some(5), 10);
|
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);
|
assert_eq!(10, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +137,12 @@ mod tests {
|
|||||||
assert_eq!(vec![
|
assert_eq!(vec![
|
||||||
// message num..
|
// message num..
|
||||||
0, 18,
|
0, 18,
|
||||||
// payload length
|
// variable size length-s
|
||||||
0, 0, 0, 0, 0, 0, 0, 16,
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
// structure raw bytes (bigendians :( )
|
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,
|
3, 0, 0, 0, 0, 0, 0, 0,
|
||||||
11, 0, 0, 0, 0, 0, 0, 0],
|
11, 0, 0, 0, 0, 0, 0, 0],
|
||||||
service_client.socket().borrow().write_buffer.clone());
|
service_client.socket().borrow().write_buffer.clone());
|
||||||
@ -127,13 +152,19 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_invoke_generic_service() {
|
fn can_invoke_generic_service() {
|
||||||
let mut socket = TestSocket::new();
|
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::<u64, _>::init(socket);
|
let db_client = DBClient::<u64, _>::init(socket);
|
||||||
|
|
||||||
let result = db_client.write(vec![0u8; 100]);
|
let result = db_client.write(vec![0u8; 100]);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_handshake_generic_service() {
|
fn can_handshake_generic_service() {
|
||||||
let mut socket = TestSocket::new();
|
let mut socket = TestSocket::new();
|
||||||
|
@ -14,4 +14,5 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// 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"));
|
include!(concat!(env!("OUT_DIR"), "/nested_cg.rs"));
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
use ipc::IpcConfig;
|
use ipc::IpcConfig;
|
||||||
|
use ipc::BinaryConvertable;
|
||||||
|
use std::mem;
|
||||||
|
use ipc::binary::BinaryConvertError;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub struct DB<L: Sized> {
|
pub struct DB<L: Sized> {
|
||||||
pub writes: RwLock<u64>,
|
pub writes: RwLock<u64>,
|
||||||
@ -30,7 +34,7 @@ pub trait DBWriter {
|
|||||||
|
|
||||||
impl<L: Sized> IpcConfig for DB<L> {}
|
impl<L: Sized> IpcConfig for DB<L> {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Binary)]
|
||||||
pub enum DBError { Write, Read }
|
pub enum DBError { Write, Read }
|
||||||
|
|
||||||
#[derive(Ipc)]
|
#[derive(Ipc)]
|
||||||
|
@ -20,7 +20,7 @@ mod tests {
|
|||||||
use super::super::service::*;
|
use super::super::service::*;
|
||||||
use nanoipc;
|
use nanoipc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::io::{Write, Read};
|
use std::io::Write;
|
||||||
use std::sync::atomic::{Ordering, AtomicBool};
|
use std::sync::atomic::{Ordering, AtomicBool};
|
||||||
|
|
||||||
fn dummy_write(addr: &str, buf: &[u8]) -> (::nanomsg::Socket, ::nanomsg::Endpoint) {
|
fn dummy_write(addr: &str, buf: &[u8]) -> (::nanomsg::Socket, ::nanomsg::Endpoint) {
|
||||||
@ -67,42 +67,4 @@ mod tests {
|
|||||||
worker_should_exit.store(true, Ordering::Relaxed);
|
worker_should_exit.store(true, Ordering::Relaxed);
|
||||||
assert!(hs.is_ok());
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,5 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// 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"));
|
include!(concat!(env!("OUT_DIR"), "/service_cg.rs"));
|
||||||
|
@ -16,40 +16,20 @@
|
|||||||
|
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
use std::convert::*;
|
|
||||||
use ipc::IpcConfig;
|
use ipc::IpcConfig;
|
||||||
use util::bytes::{FromRawBytes, BytesConvertable, FromBytesError};
|
use std::mem;
|
||||||
|
use ipc::binary::BinaryConvertError;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub commits: RwLock<usize>,
|
pub commits: RwLock<usize>,
|
||||||
pub rollbacks: RwLock<usize>,
|
pub rollbacks: RwLock<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Binary)]
|
||||||
pub struct CustomData {
|
pub struct CustomData {
|
||||||
pub a: usize,
|
pub a: u64,
|
||||||
pub b: usize,
|
pub b: u64,
|
||||||
}
|
|
||||||
|
|
||||||
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>()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Ipc)]
|
#[derive(Ipc)]
|
||||||
@ -69,8 +49,8 @@ impl Service {
|
|||||||
let mut clock = self.commits.write().unwrap();
|
let mut clock = self.commits.write().unwrap();
|
||||||
let mut rlock = self.commits.write().unwrap();
|
let mut rlock = self.commits.write().unwrap();
|
||||||
|
|
||||||
*clock = data.a;
|
*clock = data.a as usize;
|
||||||
*rlock = data.b;
|
*rlock = data.b as usize;
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,6 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Parity interprocess hypervisor IPC service
|
//! Parity interprocess hypervisor IPC service
|
||||||
|
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/hypervisor_service_cg.rs"));
|
include!(concat!(env!("OUT_DIR"), "/hypervisor_service_cg.rs"));
|
||||||
|
@ -18,6 +18,10 @@ use std::sync::{RwLock,Arc};
|
|||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
use ipc::IpcConfig;
|
use ipc::IpcConfig;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use ipc::BinaryConvertable;
|
||||||
|
use std::mem;
|
||||||
|
use ipc::binary::BinaryConvertError;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub type IpcModuleId = u64;
|
pub type IpcModuleId = u64;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user