Inital commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"tonic",
|
||||||
|
"tonic-macros"
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
nightly-2019-08-09
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "tonic-macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Lucio Franco <[email protected]>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tonic = { path = "../tonic" }
|
||||||
|
syn = { version = "0.15", features = ["full"] }
|
||||||
|
quote = "0.6"
|
||||||
|
proc-macro2 = "0.4"
|
||||||
|
prost-build = "0.5"
|
||||||
|
tower-service = { git = "https://github.com/tower-rs/tower", branch = "std-future" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = "=0.2.0-alpha.1"
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use prost_build::{Comments, Method, Service};
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{ImplItem, ImplItemMethod, ItemImpl, Type};
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn grpc(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let service = load_service(attr);
|
||||||
|
let mut original = item.clone();
|
||||||
|
let ItemImpl { self_ty, items, .. } = syn::parse_macro_input!(item as ItemImpl);
|
||||||
|
|
||||||
|
let s = if let Type::Path(t) = *self_ty {
|
||||||
|
t.path.segments.iter().next().unwrap().clone()
|
||||||
|
} else {
|
||||||
|
panic!("wrong type!")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut m_ident = None;
|
||||||
|
for item in items {
|
||||||
|
if let ImplItem::Method(method) = item {
|
||||||
|
// println!("{:?}", method);
|
||||||
|
|
||||||
|
let ImplItemMethod { sig, .. } = method;
|
||||||
|
|
||||||
|
if sig.asyncness.is_some() {
|
||||||
|
let name = format!("{}", sig.ident);
|
||||||
|
|
||||||
|
if let Some(_method) = service.methods.iter().find(|method| method.name == name) {
|
||||||
|
// println!("found method!");
|
||||||
|
m_ident = Some(sig.ident.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let ts = quote! {
|
||||||
|
// impl<'a> tower_service::Service<tonic::Request<()>> for #s {
|
||||||
|
// type Response = tonic::Response<()>;
|
||||||
|
// type Error = tonic::Status;
|
||||||
|
// type Future = tonic::ResponseFuture<'a, Self::Response, Self::Error>;
|
||||||
|
|
||||||
|
// fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
|
||||||
|
// std::task::Poll::Ready(Ok(()))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn call(&mut self, request: tonic::Request<()>) -> Self::Future {
|
||||||
|
// Box::pin(self.#m_ident(request))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
let ts = quote! {
|
||||||
|
impl tonic::GrpcInnerService<tonic::Request<()>> for #s {
|
||||||
|
type Response = tonic::Response<()>;
|
||||||
|
|
||||||
|
fn call<'a>(&'a mut self, request: tonic::Request<()>) -> tonic::ResponseFuture<'a, Self::Response>
|
||||||
|
where Self: 'a {
|
||||||
|
Box::pin(self.#m_ident(request))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
original.extend(TokenStream::from(ts));
|
||||||
|
original
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_service(_attr: TokenStream) -> Service {
|
||||||
|
Service {
|
||||||
|
name: "Greeter".into(),
|
||||||
|
proto_name: "greeter".into(),
|
||||||
|
package: "helloworld".into(),
|
||||||
|
comments: Comments {
|
||||||
|
leading_detached: Vec::new(),
|
||||||
|
leading: Vec::new(),
|
||||||
|
trailing: Vec::new(),
|
||||||
|
},
|
||||||
|
methods: vec![Method {
|
||||||
|
name: "say_hello".into(),
|
||||||
|
proto_name: "SayHello".into(),
|
||||||
|
comments: Comments {
|
||||||
|
leading_detached: Vec::new(),
|
||||||
|
leading: Vec::new(),
|
||||||
|
trailing: Vec::new(),
|
||||||
|
},
|
||||||
|
input_type: "HelloRequest".into(),
|
||||||
|
output_type: "HelloResponse".into(),
|
||||||
|
input_proto_type: "HelloRequest".into(),
|
||||||
|
output_proto_type: "HelloResponse".into(),
|
||||||
|
options: Default::default(),
|
||||||
|
client_streaming: false,
|
||||||
|
server_streaming: false,
|
||||||
|
}],
|
||||||
|
options: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
use tonic::{Request, Response, Status};
|
||||||
|
use tonic_macros::grpc;
|
||||||
|
use tokio::timer::Delay;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
|
// struct HelloRequest;
|
||||||
|
// #[derive(Debug)]
|
||||||
|
// struct HelloResponse;
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
struct MyGreeter {
|
||||||
|
data: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[grpc(service = "proto/helloworld.proto")]
|
||||||
|
impl MyGreeter {
|
||||||
|
pub async fn say_hello(&mut self, request: Request<()>) -> Result<Response<()>, Status> {
|
||||||
|
println!("Got a request: {:?}", request);
|
||||||
|
|
||||||
|
let string = &self.data;
|
||||||
|
|
||||||
|
let when = tokio::clock::now() + Duration::from_millis(100);
|
||||||
|
Delay::new(when).await;
|
||||||
|
|
||||||
|
println!("My data: {:?}", string);
|
||||||
|
|
||||||
|
Delay::new(when).await;
|
||||||
|
|
||||||
|
Ok(Response::new(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn grpc() {
|
||||||
|
let mut greeter = MyGreeter { data: "some data".into()};
|
||||||
|
|
||||||
|
use tonic::GrpcInnerService;
|
||||||
|
greeter.call(Request::new(())).await.unwrap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "tonic"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Lucio Franco <[email protected]>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tower-grpc = { git = "https://github.com/tower-rs/tower-grpc", branch = "std-future" }
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
pub use tower_grpc::*;
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
pub type ResponseFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, Status>> + Send + 'a>>;
|
||||||
|
|
||||||
|
pub trait GrpcInnerService<Request> {
|
||||||
|
type Response;
|
||||||
|
|
||||||
|
fn call<'a>(&'a mut self, request: Request) -> ResponseFuture<'a, Self::Response>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user