diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index f56e00430..a2fa0ee49 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -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) -> P { + 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 { - 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::>(); + + (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::>(); + + ( + 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::>(); - 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(&self, r: &mut R) -> Vec where R: ::std::io::Read { diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 8b52be11c..7afcd583d 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -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::::protocol_version(); assert_eq!(ver, Version::parse("1.0.0").unwrap()); - let ver = Service::api_version(); + let ver = Arc::::api_version(); assert_eq!(ver, Version::parse("1.0.0").unwrap()); } diff --git a/ipc/tests/nested.rs.in b/ipc/tests/nested.rs.in index 26f344d92..c249799f2 100644 --- a/ipc/tests/nested.rs.in +++ b/ipc/tests/nested.rs.in @@ -33,7 +33,7 @@ pub trait DBWriter { fn write_slice(&self, data: &[u8]) -> Result<(), DBError>; } -impl IpcConfig for DB {} +impl IpcConfig for ::std::sync::Arc {} #[derive(Binary)] pub enum DBError { Write, Read } @@ -53,3 +53,9 @@ impl DBWriter for DB { } } +#[derive(Ipc)] +trait DBNotify { + fn notify(&self, a: u64, b: u64) -> bool; +} + +impl IpcConfig for ::std::sync::Arc { } diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 6bee63133..1e3d235e5 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -70,4 +70,4 @@ impl Service { } } -impl ::ipc::IpcConfig for Service {} +impl ::ipc::IpcConfig for ::std::sync::Arc {} diff --git a/ipc/tests/with_attrs.rs.in b/ipc/tests/with_attrs.rs.in index 0168f3a72..8458667ef 100644 --- a/ipc/tests/with_attrs.rs.in +++ b/ipc/tests/with_attrs.rs.in @@ -31,4 +31,4 @@ impl BadlyNamedService { } } -impl ::ipc::IpcConfig for BadlyNamedService {} +impl ::ipc::IpcConfig for ::std::sync::Arc {}