#![forbid(future_incompatible, rust_2018_idioms)]
#![deny(missing_debug_implementations, nonstandard_style)]
#![warn(missing_docs, missing_doc_code_examples)]
#![cfg_attr(any(feature = "nightly", test), feature(external_doc))]
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]
use bytes::Bytes;
use futures::{
future,
prelude::*,
stream::{self, BoxStream},
task::{Context, Poll},
};
use std::fmt;
use std::pin::Pin;
#[cfg(test)]
#[doc(include = "../README.md")]
const _README: () = ();
pub struct Body {
stream: BoxStream<'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: s.boxed() }
}
#[allow(clippy::wrong_self_convention)] pub async fn into_vec(mut self) -> std::io::Result<Vec<u8>> {
let mut bytes = Vec::new();
while let Some(chunk) = self.next().await {
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>> {
self.stream.poll_next_unpin(cx)
}
}
impl fmt::Debug for Body {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Body").finish()
}
}
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 ResponseFuture: Send + 'static + TryFuture<Ok = Response>;
fn respond(&self, conn: &mut Self::Connection, req: Request) -> Self::ResponseFuture;
}
impl<F, R> HttpService for F
where
F: Send + Sync + 'static + Fn(Request) -> R,
R: Send + 'static + TryFuture<Ok = Response>,
R::Error: Send,
{
type Connection = ();
type ConnectionFuture = future::Ready<Result<(), R::Error>>;
fn connect(&self) -> Self::ConnectionFuture {
future::ok(())
}
type ResponseFuture = R;
fn respond(&self, _: &mut (), req: Request) -> Self::ResponseFuture {
(self)(req)
}
}