From 15ecbaf59c65bf3022a4d42784d5c1eab1df9fdb Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 01:40:30 +0300 Subject: [PATCH 01/17] invoke with hand-written code and tests --- ipc/tests/examples.rs | 12 ++++++++++++ ipc/tests/service.rs.in | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 280e25d08..a285e4c52 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -33,4 +33,16 @@ mod tests { assert_eq!(10, *service.commits.read().unwrap()); } + + #[test] + fn call_service_proxy() { + let mut socket = TestSocket::new(); + socket.read_buffer = vec![0, 0, 0, 10]; + let service_proxy = ServiceProxy::new(socket); + + let result = service_proxy.commit(5); + + assert_eq!(vec![0, 0, 0, 0, 0, 5], service_proxy.socket().borrow().write_buffer.clone()); + assert_eq!(10, result); + } } diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 64b43c2ef..683b9ccde 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::sync::RwLock; +use std::ops::*; pub struct Service { pub commits: RwLock, @@ -35,6 +36,37 @@ impl Service { } } +impl ServiceProxy { + pub fn commit(&self, f: u32) -> u32 { + #[derive(Serialize)] + struct Request<'a> { + f: &'a u32, + } + let payload = Request{ f: &f, }; + + let mut socket_ref = self.socket.borrow_mut(); + let mut socket = socket_ref.deref_mut(); + + let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); + ::ipc::invoke(0, &Some(serialized_payload), &mut socket); + + while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } + ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() + } + + pub fn new(socket: S) -> ServiceProxy { + ServiceProxy { + socket: ::std::cell::RefCell::new(socket), + phantom: ::std::marker::PhantomData, + } + } + + #[cfg(test)] + pub fn socket(&self) -> &::std::cell::RefCell { + &self.socket + } +} + impl Service { pub fn new() -> Service { Service { From 44ea98801ba6f8363e470d28ac511f3ff6278a4a Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 01:40:43 +0300 Subject: [PATCH 02/17] invoke with hand-written code and tests --- ipc/codegen/src/codegen.rs | 23 ++++++++++++++++++----- ipc/rpc/Cargo.toml | 1 + ipc/rpc/src/interface.rs | 26 ++++++++++++++++++++++++-- ipc/rpc/src/lib.rs | 4 +++- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 69160bed5..b5e7fc994 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -57,6 +57,8 @@ pub fn expand_ipc_implementation( Err(Error) => { return; } }; + push_proxy(cx, &builder, &item, push); + push(Annotatable::Item(impl_item)) } @@ -220,6 +222,22 @@ fn implement_dispatch_arm(cx: &ExtCtxt, builder: &aster::AstBuilder, index: u32, quote_arm!(cx, $index_ident => { $invoke_expr } ) } +fn push_proxy_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { + let proxy_ident = builder.id(format!("{}Proxy", item.ident.name.as_str())); + + let proxy_struct_item = quote_item!(cx, + pub struct $proxy_ident { + socket: ::std::cell::RefCell, + phantom: ::std::marker::PhantomData, + }); + + push(Annotatable::Item(proxy_struct_item.expect(&format!("could not generate proxy struct for {:?}", proxy_ident.name)))); +} + +fn push_proxy(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { + push_proxy_struct(cx, builder, item, push) +} + fn implement_interface( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -274,11 +292,6 @@ fn implement_interface( _ => vec![] } } - fn invoke(&self, _method_num: u16, _payload: &Option>, _w: &mut W) - where W: ::std::io::Write - { - } - } ).unwrap()) } diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml index b8a05f543..99fcd3233 100644 --- a/ipc/rpc/Cargo.toml +++ b/ipc/rpc/Cargo.toml @@ -7,3 +7,4 @@ license = "GPL-3.0" [features] [dependencies] +ethcore-devtools = { path = "../../devtools" } diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index 111176b1f..f51e82dfa 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -19,6 +19,28 @@ pub trait IpcInterface { /// reads the message from io, dispatches the call and returns result fn dispatch(&self, r: &mut R) -> Vec where R: ::std::io::Read; - /// encodes the invocation, writes payload and waits for result - fn invoke(&self, method_num: u16, params: &Option>, w: &mut W) where W: ::std::io::Write; +} + +pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: ::std::io::Write { + let buf_len = match *params { None => 2, Some(ref val) => val.len() + 2 }; + let mut buf = vec![0u8; buf_len]; + buf[0] = (method_num & (255<<8)) as u8; + buf[1] = (method_num >> 8) as u8; + if params.is_some() { + buf[2..buf_len].clone_from_slice(params.as_ref().unwrap()); + } + if w.write(&buf).unwrap() != buf_len + { + panic!("failed to write to socket"); + } +} + +pub trait IpcSocket: ::std::io::Read + ::std::io::Write { + fn ready(&self) -> ::std::sync::atomic::AtomicBool; +} + +impl IpcSocket for ::devtools::TestSocket { + fn ready(&self) -> ::std::sync::atomic::AtomicBool { + ::std::sync::atomic::AtomicBool::new(true) + } } diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index 5018a5cd2..f8c68cdbd 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -16,5 +16,7 @@ //! IPC RPC interface +extern crate ethcore_devtools as devtools; + pub mod interface; -pub use interface::IpcInterface; +pub use interface::{IpcInterface, IpcSocket, invoke}; From 3de46a31d989c27c704db6cad52407b2c11967eb Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 01:55:04 +0300 Subject: [PATCH 03/17] extracting type info for args --- ipc/codegen/src/codegen.rs | 52 +++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index b5e7fc994..8cd066daf 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -25,6 +25,7 @@ use syntax::ast::{ Arg, PatKind, FunctionRetTy, + Ty, }; use syntax::ast; @@ -77,33 +78,38 @@ fn push_invoke_signature_aster( ) -> Dispatch { let inputs = &signature.decl.inputs; - let (input_type_name, input_arg_names) = if inputs.len() > 0 { + let (input_type_name, input_arg_names, input_arg_tys) = if inputs.len() > 0 { let first_field_name = field_name(builder, &inputs[0]).name.as_str(); - if first_field_name == "self" && inputs.len() == 1 { (None, vec![]) } + if first_field_name == "self" && inputs.len() == 1 { (None, vec![], vec![]) } else { let skip = if first_field_name == "self" { 2 } else { 1 }; let name_str = format!("{}_input", implement.ident.name.as_str()); let mut arg_names = Vec::new(); + let mut arg_tys = Vec::new(); let arg_name = format!("{}", field_name(builder, &inputs[skip-1]).name); + let arg_ty = inputs[skip-1].ty.clone(); let mut tree = builder.item() .attr().word("derive(Serialize, Deserialize)") .attr().word("allow(non_camel_case_types)") .struct_(name_str.as_str()) - .field(arg_name.as_str()).ty().build(inputs[skip-1].ty.clone()); + .field(arg_name.as_str()).ty().build(arg_ty.clone()); arg_names.push(arg_name); + arg_tys.push(arg_ty.clone()); for arg in inputs.iter().skip(skip) { let arg_name = format!("{}", field_name(builder, &arg)); - tree = tree.field(arg_name.as_str()).ty().build(arg.ty.clone()); + let arg_ty = arg.ty.clone(); + tree = tree.field(arg_name.as_str()).ty().build(arg_ty.clone()); arg_names.push(arg_name); + arg_tys.push(arg_ty); } push(Annotatable::Item(tree.build())); - (Some(name_str.to_owned()), arg_names) + (Some(name_str.to_owned()), arg_names, arg_tys) } } else { - (None, vec![]) + (None, vec![], vec![]) }; let return_type_name = match signature.decl.output { @@ -124,6 +130,7 @@ fn push_invoke_signature_aster( function_name: format!("{}", implement.ident.name.as_str()), input_type_name: input_type_name, input_arg_names: input_arg_names, + input_arg_tys: input_arg_tys, return_type_name: return_type_name, } } @@ -132,6 +139,7 @@ struct Dispatch { function_name: String, input_type_name: Option, input_arg_names: Vec, + input_arg_tys: Vec>, return_type_name: Option, } @@ -238,6 +246,38 @@ fn push_proxy(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut push_proxy_struct(cx, builder, item, push) } +fn push_proxy_implementation_method( + cx: &ExtCtxt, + builder: + &aster::AstBuilder, + item: &Item, + dispatch: &Dispatch, + push: &mut FnMut(Annotatable)) +{ + let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); + + let invariant_serialization = quote_expr!(cx, { + let mut socket_ref = self.socket.borrow_mut(); + let mut socket = socket_ref.deref_mut(); + + let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); + ::ipc::invoke(0, &Some(serialized_payload), &mut socket); + + while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } + ::bincode::serde::deserialize_from::<_, $output_type_id>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() + }); +} + +fn push_proxy_implementation( + cx: &ExtCtxt, + builder: + &aster::AstBuilder, + item: &Item, + dispatches: &[Dispatch], + push: &mut FnMut(Annotatable)) +{ +} + fn implement_interface( cx: &ExtCtxt, builder: &aster::AstBuilder, From bd377e1f28c39aae472dbc67db5a7f9b53a5f187 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 22:00:23 +0300 Subject: [PATCH 04/17] almost valid signature (re)generation --- ipc/codegen/src/codegen.rs | 214 +++++++++++++++++++++++++++++++------ 1 file changed, 179 insertions(+), 35 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 8cd066daf..ce24c9cd8 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -53,12 +53,12 @@ pub fn expand_ipc_implementation( let builder = aster::AstBuilder::new().span(span); - let impl_item = match implement_interface(cx, &builder, &item, push) { - Ok(item) => item, + let (impl_item, dispatches) = match implement_interface(cx, &builder, &item, push) { + Ok((item, dispatches)) => (item, dispatches), Err(Error) => { return; } }; - push_proxy(cx, &builder, &item, push); + push_proxy(cx, &builder, &item, &dispatches, push); push(Annotatable::Item(impl_item)) } @@ -242,40 +242,184 @@ fn push_proxy_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, pus push(Annotatable::Item(proxy_struct_item.expect(&format!("could not generate proxy struct for {:?}", proxy_ident.name)))); } -fn push_proxy(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { - push_proxy_struct(cx, builder, item, push) -} - -fn push_proxy_implementation_method( +fn push_proxy( cx: &ExtCtxt, - builder: - &aster::AstBuilder, - item: &Item, - dispatch: &Dispatch, - push: &mut FnMut(Annotatable)) -{ - let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); - - let invariant_serialization = quote_expr!(cx, { - let mut socket_ref = self.socket.borrow_mut(); - let mut socket = socket_ref.deref_mut(); - - let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); - ::ipc::invoke(0, &Some(serialized_payload), &mut socket); - - while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } - ::bincode::serde::deserialize_from::<_, $output_type_id>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() - }); -} - -fn push_proxy_implementation( - cx: &ExtCtxt, - builder: - &aster::AstBuilder, + builder: &aster::AstBuilder, item: &Item, dispatches: &[Dispatch], push: &mut FnMut(Annotatable)) { + push_proxy_struct(cx, builder, item, push); + push_proxy_implementation(cx, builder, dispatches, push); +} + +fn implement_proxy_method_body( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + dispatch: &Dispatch) + -> P +{ + let request = if dispatch.input_arg_names.len() > 0 { + let arg_name = dispatch.input_arg_names[0].as_str(); + let arg_ty = builder + .ty().ref_() + .lifetime("'a") + .ty().build(dispatch.input_arg_tys[0].clone()); + + let mut tree = builder.item() + .attr().word("derive(Serialize)") + .struct_("Request") + .generics() + .lifetime_name("'a") + .build() + .field(arg_name).ty().build(arg_ty); + + for arg_idx in 1..dispatch.input_arg_names.len() { + let arg_name = dispatch.input_arg_names[arg_idx].as_str(); + let arg_ty = builder + .ty().ref_() + .lifetime("'a") + .ty().build(dispatch.input_arg_tys[arg_idx].clone()); + tree = tree.field(arg_name).ty().build(arg_ty); + } + let mut request_serialization_statements = Vec::new(); + + let struct_tree = tree.build(); + let struct_stmt = quote_stmt!(cx, $struct_tree); + request_serialization_statements.push(struct_stmt); + + // actually this is just expanded version of this: + // request_serialization_statements.push(quote_stmt!(cx, let payload = Request { p1: &p1, p2: &p2, ... pn: &pn, })); + // again, cannot dynamically create expression with arbitrary number of comma-separated members + request_serialization_statements.push({ + let ext_cx = &*cx; + ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("let"), ::syntax::parse::token::Plain))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("payload"), ::syntax::parse::token::Plain))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Eq)); + 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 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))); + 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::Comma)); + } + + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Brace))); + tt + })) + }); + + request_serialization_statements.push( + quote_stmt!(cx, let mut socket_ref = self.socket.borrow_mut())); + + request_serialization_statements.push( + 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())); + + request_serialization_statements.push( + quote_stmt!(cx, ::ipc::invoke(0, &Some(serialized_payload), &mut socket))); + + + request_serialization_statements + } + else { + vec![] + }; + + let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); + let invariant_serialization = quote_expr!(cx, { + while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } + ::bincode::serde::deserialize_from::<_, $output_type_id>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() + }); + + quote_expr!(cx, { + $request + $invariant_serialization + }) +} + +fn implement_proxy_method( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + dispatch: &Dispatch) + -> ast::ImplItem +{ + let method_name = builder.id(dispatch.function_name.as_str()); + let body = implement_proxy_method_body(cx, builder, dispatch); + + let ext_cx = &*cx; + // expanded version of this + // pub fn $method_name(&self, p1: p1_ty, p2: p2_ty ... pn: pn_ty, ) [-> return_ty] { $body } + // looks like it's tricky to build function declaration with aster if body already generated + let signature = ::syntax::parse::parser::Parser::parse_impl_item( + &mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("pub"), ::syntax::parse::token::Plain))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("fn"), ::syntax::parse::token::Plain))); + tt.extend(::quasi::ToTokens::to_tokens(&method_name, ext_cx).into_iter()); + 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::BinOp(::syntax::parse::token::And))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("self"), ::syntax::parse::token::Plain))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Comma)); + + for arg_idx in 0..dispatch.input_arg_names.len() { + let arg_name = dispatch.input_arg_names[arg_idx].as_str(); + let arg_ty = dispatch.input_arg_tys[arg_idx].clone(); + + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg_name), ::syntax::parse::token::Plain))); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Colon)); + tt.extend(::quasi::ToTokens::to_tokens(&arg_ty, ext_cx).into_iter()); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Comma)); + } + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); + + if let Some(ref return_name) = dispatch.return_type_name { + let return_ident = builder.id(return_name); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::RArrow)); + tt.extend(::quasi::ToTokens::to_tokens(&return_ident, ext_cx).into_iter()); + } + + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); + tt.extend(::quasi::ToTokens::to_tokens(&body, ext_cx).into_iter()); + tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Brace))); + + tt + })); + + signature.unwrap() +} + +fn push_proxy_implementation( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + dispatches: &[Dispatch], + push: &mut FnMut(Annotatable)) +{ + let items = dispatches.iter() + .map(|dispatch| P(implement_proxy_method(cx, builder, dispatch))) + .collect::>>(); + + let implement = quote_item!(cx, + impl ServiceProxy where S: ::ipc::IpcSocket { + $items + }).unwrap(); + + push(Annotatable::Item(implement)); } fn implement_interface( @@ -283,7 +427,7 @@ fn implement_interface( builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable), -) -> Result, Error> { +) -> Result<(P, Vec), Error> { let (generics, impl_items) = match item.node { ast::ItemKind::Impl(_, _, ref generics, _, _, ref impl_items) => (generics, impl_items), _ => { @@ -316,7 +460,7 @@ fn implement_interface( let dispatch_arms: Vec<_> = dispatch_table.iter() .map(|dispatch| { index = index + 1; implement_dispatch_arm(cx, builder, index as u32, dispatch) }).collect(); - Ok(quote_item!(cx, + Ok((quote_item!(cx, impl $impl_generics ::ipc::IpcInterface<$ty> for $ty $where_clause { fn dispatch(&self, r: &mut R) -> Vec where R: ::std::io::Read @@ -333,5 +477,5 @@ fn implement_interface( } } } - ).unwrap()) + ).unwrap(), dispatch_table)) } From 34f6c1f2f1949cc82b1802702aa0c6eea61ac516 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 22:15:45 +0300 Subject: [PATCH 05/17] replaced hand-written with generated --- ipc/codegen/src/codegen.rs | 47 +++++++++++++++++++++++++------------- ipc/tests/service.rs.in | 17 -------------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index ce24c9cd8..b6e823fde 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -112,7 +112,7 @@ fn push_invoke_signature_aster( (None, vec![], vec![]) }; - let return_type_name = match signature.decl.output { + let (return_type_name, return_type_ty) = match signature.decl.output { FunctionRetTy::Ty(ref ty) => { let name_str = format!("{}_output", implement.ident.name.as_str()); let tree = builder.item() @@ -121,9 +121,9 @@ fn push_invoke_signature_aster( .struct_(name_str.as_str()) .field(format!("payload")).ty().build(ty.clone()); push(Annotatable::Item(tree.build())); - Some(name_str.to_owned()) + (Some(name_str.to_owned()), Some(ty.clone())) } - _ => None + _ => (None, None) }; Dispatch { @@ -132,6 +132,7 @@ fn push_invoke_signature_aster( input_arg_names: input_arg_names, input_arg_tys: input_arg_tys, return_type_name: return_type_name, + return_type_ty: return_type_ty, } } @@ -141,6 +142,7 @@ struct Dispatch { input_arg_names: Vec, input_arg_tys: Vec>, return_type_name: Option, + return_type_ty: Option>, } fn implement_dispatch_arm_invoke( @@ -337,16 +339,30 @@ fn implement_proxy_method_body( vec![] }; - let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); - let invariant_serialization = quote_expr!(cx, { - while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } - ::bincode::serde::deserialize_from::<_, $output_type_id>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() - }); + let wait_result_stmt = quote_stmt!(cx, while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { }); + 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() + ); + quote_expr!(cx, { + $request + $wait_result_stmt + $return_expr + }) + } + else { + quote_expr!(cx, { + $request + $wait_result_stmt + }) + } + + //let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); +// let invariant_serialization = quote_expr!(cx, { +// +// +// }); - quote_expr!(cx, { - $request - $invariant_serialization - }) } fn implement_proxy_method( @@ -376,7 +392,7 @@ fn implement_proxy_method( 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::Ident(ext_cx.ident_of("self"), ::syntax::parse::token::Plain))); tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::Comma)); - + for arg_idx in 0..dispatch.input_arg_names.len() { let arg_name = dispatch.input_arg_names[arg_idx].as_str(); let arg_ty = dispatch.input_arg_tys[arg_idx].clone(); @@ -388,10 +404,9 @@ fn implement_proxy_method( } tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - if let Some(ref return_name) = dispatch.return_type_name { - let return_ident = builder.id(return_name); + if let Some(ref return_ty) = dispatch.return_type_ty { tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::RArrow)); - tt.extend(::quasi::ToTokens::to_tokens(&return_ident, ext_cx).into_iter()); + tt.extend(::quasi::ToTokens::to_tokens(return_ty, ext_cx).into_iter()); } tt.push(::syntax::ast::TokenTree::Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 683b9ccde..b4545d320 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -37,23 +37,6 @@ impl Service { } impl ServiceProxy { - pub fn commit(&self, f: u32) -> u32 { - #[derive(Serialize)] - struct Request<'a> { - f: &'a u32, - } - let payload = Request{ f: &f, }; - - let mut socket_ref = self.socket.borrow_mut(); - let mut socket = socket_ref.deref_mut(); - - let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); - ::ipc::invoke(0, &Some(serialized_payload), &mut socket); - - while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } - ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() - } - pub fn new(socket: S) -> ServiceProxy { ServiceProxy { socket: ::std::cell::RefCell::new(socket), From 579d2b1f02bacd7e7d3dbb9061c40c6f770d8373 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 22:29:43 +0300 Subject: [PATCH 06/17] final static functions --- ipc/codegen/src/codegen.rs | 12 ++++++++++++ ipc/tests/service.rs.in | 16 +--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index b6e823fde..621069cc2 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -431,6 +431,18 @@ fn push_proxy_implementation( let implement = quote_item!(cx, impl ServiceProxy where S: ::ipc::IpcSocket { + pub fn new(socket: S) -> ServiceProxy { + ServiceProxy { + socket: ::std::cell::RefCell::new(socket), + phantom: ::std::marker::PhantomData, + } + } + + #[cfg(test)] + pub fn socket(&self) -> &::std::cell::RefCell { + &self.socket + } + $items }).unwrap(); diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index b4545d320..9439e6508 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -36,21 +36,7 @@ impl Service { } } -impl ServiceProxy { - pub fn new(socket: S) -> ServiceProxy { - ServiceProxy { - socket: ::std::cell::RefCell::new(socket), - phantom: ::std::marker::PhantomData, - } - } - - #[cfg(test)] - pub fn socket(&self) -> &::std::cell::RefCell { - &self.socket - } -} - -impl Service { + impl Service { pub fn new() -> Service { Service { commits: RwLock::new(0usize), From fc3d4243156bcf2f0a77aedfaa23a5ea077993cf Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 22:31:20 +0300 Subject: [PATCH 07/17] cleanup --- ipc/codegen/src/codegen.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 621069cc2..5b2b63561 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -356,13 +356,6 @@ fn implement_proxy_method_body( $wait_result_stmt }) } - - //let output_type_id = builder.id(dispatch.return_type_name.clone().unwrap().as_str()); -// let invariant_serialization = quote_expr!(cx, { -// -// -// }); - } fn implement_proxy_method( From 198613a854f9e949e646c4c7ba7bdb117493653a Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 29 Mar 2016 22:40:38 +0300 Subject: [PATCH 08/17] redundant tab --- ipc/tests/service.rs.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 9439e6508..7cb47cda6 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -36,7 +36,7 @@ impl Service { } } - impl Service { +impl Service { pub fn new() -> Service { Service { commits: RwLock::new(0usize), From be405536741d8ba5a97dd2f62aea9a6dcfdbc1b7 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 02:20:01 +0300 Subject: [PATCH 09/17] extra test and method encode fix --- ipc/tests/examples.rs | 12 ++++++++++++ ipc/tests/service.rs.in | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index a285e4c52..2f50f13db 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -45,4 +45,16 @@ mod tests { assert_eq!(vec![0, 0, 0, 0, 0, 5], service_proxy.socket().borrow().write_buffer.clone()); assert_eq!(10, result); } + + #[test] + fn call_service_proxy_optional() { + let mut socket = TestSocket::new(); + socket.read_buffer = vec![0, 0, 0, 10]; + let service_proxy = ServiceProxy::new(socket); + + let result = service_proxy.rollback(Some(5), 10); + + assert_eq!(vec![0, 1, 1, 0, 0, 0, 5, 0, 0, 0, 10], service_proxy.socket().borrow().write_buffer.clone()); + assert_eq!(10, result); + } } diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 7cb47cda6..2b529534a 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -29,10 +29,11 @@ impl Service { *lock = *lock + f as usize; f } - pub fn rollback(&self, a: u32, b: u32) -> i32 { + pub fn rollback(&self, a: Option, b: u32) -> i32 { + let a_0 = a.unwrap_or_else(|| 0); let mut lock = self.rollbacks.write().unwrap(); - *lock = *lock + a as usize - b as usize; - (a - b) as i32 + *lock = *lock + a_0 as usize - b as usize; + (a_0 - b) as i32 } } From 7097451323f47108880da55ad2df2e21eab3aced Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 02:21:47 +0300 Subject: [PATCH 10/17] forgotten upper files --- ipc/codegen/src/codegen.rs | 14 ++++++++++---- ipc/rpc/src/interface.rs | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 5b2b63561..a3a470266 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -258,7 +258,9 @@ fn push_proxy( fn implement_proxy_method_body( cx: &ExtCtxt, builder: &aster::AstBuilder, - dispatch: &Dispatch) + index: u16, + dispatch: &Dispatch, + ) -> P { let request = if dispatch.input_arg_names.len() > 0 { @@ -329,8 +331,10 @@ fn implement_proxy_method_body( request_serialization_statements.push( quote_stmt!(cx, let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap())); + let index_ident = builder.id(format!("{}", index).as_str()); + request_serialization_statements.push( - quote_stmt!(cx, ::ipc::invoke(0, &Some(serialized_payload), &mut socket))); + quote_stmt!(cx, ::ipc::invoke($index_ident, &Some(serialized_payload), &mut socket))); request_serialization_statements @@ -361,11 +365,12 @@ fn implement_proxy_method_body( fn implement_proxy_method( cx: &ExtCtxt, builder: &aster::AstBuilder, + index: u16, dispatch: &Dispatch) -> ast::ImplItem { let method_name = builder.id(dispatch.function_name.as_str()); - let body = implement_proxy_method_body(cx, builder, dispatch); + let body = implement_proxy_method_body(cx, builder, index, dispatch); let ext_cx = &*cx; // expanded version of this @@ -418,8 +423,9 @@ fn push_proxy_implementation( dispatches: &[Dispatch], push: &mut FnMut(Annotatable)) { + let mut index = -1i32; let items = dispatches.iter() - .map(|dispatch| P(implement_proxy_method(cx, builder, dispatch))) + .map(|dispatch| { index = index + 1; P(implement_proxy_method(cx, builder, index as u16, dispatch)) }) .collect::>>(); let implement = quote_item!(cx, diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index f51e82dfa..c99cd3e35 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -24,8 +24,8 @@ pub trait IpcInterface { pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: ::std::io::Write { let buf_len = match *params { None => 2, Some(ref val) => val.len() + 2 }; let mut buf = vec![0u8; buf_len]; - buf[0] = (method_num & (255<<8)) as u8; - buf[1] = (method_num >> 8) as u8; + buf[1] = (method_num & 255) as u8; + buf[0] = (method_num >> 8) as u8; if params.is_some() { buf[2..buf_len].clone_from_slice(params.as_ref().unwrap()); } From 71de6b884959bc97c397d5cbb7a02cee2eb34a5f Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 18:17:49 +0300 Subject: [PATCH 11/17] proxy -> client --- ipc/codegen/src/codegen.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index a3a470266..571dc60bc 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -233,7 +233,7 @@ fn implement_dispatch_arm(cx: &ExtCtxt, builder: &aster::AstBuilder, index: u32, } fn push_proxy_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { - let proxy_ident = builder.id(format!("{}Proxy", item.ident.name.as_str())); + let proxy_ident = builder.id(format!("{}Client", item.ident.name.as_str())); let proxy_struct_item = quote_item!(cx, pub struct $proxy_ident { @@ -252,7 +252,7 @@ fn push_proxy( push: &mut FnMut(Annotatable)) { push_proxy_struct(cx, builder, item, push); - push_proxy_implementation(cx, builder, dispatches, push); + push_proxy_implementation(cx, builder, dispatches, item, push); } fn implement_proxy_method_body( @@ -421,6 +421,7 @@ fn push_proxy_implementation( cx: &ExtCtxt, builder: &aster::AstBuilder, dispatches: &[Dispatch], + item: &Item, push: &mut FnMut(Annotatable)) { let mut index = -1i32; @@ -428,10 +429,11 @@ fn push_proxy_implementation( .map(|dispatch| { index = index + 1; P(implement_proxy_method(cx, builder, index as u16, dispatch)) }) .collect::>>(); + let client_ident = builder.id(format!("{}Client", item.ident.name.as_str())); let implement = quote_item!(cx, - impl ServiceProxy where S: ::ipc::IpcSocket { - pub fn new(socket: S) -> ServiceProxy { - ServiceProxy { + impl $client_ident where S: ::ipc::IpcSocket { + pub fn new(socket: S) -> $client_ident { + $client_ident { socket: ::std::cell::RefCell::new(socket), phantom: ::std::marker::PhantomData, } From 0291b9a1c373799c9656797f584d81d97ca14640 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 18:19:03 +0300 Subject: [PATCH 12/17] fixed tests --- ipc/tests/examples.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 2f50f13db..52ac0cf22 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -38,11 +38,11 @@ mod tests { fn call_service_proxy() { let mut socket = TestSocket::new(); socket.read_buffer = vec![0, 0, 0, 10]; - let service_proxy = ServiceProxy::new(socket); + let service_client = ServiceClient::new(socket); - let result = service_proxy.commit(5); + let result = service_client.commit(5); - assert_eq!(vec![0, 0, 0, 0, 0, 5], service_proxy.socket().borrow().write_buffer.clone()); + assert_eq!(vec![0, 0, 0, 0, 0, 5], service_client.socket().borrow().write_buffer.clone()); assert_eq!(10, result); } @@ -50,11 +50,11 @@ mod tests { fn call_service_proxy_optional() { let mut socket = TestSocket::new(); socket.read_buffer = vec![0, 0, 0, 10]; - let service_proxy = ServiceProxy::new(socket); + let service_client = ServiceClient::new(socket); - let result = service_proxy.rollback(Some(5), 10); + let result = service_client.rollback(Some(5), 10); - assert_eq!(vec![0, 1, 1, 0, 0, 0, 5, 0, 0, 0, 10], service_proxy.socket().borrow().write_buffer.clone()); + assert_eq!(vec![0, 1, 1, 0, 0, 0, 5, 0, 0, 0, 10], service_client.socket().borrow().write_buffer.clone()); assert_eq!(10, result); } } From 054fa71b52cd3a197cbb91970204ad96497961e0 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 18:25:31 +0300 Subject: [PATCH 13/17] dried namespaces --- ipc/rpc/src/interface.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index c99cd3e35..8d67deca3 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -16,31 +16,43 @@ //! IPC RPC interface +use std::io::{Read, Write}; +use std::marker::Sync; +use std::sync::atomic::*; + pub trait IpcInterface { /// reads the message from io, dispatches the call and returns result - fn dispatch(&self, r: &mut R) -> Vec where R: ::std::io::Read; + fn dispatch(&self, r: &mut R) -> Vec where R: Read; } -pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: ::std::io::Write { +/// serializes method invocation (method_num and parameters) to the stream specified by `w` +pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: Write { + // creating buffer to contain all message let buf_len = match *params { None => 2, Some(ref val) => val.len() + 2 }; let mut buf = vec![0u8; buf_len]; + + // writing method_num as u16 buf[1] = (method_num & 255) as u8; buf[0] = (method_num >> 8) as u8; + + // serializing parameters only if provided with any if params.is_some() { buf[2..buf_len].clone_from_slice(params.as_ref().unwrap()); } if w.write(&buf).unwrap() != buf_len { + // if write was inconsistent panic!("failed to write to socket"); } } -pub trait IpcSocket: ::std::io::Read + ::std::io::Write { - fn ready(&self) -> ::std::sync::atomic::AtomicBool; +/// IpcSocket +pub trait IpcSocket: Read + Write + Sync { + fn ready(&self) -> AtomicBool; } impl IpcSocket for ::devtools::TestSocket { - fn ready(&self) -> ::std::sync::atomic::AtomicBool { - ::std::sync::atomic::AtomicBool::new(true) + fn ready(&self) -> AtomicBool { + AtomicBool::new(true) } } From ba302343975be14b9e110af124945cb727feee83 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 18:27:31 +0300 Subject: [PATCH 14/17] codegen proxy->client --- ipc/codegen/src/codegen.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 571dc60bc..6907b735e 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -58,7 +58,7 @@ pub fn expand_ipc_implementation( Err(Error) => { return; } }; - push_proxy(cx, &builder, &item, &dispatches, push); + push_client(cx, &builder, &item, &dispatches, push); push(Annotatable::Item(impl_item)) } @@ -232,7 +232,7 @@ fn implement_dispatch_arm(cx: &ExtCtxt, builder: &aster::AstBuilder, index: u32, quote_arm!(cx, $index_ident => { $invoke_expr } ) } -fn push_proxy_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { +fn push_client_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { let proxy_ident = builder.id(format!("{}Client", item.ident.name.as_str())); let proxy_struct_item = quote_item!(cx, @@ -244,18 +244,18 @@ fn push_proxy_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, pus push(Annotatable::Item(proxy_struct_item.expect(&format!("could not generate proxy struct for {:?}", proxy_ident.name)))); } -fn push_proxy( +fn push_client( cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, dispatches: &[Dispatch], push: &mut FnMut(Annotatable)) { - push_proxy_struct(cx, builder, item, push); - push_proxy_implementation(cx, builder, dispatches, item, push); + push_client_struct(cx, builder, item, push); + push_client_implementation(cx, builder, dispatches, item, push); } -fn implement_proxy_method_body( +fn implement_client_method_body( cx: &ExtCtxt, builder: &aster::AstBuilder, index: u16, @@ -362,7 +362,7 @@ fn implement_proxy_method_body( } } -fn implement_proxy_method( +fn implement_client_method( cx: &ExtCtxt, builder: &aster::AstBuilder, index: u16, @@ -370,7 +370,7 @@ fn implement_proxy_method( -> ast::ImplItem { let method_name = builder.id(dispatch.function_name.as_str()); - let body = implement_proxy_method_body(cx, builder, index, dispatch); + let body = implement_client_method_body(cx, builder, index, dispatch); let ext_cx = &*cx; // expanded version of this @@ -417,7 +417,7 @@ fn implement_proxy_method( signature.unwrap() } -fn push_proxy_implementation( +fn push_client_implementation( cx: &ExtCtxt, builder: &aster::AstBuilder, dispatches: &[Dispatch], @@ -426,7 +426,7 @@ fn push_proxy_implementation( { let mut index = -1i32; let items = dispatches.iter() - .map(|dispatch| { index = index + 1; P(implement_proxy_method(cx, builder, index as u16, dispatch)) }) + .map(|dispatch| { index = index + 1; P(implement_client_method(cx, builder, index as u16, dispatch)) }) .collect::>>(); let client_ident = builder.id(format!("{}Client", item.ident.name.as_str())); From 3bbfcefb0b38bc8dc072412128b4cb7c0ae57869 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 19:20:39 +0300 Subject: [PATCH 15/17] client method generation documented --- ipc/codegen/src/codegen.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 6907b735e..2e0bab27b 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -255,6 +255,35 @@ fn push_client( push_client_implementation(cx, builder, dispatches, item, push); } +/// returns an expression with the method for single operation with the signature identical to server +/// method and which is basically implements invoke of the remote rpc method, waiting for return (if any +/// expected) and returning deserialized output +/// +/// assuming expanded class contains method +/// fn commit(&self, f: u32) -> u32 +/// +/// the expanded implementation will generate method for the client like that +/// +/// pub fn commit(&self, f: u32) -> u32 { +/// { +/// #[derive(Serialize)] +/// struct Request<'a> { +/// f: &'a u32, +/// } +/// let payload = Request{f: &f,}; +/// let mut socket_ref = self.socket.borrow_mut(); +/// let mut socket = socket_ref.deref_mut(); +/// let serialized_payload = +/// ::bincode::serde::serialize(&payload, +/// ::bincode::SizeLimit::Infinite).unwrap(); +/// ::ipc::invoke(0, &Some(serialized_payload), &mut socket); +/// while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) +/// { +/// } +/// ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() +/// } +/// } +/// fn implement_client_method_body( cx: &ExtCtxt, builder: &aster::AstBuilder, From 92feabf3e7eed413aec313a74da7ba7712f61b9e Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 19:27:39 +0300 Subject: [PATCH 16/17] fixed sig/body --- ipc/codegen/src/codegen.rs | 43 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 2e0bab27b..705a1f641 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -224,6 +224,7 @@ fn implement_dispatch_arm_invoke( }) } +/// generates dispatch match for method id fn implement_dispatch_arm(cx: &ExtCtxt, builder: &aster::AstBuilder, index: u32, dispatch: &Dispatch) -> ast::Arm { @@ -232,6 +233,8 @@ fn implement_dispatch_arm(cx: &ExtCtxt, builder: &aster::AstBuilder, index: u32, quote_arm!(cx, $index_ident => { $invoke_expr } ) } +/// generates client type for specified server type +/// for say `Service` it generates `ServiceClient` fn push_client_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push: &mut FnMut(Annotatable)) { let proxy_ident = builder.id(format!("{}Client", item.ident.name.as_str())); @@ -244,6 +247,7 @@ fn push_client_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, pu push(Annotatable::Item(proxy_struct_item.expect(&format!("could not generate proxy struct for {:?}", proxy_ident.name)))); } +/// pushes generated code for the client class (type declaration and method invocation implementations) fn push_client( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -255,35 +259,26 @@ fn push_client( push_client_implementation(cx, builder, dispatches, item, push); } -/// returns an expression with the method for single operation with the signature identical to server -/// method and which is basically implements invoke of the remote rpc method, waiting for return (if any -/// expected) and returning deserialized output +/// returns an expression with the body for single operation that is being sent to server +/// operation itself serializes input, writes to socket and waits for socket to respond +/// (the latter only if original method signature returns anyting) /// /// assuming expanded class contains method /// fn commit(&self, f: u32) -> u32 /// /// the expanded implementation will generate method for the client like that -/// -/// pub fn commit(&self, f: u32) -> u32 { -/// { -/// #[derive(Serialize)] -/// struct Request<'a> { -/// f: &'a u32, -/// } -/// let payload = Request{f: &f,}; -/// let mut socket_ref = self.socket.borrow_mut(); -/// let mut socket = socket_ref.deref_mut(); -/// let serialized_payload = -/// ::bincode::serde::serialize(&payload, -/// ::bincode::SizeLimit::Infinite).unwrap(); -/// ::ipc::invoke(0, &Some(serialized_payload), &mut socket); -/// while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) -/// { -/// } -/// ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() -/// } +/// #[derive(Serialize)] +/// struct Request<'a> { +/// f: &'a u32, /// } -/// +/// let payload = Request{f: &f,}; +/// let mut socket_ref = self.socket.borrow_mut(); +/// let mut socket = socket_ref.deref_mut(); +/// let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); +/// ::ipc::invoke(0, &Some(serialized_payload), &mut socket); +/// while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } +/// ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() + fn implement_client_method_body( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -391,6 +386,8 @@ fn implement_client_method_body( } } +/// +/// Generates signature and fn implement_client_method( cx: &ExtCtxt, builder: &aster::AstBuilder, From 97fbc11a8fbd25e79ae4a71a4b81efc93d7b481a Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 30 Mar 2016 19:31:09 +0300 Subject: [PATCH 17/17] more doc effort --- ipc/codegen/src/codegen.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 705a1f641..166ae87bd 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -278,7 +278,6 @@ fn push_client( /// ::ipc::invoke(0, &Some(serialized_payload), &mut socket); /// while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } /// ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() - fn implement_client_method_body( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -386,8 +385,8 @@ fn implement_client_method_body( } } -/// -/// Generates signature and +/// Generates signature and body (see `implement_client_method_body`) +/// for the client (signature is identical to the original method) fn implement_client_method( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -443,6 +442,7 @@ fn implement_client_method( signature.unwrap() } +/// pushes full client side code for the original class exposed via ipc fn push_client_implementation( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -476,6 +476,7 @@ fn push_client_implementation( push(Annotatable::Item(implement)); } +/// implements `IpcInterface` for the given class `C` fn implement_interface( cx: &ExtCtxt, builder: &aster::AstBuilder,