Inital commit

This commit is contained in:
Lucio Franco
2019-08-09 14:01:27 -04:00
commit b827fdd950
8 changed files with 192 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
/target
**/*.rs.bk
Cargo.lock
+5
View File
@@ -0,0 +1,5 @@
[workspace]
members = [
"tonic",
"tonic-macros"
]
+1
View File
@@ -0,0 +1 @@
nightly-2019-08-09
+19
View File
@@ -0,0 +1,19 @@
[package]
name = "tonic-macros"
version = "0.1.0"
authors = ["Lucio Franco <luciofranco14@gmail.com>"]
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"
+98
View File
@@ -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(),
}
}
+42
View File
@@ -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();
}
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "tonic"
version = "0.1.0"
authors = ["Lucio Franco <luciofranco14@gmail.com>"]
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" }
+14
View File
@@ -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;
}