From 5278a0dec54e5bfb4a2a5f1dff280bc95b7e4322 Mon Sep 17 00:00:00 2001 From: roblabla Date: Tue, 22 Sep 2020 15:28:44 +0000 Subject: [PATCH 1/4] Change Method::CODEC_PATH to be a method instead. This allows the underlying codec to be configured by a build script, useful when using a codec wrapper. --- tonic-build/src/client.rs | 20 ++++++++++---------- tonic-build/src/lib.rs | 9 ++++----- tonic-build/src/prost.rs | 10 ++++++++-- tonic-build/src/server.rs | 8 ++++---- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/tonic-build/src/client.rs b/tonic-build/src/client.rs index db8eaa32c..e4d108a48 100644 --- a/tonic-build/src/client.rs +++ b/tonic-build/src/client.rs @@ -119,7 +119,7 @@ fn generate_methods(service: &T, proto_path: &str) -> TokenStream { } fn generate_unary(method: &T, proto_path: &str, path: String) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let ident = format_ident!("{}", method.name()); let (request, response) = method.request_response_name(proto_path); @@ -132,14 +132,14 @@ fn generate_unary(method: &T, proto_path: &str, path: String) -> Toke tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())) })?; let codec = #codec_name::default(); - let path = http::uri::PathAndQuery::from_static(#path); - self.inner.unary(request.into_request(), path, codec).await + let path = http::uri::PathAndQuery::from_static(#path); + self.inner.unary(request.into_request(), path, codec).await } } } fn generate_server_streaming(method: &T, proto_path: &str, path: String) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let ident = format_ident!("{}", method.name()); let (request, response) = method.request_response_name(proto_path); @@ -153,14 +153,14 @@ fn generate_server_streaming(method: &T, proto_path: &str, path: Stri tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())) })?; let codec = #codec_name::default(); - let path = http::uri::PathAndQuery::from_static(#path); - self.inner.server_streaming(request.into_request(), path, codec).await + let path = http::uri::PathAndQuery::from_static(#path); + self.inner.server_streaming(request.into_request(), path, codec).await } } } fn generate_client_streaming(method: &T, proto_path: &str, path: String) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let ident = format_ident!("{}", method.name()); let (request, response) = method.request_response_name(proto_path); @@ -181,7 +181,7 @@ fn generate_client_streaming(method: &T, proto_path: &str, path: Stri } fn generate_streaming(method: &T, proto_path: &str, path: String) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let ident = format_ident!("{}", method.name()); let (request, response) = method.request_response_name(proto_path); @@ -195,8 +195,8 @@ fn generate_streaming(method: &T, proto_path: &str, path: String) -> tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())) })?; let codec = #codec_name::default(); - let path = http::uri::PathAndQuery::from_static(#path); - self.inner.streaming(request.into_streaming_request(), path, codec).await + let path = http::uri::PathAndQuery::from_static(#path); + self.inner.streaming(request.into_streaming_request(), path, codec).await } } } diff --git a/tonic-build/src/lib.rs b/tonic-build/src/lib.rs index 8b9b0af9b..cb8338491 100644 --- a/tonic-build/src/lib.rs +++ b/tonic-build/src/lib.rs @@ -103,15 +103,14 @@ pub mod server; /// to allow any codegen module to generate service /// abstractions. pub trait Service { - /// Path to the codec. - const CODEC_PATH: &'static str; - /// Comment type. type Comment: AsRef; /// Method type. type Method: Method; + /// Path to the codec. + fn codec_path(&self) -> &str; /// Name of service. fn name(&self) -> &str; /// Package name of service. @@ -131,11 +130,11 @@ pub trait Service { /// to generate abstraction implementations for /// the provided methods. pub trait Method { - /// Path to the codec. - const CODEC_PATH: &'static str; /// Comment type. type Comment: AsRef; + /// Path to the codec. + fn codec_path(&self) -> &str; /// Name of method. fn name(&self) -> &str; /// Identifier used to generate type name. diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index 1351bdbc9..339278c5d 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -42,11 +42,14 @@ pub fn compile_protos(proto: impl AsRef) -> io::Result<()> { const PROST_CODEC_PATH: &'static str = "tonic::codec::ProstCodec"; impl crate::Service for Service { - const CODEC_PATH: &'static str = PROST_CODEC_PATH; type Method = Method; type Comment = String; + fn codec_path(&self) -> &str { + PROST_CODEC_PATH + } + fn name(&self) -> &str { &self.name } @@ -69,9 +72,12 @@ impl crate::Service for Service { } impl crate::Method for Method { - const CODEC_PATH: &'static str = PROST_CODEC_PATH; type Comment = String; + fn codec_path(&self) -> &str { + PROST_CODEC_PATH + } + fn name(&self) -> &str { &self.name } diff --git a/tonic-build/src/server.rs b/tonic-build/src/server.rs index 11dd866bf..7e9be185e 100644 --- a/tonic-build/src/server.rs +++ b/tonic-build/src/server.rs @@ -261,7 +261,7 @@ fn generate_unary( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let service_ident = quote::format_ident!("{}Svc", method.identifier()); @@ -311,7 +311,7 @@ fn generate_server_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let service_ident = quote::format_ident!("{}Svc", method.identifier()); @@ -368,7 +368,7 @@ fn generate_client_streaming( let service_ident = quote::format_ident!("{}Svc", method.identifier()); let (request, response) = method.request_response_name(proto_path); - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); quote! { #[allow(non_camel_case_types)] @@ -416,7 +416,7 @@ fn generate_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(T::CODEC_PATH).unwrap(); + let codec_name = syn::parse_str::(method.codec_path()).unwrap(); let service_ident = quote::format_ident!("{}Svc", method.identifier()); From 86071d2ff47d851cf9584688127bec2bfb05418e Mon Sep 17 00:00:00 2001 From: roblabla Date: Tue, 22 Sep 2020 15:30:25 +0000 Subject: [PATCH 2/4] Allow the prost codec to be configured. --- tonic-build/src/prost.rs | 81 ++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index 339278c5d..c92605833 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -1,6 +1,6 @@ use super::{client, server}; use proc_macro2::TokenStream; -use prost_build::{Config, Method, Service}; +use prost_build::{Config, Method as ProstMethod, Service as ProstService}; use quote::ToTokens; use std::io; use std::path::{Path, PathBuf}; @@ -19,6 +19,7 @@ pub fn configure() -> Builder { proto_path: "super".to_string(), #[cfg(feature = "rustfmt")] format: true, + codec_path: DEFAULT_PROST_CODEC_PATH.to_string(), } } @@ -39,15 +40,39 @@ pub fn compile_protos(proto: impl AsRef) -> io::Result<()> { Ok(()) } -const PROST_CODEC_PATH: &'static str = "tonic::codec::ProstCodec"; +const DEFAULT_PROST_CODEC_PATH: &str = "tonic::codec::ProstCodec"; -impl crate::Service for Service { +struct Service { + name: String, + package: String, + proto_name: String, + comments: Vec, + methods: Vec, + codec_path: String, +} + +impl Service { + fn new(service: ProstService, codec_path: String) -> Service { + Service { + name: service.name, + package: service.package, + proto_name: service.proto_name, + comments: service.comments.leading, + methods: service.methods.into_iter().map(|v| Method { + inner: v, + codec_path: codec_path.clone() + }).collect(), + codec_path: codec_path.clone(), + } + } +} +impl crate::Service for Service { type Method = Method; type Comment = String; fn codec_path(&self) -> &str { - PROST_CODEC_PATH + &self.codec_path } fn name(&self) -> &str { @@ -63,7 +88,7 @@ impl crate::Service for Service { } fn comment(&self) -> &[Self::Comment] { - &self.comments.leading[..] + &self.comments[..] } fn methods(&self) -> &[Self::Method] { @@ -71,50 +96,55 @@ impl crate::Service for Service { } } +struct Method { + inner: ProstMethod, + codec_path: String, +} + impl crate::Method for Method { type Comment = String; fn codec_path(&self) -> &str { - PROST_CODEC_PATH + &self.codec_path } fn name(&self) -> &str { - &self.name + &self.inner.name } fn identifier(&self) -> &str { - &self.proto_name + &self.inner.proto_name } fn client_streaming(&self) -> bool { - self.client_streaming + self.inner.client_streaming } fn server_streaming(&self) -> bool { - self.server_streaming + self.inner.server_streaming } fn comment(&self) -> &[Self::Comment] { - &self.comments.leading[..] + &self.inner.comments.leading[..] } fn request_response_name(&self, proto_path: &str) -> (TokenStream, TokenStream) { - let request = if self.input_proto_type.starts_with(".google.protobuf") - || self.input_type.starts_with("::") + let request = if self.inner.input_proto_type.starts_with(".google.protobuf") + || self.inner.input_type.starts_with("::") { - self.input_type.parse::().unwrap() + self.inner.input_type.parse::().unwrap() } else { - syn::parse_str::(&format!("{}::{}", proto_path, self.input_type)) + syn::parse_str::(&format!("{}::{}", proto_path, self.inner.input_type)) .unwrap() .to_token_stream() }; - let response = if self.output_proto_type.starts_with(".google.protobuf") - || self.output_type.starts_with("::") + let response = if self.inner.output_proto_type.starts_with(".google.protobuf") + || self.inner.output_type.starts_with("::") { - self.output_type.parse::().unwrap() + self.inner.output_type.parse::().unwrap() } else { - syn::parse_str::(&format!("{}::{}", proto_path, self.output_type)) + syn::parse_str::(&format!("{}::{}", proto_path, self.inner.output_type)) .unwrap() .to_token_stream() }; @@ -140,7 +170,8 @@ impl ServiceGenerator { } impl prost_build::ServiceGenerator for ServiceGenerator { - fn generate(&mut self, service: prost_build::Service, _buf: &mut String) { + fn generate(&mut self, service: ProstService, _buf: &mut String) { + let service = Service::new(service, self.builder.codec_path.clone()); if self.builder.build_server { let server = server::generate(&service, &self.builder.proto_path); self.servers.extend(server); @@ -190,6 +221,7 @@ pub struct Builder { pub(crate) field_attributes: Vec<(String, String)>, pub(crate) type_attributes: Vec<(String, String)>, pub(crate) proto_path: String, + pub(crate) codec_path: String, out_dir: Option, #[cfg(feature = "rustfmt")] @@ -264,6 +296,15 @@ impl Builder { self } + /// Set the module path to the `tonic::codec::Codec` implementation to use + /// to serialize/deserialize the protobuf messages. + /// + /// This defaults to `tonic::codec::ProstCodec` + pub fn codec_path(mut self, codec_path: impl AsRef) -> Self { + self.codec_path = codec_path.as_ref().to_string(); + self + } + /// Compile the .proto files and execute code generation. pub fn compile

(self, protos: &[P], includes: &[P]) -> io::Result<()> where From de97a6ce07de5cda2d761519bde0e8b290a7c1de Mon Sep 17 00:00:00 2001 From: roblabla Date: Tue, 22 Sep 2020 16:15:49 +0000 Subject: [PATCH 3/4] Remove useless clone --- tonic-build/src/prost.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index c92605833..5038528fb 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -62,7 +62,7 @@ impl Service { inner: v, codec_path: codec_path.clone() }).collect(), - codec_path: codec_path.clone(), + codec_path, } } } From 6a37a865a16767a76c2872cc3feb113aa276ce39 Mon Sep 17 00:00:00 2001 From: roblabla Date: Tue, 22 Sep 2020 16:16:04 +0000 Subject: [PATCH 4/4] Run fmt --- tonic-build/src/prost.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index 5038528fb..b5d4ae253 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -58,10 +58,14 @@ impl Service { package: service.package, proto_name: service.proto_name, comments: service.comments.leading, - methods: service.methods.into_iter().map(|v| Method { - inner: v, - codec_path: codec_path.clone() - }).collect(), + methods: service + .methods + .into_iter() + .map(|v| Method { + inner: v, + codec_path: codec_path.clone(), + }) + .collect(), codec_path, } }