Inital pass at route guide

This commit is contained in:
Lucio Franco
2019-08-16 14:46:18 -04:00
parent 28a0b9e286
commit 1630547f97
10 changed files with 331 additions and 114 deletions
-104
View File
@@ -1,104 +0,0 @@
#![feature(async_await, type_alias_impl_trait)]
use futures_util::future;
use std::future::Future;
use std::task::{Context, Poll};
use tokio::net::TcpListener;
use tonic::{
body,
server::{Grpc, UnaryService},
Request, Response, Status,
};
use tower_h2::{RecvBody, Server};
use tower_service::Service;
#[derive(Clone, PartialEq, prost::Message)]
pub struct HelloRequest {
#[prost(string, tag = "1")]
pub name: std::string::String,
}
/// The response message containing the greetings
#[derive(Clone, PartialEq, prost::Message)]
pub struct HelloReply {
#[prost(string, tag = "1")]
pub message: std::string::String,
}
struct SayHello;
impl UnaryService<HelloRequest> for SayHello {
type Response = HelloReply;
type Future = impl Future<Output = Result<Response<Self::Response>, Status>>;
fn call(&mut self, request: Request<HelloRequest>) -> Self::Future {
async move {
println!("REQUEST = {:?}", request);
let reply = HelloReply {
message: "Zomg, it works!".to_string(),
};
Ok(Response::new(reply))
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse().unwrap();
let mut bind = TcpListener::bind(&addr)?;
let mut server = Server::new(MakeSvc, Default::default());
while let Ok((sock, _addr)) = bind.accept().await {
if let Err(e) = sock.set_nodelay(true) {
return Err(e.into());
}
if let Err(e) = server.serve(sock).await {
println!("H2 ERROR: {}", e);
}
}
Ok(())
}
#[derive(Debug)]
pub struct Svc;
impl Service<http::Request<RecvBody>> for Svc {
type Response = http::Response<body::BoxAsyncBody>;
type Error = tonic::error::Never;
type Future = impl Future<Output = Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Ok(()).into()
}
fn call(&mut self, req: http::Request<RecvBody>) -> Self::Future {
let fut = async move {
let codec = tonic::codec::ProstCodec::new();
let mut grpc = Grpc::new(codec);
let response = grpc.unary(SayHello, req).await;
Ok(response)
};
Box::pin(fut)
}
}
pub struct MakeSvc;
impl Service<()> for MakeSvc {
type Response = Svc;
type Error = std::io::Error;
type Future = future::Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Ok(()).into()
}
fn call(&mut self, _: ()) -> Self::Future {
future::ok(Svc)
}
}
+1
View File
@@ -98,6 +98,7 @@ impl Body for BoxAsyncBody {
}
}
// TODO: refactor this to accept an !Unpin stream
#[derive(Debug)]
pub struct AsyncBody<S> {
inner: S,
+2
View File
@@ -43,6 +43,8 @@ pub mod _codegen {
pub type BoxFuture<T, E> =
self::Pin<Box<dyn self::Future<Output = Result<T, E>> + Send + 'static>>;
pub type BoxStream<T> =
self::Pin<Box<dyn futures_core::Stream<Item = Result<T, crate::Status>> + Send + 'static>>;
pub mod http {
pub use http::*;
+19
View File
@@ -6,6 +6,10 @@ use tokio_buf::BufStream;
use tonic::codec::UnitCodec;
use tonic::server::*;
use tonic::{Request, Response, Status};
use std::pin::Pin;
use futures_core::Stream;
type BoxStream<T> = Pin<Box<dyn Stream<Item = Result<T, Status>> + Send + 'static>>;
struct SayHello;
@@ -18,6 +22,18 @@ impl UnaryService<()> for SayHello {
}
}
struct SayHelloStream;
impl<S> ClientStreamingService<S> for SayHelloStream
where S: Stream{
type Response = ();
type Future = impl Future<Output = Result<Response<Self::Response>, Status>>;
fn call(&mut self, _: Request<S>) -> Self::Future {
async move { Ok(Response::new(())) }
}
}
#[tokio::test]
async fn say_hello() {
let codec = UnitCodec::default();
@@ -25,6 +41,9 @@ async fn say_hello() {
let request = http::Request::new(Body(Vec::new()));
grpc.unary(SayHello, request).await;
let request = http::Request::new(Body(Vec::new()));
grpc.client_streaming(SayHelloStream, request).await;
}
#[derive(Debug, Default, Clone)]