#![forbid(future_incompatible, rust_2018_idioms)]
#![deny(missing_debug_implementations, nonstandard_style)]
#![warn(missing_docs, missing_doc_code_examples)]
#![cfg_attr(test, deny(warnings))]
#![feature(futures_api, async_await, await_macro, arbitrary_self_types)]
use bytes::Bytes;
use futures::{
future,
prelude::*,
stream::{self, StreamObj},
task::Context,
Poll,
};
use std::marker::Unpin;
use std::pin::Pin;
#[derive(Debug)]
pub struct Body {
stream: StreamObj<'static, Result<Bytes, std::io::Error>>,
}
impl Body {
pub fn empty() -> Self {
Body::from_stream(stream::empty())
}
pub fn from_stream<S>(s: S) -> Self
where
S: Stream<Item = Result<Bytes, std::io::Error>> + Send + 'static,
{
Self {
stream: StreamObj::new(Box::new(s)),
}
}
pub async fn into_vec(mut self) -> std::io::Result<Vec<u8>> {
let mut bytes = Vec::new();
while let Some(chunk) = await!(self.next()) {
bytes.extend(chunk?);
}
Ok(bytes)
}
}
impl<T: Into<Bytes> + Send> From<T> for Body {
fn from(x: T) -> Self {
Self::from_stream(stream::once(future::ok(x.into())))
}
}
impl Unpin for Body {}
impl Stream for Body {
type Item = Result<Bytes, std::io::Error>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.stream).poll_next(cx)
}
}
pub type Request = http::Request<Body>;
pub type Response = http::Response<Body>;
pub trait HttpService: Send + Sync + 'static {
type Connection: Send + 'static;
type ConnectionFuture: Send + 'static + TryFuture<Ok = Self::Connection>;
fn connect(&self) -> Self::ConnectionFuture;
type Fut: Send + 'static + TryFuture<Ok = Response>;
fn respond(&self, conn: &mut Self::Connection, req: Request) -> Self::Fut;
}
impl<F, Fut> HttpService for F
where
F: Send + Sync + 'static + Fn(Request) -> Fut,
Fut: Send + 'static + TryFuture<Ok = Response>,
Fut::Error: Send,
{
type Connection = ();
type ConnectionFuture = future::Ready<Result<(), Fut::Error>>;
fn connect(&self) -> Self::ConnectionFuture {
future::ok(())
}
type Fut = Fut;
fn respond(&self, _: &mut (), req: Request) -> Self::Fut {
(self)(req)
}
}