IPC RPC deriving for traits (#1599)
* sorting out the multi-interface dispatch scenario * codegen expansion for traits * fix rwlock
This commit is contained in:
parent
e0efe577b3
commit
be7c771efd
@ -28,6 +28,7 @@ use syntax::ast::{
|
||||
TraitRef,
|
||||
Ident,
|
||||
Generics,
|
||||
TraitItemKind,
|
||||
};
|
||||
|
||||
use syntax::ast;
|
||||
@ -80,19 +81,23 @@ pub fn replace_slice_u8(builder: &aster::AstBuilder, ty: &P<ast::Ty>) -> P<ast::
|
||||
ty.clone()
|
||||
}
|
||||
|
||||
struct NamedSignature<'a> {
|
||||
sig: &'a MethodSig,
|
||||
ident: &'a Ident,
|
||||
}
|
||||
|
||||
fn push_invoke_signature_aster(
|
||||
builder: &aster::AstBuilder,
|
||||
implement: &ImplItem,
|
||||
signature: &MethodSig,
|
||||
named_signature: &NamedSignature,
|
||||
push: &mut FnMut(Annotatable),
|
||||
) -> Dispatch {
|
||||
let inputs = &signature.decl.inputs;
|
||||
let inputs = &named_signature.sig.decl.inputs;
|
||||
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![], vec![]) }
|
||||
else {
|
||||
let skip = if first_field_name == "self" { 2 } else { 1 };
|
||||
let name_str = format!("{}_input", implement.ident.name.as_str());
|
||||
let name_str = format!("{}_input", named_signature.ident.name.as_str());
|
||||
|
||||
let mut arg_names = Vec::new();
|
||||
let mut arg_tys = Vec::new();
|
||||
@ -126,9 +131,9 @@ fn push_invoke_signature_aster(
|
||||
(None, vec![], vec![])
|
||||
};
|
||||
|
||||
let return_type_ty = match signature.decl.output {
|
||||
let return_type_ty = match named_signature.sig.decl.output {
|
||||
FunctionRetTy::Ty(ref ty) => {
|
||||
let name_str = format!("{}_output", implement.ident.name.as_str());
|
||||
let name_str = format!("{}_output", named_signature.ident.name.as_str());
|
||||
let tree = builder.item()
|
||||
.attr().word("derive(Binary)")
|
||||
.attr().word("allow(non_camel_case_types)")
|
||||
@ -141,7 +146,7 @@ fn push_invoke_signature_aster(
|
||||
};
|
||||
|
||||
Dispatch {
|
||||
function_name: format!("{}", implement.ident.name.as_str()),
|
||||
function_name: format!("{}", named_signature.ident.name.as_str()),
|
||||
input_type_name: input_type_name,
|
||||
input_arg_names: input_arg_names,
|
||||
input_arg_tys: input_arg_tys,
|
||||
@ -587,8 +592,8 @@ fn push_client_implementation(
|
||||
let handshake_item = quote_impl_item!(cx,
|
||||
pub fn handshake(&self) -> Result<(), ::ipc::Error> {
|
||||
let payload = ::ipc::Handshake {
|
||||
protocol_version: Arc::<$endpoint>::protocol_version(),
|
||||
api_version: Arc::<$endpoint>::api_version(),
|
||||
protocol_version: ::std::sync::Arc::<$endpoint>::protocol_version(),
|
||||
api_version: ::std::sync::Arc::<$endpoint>::api_version(),
|
||||
};
|
||||
|
||||
::ipc::invoke(
|
||||
@ -771,8 +776,43 @@ fn implement_interface(
|
||||
item: &Item,
|
||||
push: &mut FnMut(Annotatable),
|
||||
) -> Result<InterfaceMap, Error> {
|
||||
let (generics, impl_trait, original_ty, impl_items) = match item.node {
|
||||
ast::ItemKind::Impl(_, _, ref generics, ref impl_trait, ref ty, ref impl_items) => (generics, impl_trait, ty, impl_items),
|
||||
let (generics, impl_trait, original_ty, dispatch_table) = match item.node {
|
||||
ast::ItemKind::Impl(_, _, ref generics, ref impl_trait, ref ty, ref impl_items) => {
|
||||
let mut method_signatures = Vec::new();
|
||||
for impl_item in impl_items {
|
||||
if let ImplItemKind::Method(ref signature, _) = impl_item.node {
|
||||
method_signatures.push(NamedSignature { ident: &impl_item.ident, sig: signature });
|
||||
}
|
||||
}
|
||||
|
||||
let dispatch_table = method_signatures.iter().map(|named_signature|
|
||||
push_invoke_signature_aster(builder, named_signature, push))
|
||||
.collect::<Vec<Dispatch>>();
|
||||
|
||||
(generics, impl_trait.clone(), ty.clone(), dispatch_table)
|
||||
},
|
||||
ast::ItemKind::Trait(_, ref generics, _, ref trait_items) => {
|
||||
let mut method_signatures = Vec::new();
|
||||
for trait_item in trait_items {
|
||||
if let TraitItemKind::Method(ref signature, _) = trait_item.node {
|
||||
method_signatures.push(NamedSignature { ident: &trait_item.ident, sig: signature });
|
||||
}
|
||||
}
|
||||
|
||||
let dispatch_table = method_signatures.iter().map(|named_signature|
|
||||
push_invoke_signature_aster(builder, named_signature, push))
|
||||
.collect::<Vec<Dispatch>>();
|
||||
|
||||
(
|
||||
generics,
|
||||
Some(ast::TraitRef {
|
||||
path: builder.path().ids(&[item.ident.name]).build(),
|
||||
ref_id: item.id,
|
||||
}),
|
||||
builder.ty().id(item.ident),
|
||||
dispatch_table
|
||||
)
|
||||
},
|
||||
_ => {
|
||||
cx.span_err(
|
||||
item.span,
|
||||
@ -783,30 +823,19 @@ fn implement_interface(
|
||||
let impl_generics = builder.from_generics(generics.clone()).build();
|
||||
let where_clause = &impl_generics.where_clause;
|
||||
|
||||
let mut method_signatures = Vec::new();
|
||||
for impl_item in impl_items {
|
||||
if let ImplItemKind::Method(ref signature, _) = impl_item.node {
|
||||
method_signatures.push((impl_item, signature))
|
||||
}
|
||||
}
|
||||
|
||||
let dispatch_table = method_signatures.iter().map(|&(impl_item, signature)|
|
||||
push_invoke_signature_aster(builder, impl_item, signature, push))
|
||||
.collect::<Vec<Dispatch>>();
|
||||
|
||||
let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false);
|
||||
let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true);
|
||||
|
||||
let (handshake_arm, handshake_arm_buf) = implement_handshake_arm(cx);
|
||||
|
||||
let ty = ty_ident_map(&original_ty).ident(builder);
|
||||
let interface_endpoint = match *impl_trait {
|
||||
Some(ref trait_) => builder.id(::syntax::print::pprust::path_to_string(&trait_.path)),
|
||||
None => ty
|
||||
let (interface_endpoint, host_generics) = match impl_trait {
|
||||
Some(ref trait_) => (builder.id(::syntax::print::pprust::path_to_string(&trait_.path)), None),
|
||||
None => (ty, Some(&impl_generics)),
|
||||
};
|
||||
|
||||
let ipc_item = quote_item!(cx,
|
||||
impl $impl_generics ::ipc::IpcInterface<$interface_endpoint> for Arc<$interface_endpoint> $where_clause {
|
||||
impl $host_generics ::ipc::IpcInterface<$interface_endpoint> for ::std::sync::Arc<$interface_endpoint> $where_clause {
|
||||
fn dispatch<R>(&self, r: &mut R) -> Vec<u8>
|
||||
where R: ::std::io::Read
|
||||
{
|
||||
|
@ -19,10 +19,11 @@ mod tests {
|
||||
|
||||
use super::super::service::*;
|
||||
use super::super::binary::*;
|
||||
use super::super::nested::{DBClient,DBWriter};
|
||||
use super::super::nested::{DBClient, DBWriter};
|
||||
use ipc::*;
|
||||
use devtools::*;
|
||||
use semver::Version;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
fn call_service() {
|
||||
@ -33,7 +34,7 @@ mod tests {
|
||||
4, 0, 0, 0, 0, 0, 0, 0,
|
||||
10, 0, 0, 0]);
|
||||
|
||||
let service = Service::new();
|
||||
let service = Arc::new(Service::new());
|
||||
assert_eq!(0, *service.commits.read().unwrap());
|
||||
|
||||
service.dispatch(&mut socket);
|
||||
@ -65,7 +66,7 @@ mod tests {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
]);
|
||||
|
||||
let service = Service::new();
|
||||
let service = Arc::new(Service::new());
|
||||
let result = service.dispatch(&mut socket);
|
||||
|
||||
// single `true`
|
||||
@ -109,9 +110,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn query_default_version() {
|
||||
let ver = Service::protocol_version();
|
||||
let ver = Arc::<Service>::protocol_version();
|
||||
assert_eq!(ver, Version::parse("1.0.0").unwrap());
|
||||
let ver = Service::api_version();
|
||||
let ver = Arc::<Service>::api_version();
|
||||
assert_eq!(ver, Version::parse("1.0.0").unwrap());
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ pub trait DBWriter {
|
||||
fn write_slice(&self, data: &[u8]) -> Result<(), DBError>;
|
||||
}
|
||||
|
||||
impl<L: Sized> IpcConfig for DB<L> {}
|
||||
impl IpcConfig<DBWriter> for ::std::sync::Arc<DBWriter> {}
|
||||
|
||||
#[derive(Binary)]
|
||||
pub enum DBError { Write, Read }
|
||||
@ -53,3 +53,9 @@ impl<L: Sized> DBWriter for DB<L> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Ipc)]
|
||||
trait DBNotify {
|
||||
fn notify(&self, a: u64, b: u64) -> bool;
|
||||
}
|
||||
|
||||
impl IpcConfig<DBNotify> for ::std::sync::Arc<DBNotify> { }
|
||||
|
@ -70,4 +70,4 @@ impl Service {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::ipc::IpcConfig for Service {}
|
||||
impl ::ipc::IpcConfig<Service> for ::std::sync::Arc<Service> {}
|
||||
|
@ -31,4 +31,4 @@ impl BadlyNamedService {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::ipc::IpcConfig for BadlyNamedService {}
|
||||
impl ::ipc::IpcConfig<BadlyNamedService> for ::std::sync::Arc<BadlyNamedService> {}
|
||||
|
Loading…
Reference in New Issue
Block a user