chore(build): Refactor codegen traits (#302)

Signed-off-by: Lucio Franco <[email protected]>
This commit is contained in:
Lucio Franco
2020-03-29 12:57:11 -04:00
committed by GitHub
parent 012fa3cb4a
commit 2e082f8b3e
13 changed files with 113 additions and 144 deletions
+32 -38
View File
@@ -5,32 +5,20 @@ use quote::ToTokens;
use std::io;
use std::path::{Path, PathBuf};
impl<'a> schema::Commentable<'a> for Service {
const PROST_CODEC_PATH: &'static str = "tonic::codec::ProstCodec";
impl schema::Commentable for Service {
type Comment = String;
type CommentContainer = &'a Vec<Self::Comment>;
fn comment(&'a self) -> Self::CommentContainer {
&self.comments.leading
fn comment(&self) -> &[Self::Comment] {
&self.comments.leading[..]
}
}
/// Context data used while generate prost service
#[derive(Debug)]
pub struct ProstContext {
/// relative path to proto definitions from service definitions
pub proto_path: String,
}
impl schema::Service for Service {
const CODEC_PATH: &'static str = PROST_CODEC_PATH;
impl schema::Context for ProstContext {
fn codec_name(&self) -> &str {
"tonic::codec::ProstCodec"
}
}
impl<'a> schema::Service<'a> for Service {
type Method = Method;
type MethodContainer = &'a Vec<Self::Method>;
type Context = ProstContext;
fn name(&self) -> &str {
&self.name
@@ -44,22 +32,21 @@ impl<'a> schema::Service<'a> for Service {
&self.proto_name
}
fn methods(&'a self) -> Self::MethodContainer {
&self.methods
fn methods(&self) -> &[Self::Method] {
&self.methods[..]
}
}
impl<'a> schema::Commentable<'a> for Method {
impl schema::Commentable for Method {
type Comment = String;
type CommentContainer = &'a Vec<Self::Comment>;
fn comment(&'a self) -> Self::CommentContainer {
&self.comments.leading
fn comment(&self) -> &[Self::Comment] {
&self.comments.leading[..]
}
}
impl<'a> schema::Method<'a> for Method {
type Context = ProstContext;
impl schema::Method for Method {
const CODEC_PATH: &'static str = PROST_CODEC_PATH;
fn name(&self) -> &str {
&self.name
@@ -77,13 +64,13 @@ impl<'a> schema::Method<'a> for Method {
self.server_streaming
}
fn request_response_name(&self, context: &Self::Context) -> (TokenStream, TokenStream) {
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("::")
{
self.input_type.parse::<TokenStream>().unwrap()
} else {
syn::parse_str::<syn::Path>(&format!("{}::{}", context.proto_path, self.input_type))
syn::parse_str::<syn::Path>(&format!("{}::{}", proto_path, self.input_type))
.unwrap()
.to_token_stream()
};
@@ -93,7 +80,7 @@ impl<'a> schema::Method<'a> for Method {
{
self.output_type.parse::<TokenStream>().unwrap()
} else {
syn::parse_str::<syn::Path>(&format!("{}::{}", context.proto_path, self.output_type))
syn::parse_str::<syn::Path>(&format!("{}::{}", proto_path, self.output_type))
.unwrap()
.to_token_stream()
};
@@ -145,17 +132,13 @@ impl ServiceGenerator {
impl prost_build::ServiceGenerator for ServiceGenerator {
fn generate(&mut self, service: prost_build::Service, _buf: &mut String) {
let context = ProstContext {
proto_path: String::from("super"),
};
if self.builder.build_server {
let server = server::generate(&service, &context);
let server = server::generate(&service, &self.builder.proto_path);
self.servers.extend(server);
}
if self.builder.build_client {
let client = client::generate(&service, &context);
let client = client::generate(&service, &self.builder.proto_path);
self.clients.extend(client);
}
}
@@ -197,6 +180,7 @@ pub struct Builder {
pub(crate) extern_path: Vec<(String, String)>,
pub(crate) field_attributes: Vec<(String, String)>,
pub(crate) type_attributes: Vec<(String, String)>,
pub(crate) proto_path: String,
out_dir: Option<PathBuf>,
#[cfg(feature = "rustfmt")]
@@ -262,6 +246,15 @@ impl Builder {
self
}
/// Set the path to where tonic will search for the Request/Response proto structs
/// live relative to the module where you call `include_proto!`.
///
/// This defaults to `super` since tonic will generate code in a module.
pub fn proto_path(mut self, proto_path: impl AsRef<str>) -> Self {
self.proto_path = proto_path.as_ref().to_string();
self
}
/// Compile the .proto files and execute code generation.
pub fn compile<P: AsRef<Path>>(self, protos: &[P], includes: &[P]) -> io::Result<()> {
let out_dir = if let Some(out_dir) = self.out_dir.as_ref() {
@@ -297,6 +290,7 @@ pub fn configure() -> Builder {
extern_path: Vec::new(),
field_attributes: Vec::new(),
type_attributes: Vec::new(),
proto_path: "super".to_string(),
#[cfg(feature = "rustfmt")]
format: true,
}
@@ -306,8 +300,8 @@ pub fn configure() -> Builder {
///
/// The include directory will be the parent folder of the specified path.
/// The package name will be the filename without the extension.
pub fn compile_protos(proto_path: impl AsRef<Path>) -> io::Result<()> {
let proto_path: &Path = proto_path.as_ref();
pub fn compile_protos(proto: impl AsRef<Path>) -> io::Result<()> {
let proto_path: &Path = proto.as_ref();
// directory the main .proto file resides in
let proto_dir = proto_path