Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: Add IntoRequest and IntoStreamingRequest traits #66

Merged
merged 32 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d6dd4ed
small tweaks, typos
alce Sep 25, 2019
dc7daca
Merge branch 'master' of github.com:LucioFranco/tonic
alce Sep 25, 2019
96c9519
Merge branch 'master' of github.com:alce/tonic
alce Sep 30, 2019
d11d7b6
pin all alpha dependencies
alce Oct 1, 2019
cb84a13
Merge branch 'master' of github.com:LucioFranco/tonic
alce Oct 1, 2019
481c3a9
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 2, 2019
0ad4de1
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 2, 2019
30142bd
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 2, 2019
8313341
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 8, 2019
78e58bf
Merge branch 'master' of github.com:alce/tonic
alce Oct 9, 2019
0bbd595
Merge branch 'master' of https://github.com/hyperium/tonic
alce Oct 10, 2019
2d86038
add IntoRequest and IntoStreamingRequest traits
alce Oct 10, 2019
8a5096b
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 10, 2019
58d4238
RequestMessage marker trait. generate more compact code
alce Oct 10, 2019
bfa3e9b
improve naming
alce Oct 12, 2019
d23ec04
fmt
alce Oct 12, 2019
405b5e3
fix interop crate
alce Oct 15, 2019
d40ac7e
hide RequestMessage trait from docs
alce Oct 15, 2019
1acf426
use impl Trait instead of type parameter
alce Oct 18, 2019
0e9fe70
remove RequestMessage trait
alce Oct 18, 2019
3f6ff67
Merge branch 'master' of github.com:hyperium/tonic
alce Oct 19, 2019
0e52d8e
Merge branch 'master' into intorequest
alce Oct 19, 2019
03d7a16
conflicts
alce Oct 19, 2019
4439002
Merge branch 'intorequest' of github.com:alce/tonic into intorequest
alce Oct 19, 2019
878120c
document IntoRequest
alce Oct 19, 2019
2f93f33
document IntoStreamingRequest
alce Oct 22, 2019
0528352
Merge branch 'master' into intorequest
alce Oct 23, 2019
adbbe8c
remove IntoRequest in favor of From impl
alce Oct 24, 2019
b32b4e9
Merge branch 'intorequest' of github.com:alce/tonic into intorequest
alce Oct 24, 2019
9a9ee93
seal IntoStreamingRequest
alce Oct 24, 2019
8802192
remove From<T> for Request, implement IntoRequest instead
alce Oct 29, 2019
7017f97
improve docs
alce Oct 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions tonic-build/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,14 @@ fn generate_unary(method: &Method, proto: &str, path: String) -> TokenStream {
let (request, response) = crate::replace_wellknown(proto, &method);

quote! {
pub async fn #ident(&mut self, request: tonic::Request<#request>)
-> Result<tonic::Response<#response>, tonic::Status> {
pub async fn #ident(
&mut self,
request: impl tonic::IntoRequest<Message = #request>,
) -> Result<tonic::Response<#response>, tonic::Status> {
self.ready().await?;
let codec = tonic::codec::ProstCodec::new();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.unary(request, path, codec).await
self.inner.unary(request.into_request(), path, codec).await
}
}
}
Expand All @@ -115,12 +117,14 @@ fn generate_server_streaming(method: &Method, proto: &str, path: String) -> Toke
let (request, response) = crate::replace_wellknown(proto, &method);

quote! {
pub async fn #ident(&mut self, request: tonic::Request<#request>)
-> Result<tonic::Response<tonic::codec::Streaming<#response>>, tonic::Status> {
pub async fn #ident(
&mut self,
request: impl tonic::IntoRequest<Message = #request>,
) -> Result<tonic::Response<tonic::codec::Streaming<#response>>, tonic::Status> {
self.ready().await?;
let codec = tonic::codec::ProstCodec::new();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.server_streaming(request, path, codec).await
self.inner.server_streaming(request.into_request(), path, codec).await
}
}
}
Expand All @@ -131,14 +135,14 @@ fn generate_client_streaming(method: &Method, proto: &str, path: String) -> Toke
let (request, response) = crate::replace_wellknown(proto, &method);

quote! {
pub async fn #ident<S>(&mut self, request: tonic::Request<S>)
-> Result<tonic::Response<#response>, tonic::Status>
where S: Stream<Item = #request> + Send + 'static,
{
pub async fn #ident(
&mut self,
request: impl tonic::IntoStreamingRequest<Message = #request>
) -> Result<tonic::Response<#response>, tonic::Status> {
self.ready().await?;
let codec = tonic::codec::ProstCodec::new();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.client_streaming(request, path, codec).await
self.inner.client_streaming(request.into_streaming_request(), path, codec).await
}
}
}
Expand All @@ -149,14 +153,14 @@ fn generate_streaming(method: &Method, proto: &str, path: String) -> TokenStream
let (request, response) = crate::replace_wellknown(proto, &method);

