use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use hyper::body::{Bytes, Incoming};
use hyper::{Request, Response};
use http_body_util::combinators::BoxBody;
use http_body_util::{BodyExt, Full};
use crate::error::ServeError;
use crate::state::State;
#[derive(Debug)]
pub struct BodyError {
inner: Box<dyn std::error::Error + Send + Sync>,
}
impl BodyError {
pub fn new(err: impl std::error::Error + Send + Sync + 'static) -> Self {
BodyError {
inner: Box::new(err),
}
}
}
impl fmt::Display for BodyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "body streaming error: {}", self.inner)
}
}
impl std::error::Error for BodyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.inner)
}
}
impl From<Box<dyn std::error::Error + Send + Sync>> for BodyError {
fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
BodyError { inner: err }
}
}
pub type ResponseBody = BoxBody<Bytes, BodyError>;
pub fn body(bytes: Bytes) -> ResponseBody {
BoxBody::new(Full::new(bytes).map_err(|never: std::convert::Infallible| match never {}))
}
pub type Handler<S> = Arc<
dyn Fn(Request<Incoming>, State<S>)
-> Pin<Box<dyn Future<Output = Result<Response<ResponseBody>, ServeError>> + Send>>
+ Send
+ Sync,
>;
pub fn handler<S, F, Fut>(f: F) -> Handler<S>
where
S: Send + Sync + 'static,
F: Fn(Request<Incoming>, State<S>) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<Response<ResponseBody>, ServeError>> + Send + 'static,
{
Arc::new(move |req, state| Box::pin(f(req, state)))
}