quote! {
pub async fn #ident<S>(&mut self, request: tonic::Request<S>)
-> Result<tonic::Response<tonic::codec::Streaming<#response>>, tonic::Status>
where S: Stream<Item = #request> + Send + 'static,
{
pub async fn #ident(
&mut self,
request: impl tonic::IntoStreamingRequest<Message = #request>
) -> Result<tonic::Response<tonic::codec::Streaming<#response>>, tonic::Status> {
self.ready().await?;
let codec = tonic::codec::ProstCodec::new();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.streaming(request, path, codec).await
self.inner.streaming(request.into_streaming_request(), path, codec).await
}
}
}
49 changes: 49 additions & 0 deletions tonic-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ use quote::{ToTokens, TokenStreamExt};
#[cfg(feature = "rustfmt")]
use std::process::Command;
use std::{
collections::HashSet,
io,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -219,6 +220,8 @@ struct ServiceGenerator {
builder: Builder,
clients: TokenStream,
servers: TokenStream,
seen_input_types: HashSet<String>,
into_request_impls: TokenStream,
}

impl ServiceGenerator {
Expand All @@ -227,6 +230,8 @@ impl ServiceGenerator {
builder,
clients: TokenStream::default(),
servers: TokenStream::default(),
seen_input_types: HashSet::new(),
into_request_impls: TokenStream::default(),
}
}
}
Expand All @@ -243,14 +248,19 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
if self.builder.build_client {
let client = client::generate(&service, path);
self.clients.extend(client);

let tokens = generate_into_request_impls(&service, &mut self.seen_input_types);
self.into_request_impls.extend(tokens);
}
}

fn finalize(&mut self, buf: &mut String) {
if self.builder.build_client && !self.clients.is_empty() {
let clients = &self.clients;
let trait_impls = &self.into_request_impls;

let client_service = quote::quote! {
#trait_impls
/// Generated client implementations.
pub mod client {
#![allow(unused_variables, dead_code, missing_docs)]
Expand Down Expand Up @@ -329,3 +339,42 @@ fn replace_wellknown(proto_path: &str, method: &Method) -> (TokenStream, TokenSt

(request, response)
}

fn generate_into_request_impls(
service: &prost_build::Service,
seen_input_types: &mut HashSet<String>,
) -> TokenStream {
let service_input_types = service
.methods
.iter()
.fold(HashSet::new(), |mut set, method| {
set.insert(method.input_type.clone());
set
});

let token_stream = service_input_types.difference(seen_input_types).fold(
TokenStream::new(),
|mut stream, input| {
let request: syn::Type = syn::parse_str(&input).unwrap();

let trait_impl = quote::quote! {
impl tonic::IntoRequest for #request {
type Message = Self;

fn into_request(self) -> tonic::Request<Self> {
tonic::Request::new(self)
}
}
};

stream.extend(trait_impl);
stream
},
);

for input in service_input_types {
seen_input_types.insert(input.to_owned());
}

token_stream
}
4 changes: 2 additions & 2 deletions tonic-examples/src/helloworld/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use hello_world::{client::GreeterClient, HelloRequest};
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = GreeterClient::connect("http://[::1]:50051")?;

let request = tonic::Request::new(HelloRequest {
let request = HelloRequest {
name: "hello".into(),
});
};

let response = client.say_hello(request).await?;

Expand Down
9 changes: 3 additions & 6 deletions tonic-examples/src/routeguide/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use futures::TryStreamExt;
use route_guide::{Point, RouteNote};
use std::time::{Duration, Instant};
use tokio::timer::Interval;
use tonic::Request;

pub mod route_guide {
tonic::include_proto!("routeguide");
Expand All @@ -17,10 +16,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let start = Instant::now();

let response = client
.get_feature(Request::new(Point {
.get_feature(Point {
latitude: 409146138,
longitude: -746188906,
}))
})
.await?;

println!("FEATURE = {:?}", response);
Expand All @@ -42,9 +41,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
};

let request = Request::new(outbound);

let response = client.route_chat(request).await?;
let response = client.route_chat(outbound).await?;

let mut inbound = response.into_inner();

Expand Down
2 changes: 1 addition & 1 deletion tonic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub use async_trait::async_trait;

#[doc(inline)]
pub use codec::Streaming;
pub use request::Request;
pub use request::{IntoRequest, IntoStreamingRequest, Request};
pub use response::Response;
pub use status::{Code, Status};

Expand Down
48 changes: 48 additions & 0 deletions tonic/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::metadata::MetadataMap;
use futures_core::Stream;

/// A gRPC request and metadata from an RPC call.
#[derive(Debug)]
Expand All @@ -7,6 +8,21 @@ pub struct Request<T> {
message: T,
}

/// A trait that is implemented for all RPC request request types.
pub trait IntoRequest {
type Message;

fn into_request(self) -> Request<Self::Message>;
}

#[doc(hidden)]
pub trait IntoStreamingRequest {
type Stream: Stream<Item = Self::Message> + Send + 'static;
type Message;

fn into_streaming_request(self) -> Request<Self::Stream>;
}

impl<T> Request<T> {
/// Create a new gRPC request.
///
Expand Down Expand Up @@ -88,3 +104,35 @@ impl<T> Request<T> {
}
}
}

impl<T> IntoRequest for Request<T> {
type Message = T;

fn into_request(self) -> Request<T> {
self
}
}

impl<T> IntoStreamingRequest for Request<T>
where
T: Stream + Send + 'static,
{
type Stream = T;
type Message = T::Item;

fn into_streaming_request(self) -> Self {
self
}
}

impl<T> IntoStreamingRequest for T
where
T: Stream + Send + 'static,
{
type Stream = T;
type Message = T::Item;

fn into_streaming_request(self) -> Request<Self> {
Request::new(self)
}
}