use async_trait::async_trait;
use futures::Future;
use hyperx::header::Header;
use std::fmt::Display;
use tide::convert::Serialize;
use tide::http::headers::{HeaderName, HeaderValue, ToHeaderValues};
use tide::{Body, Request, StatusCode};
pub trait Responder {
fn into_response(self) -> tide::Result<tide::Response>;
}
pub struct High<F>(F);
pub fn wrap<F>(f: F) -> High<F> {
High(f)
}
#[async_trait]
impl<State, F, Fut, Res> tide::Endpoint<State> for High<F>
where
State: Clone + Send + Sync + 'static,
F: Send + Sync + 'static + Fn(Request<State>) -> Fut,
Fut: Future<Output = Res> + Send + 'static,
Res: Responder + 'static,
{
async fn call(&self, req: Request<State>) -> tide::Result<tide::Response> {
let fut = (self.0)(req);
let res = fut.await;
res.into_response()
}
}
pub struct Response {
inner: tide::Response,
}
impl Response {
pub fn ok() -> Self {
Self {
inner: tide::Response::from(StatusCode::Ok),
}
}
pub fn status(s: StatusCode) -> Self {
Self {
inner: tide::Response::from(s),
}
}
pub fn body(mut self, body: impl Into<Body>) -> Self {
self.inner.set_body(body);
self
}
pub fn json(mut self, body: impl Serialize) -> tide::Result<Self> {
self.inner.set_body(Body::from_json(&body)?);
Ok(self)
}
pub fn form(mut self, body: impl Serialize) -> tide::Result<Self> {
self.inner.set_body(Body::from_form(&body)?);
Ok(self)
}
pub fn header<H: Header + Display>(mut self, h: H) -> Self {
self.inner.insert_header(
H::header_name(),
h.to_string()
.parse::<HeaderValue>()
.expect("invalid header"),
);
self
}
pub fn raw_header(mut self, name: impl Into<HeaderName>, key: impl ToHeaderValues) -> Self {
self.inner.insert_header(name, key);
self
}
pub fn into_inner(self) -> tide::Response {
self.inner
}
}
impl Responder for StatusCode {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(tide::Response::from(self))
}
}
impl Responder for String {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(tide::Response::from(self))
}
}
impl Responder for &str {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(tide::Response::from(self))
}
}
impl Responder for &[u8] {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(tide::Response::from(Body::from(self)))
}
}
impl<R: Responder> Responder for (StatusCode, R) {
fn into_response(self) -> tide::Result<tide::Response> {
let mut resp = self.1.into_response()?;
resp.set_status(self.0);
Ok(resp)
}
}
impl<R: Responder> Responder for Option<R> {
fn into_response(self) -> tide::Result<tide::Response> {
match self {
None => StatusCode::NotFound.into_response(),
Some(r) => r.into_response(),
}
}
}
pub struct Json<T: Serialize>(pub T);
impl<T: Serialize> Responder for Json<T> {
fn into_response(self) -> tide::Result<tide::Response> {
Response::ok().json(self.0).map(|r| r.into_inner())
}
}
pub struct Form<T: Serialize>(pub T);
impl<T: Serialize> Responder for Form<T> {
fn into_response(self) -> tide::Result<tide::Response> {
Response::ok().form(self.0).map(|r| r.into_inner())
}
}
impl Responder for Response {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(self.into_inner())
}
}
impl Responder for tide::Response {
fn into_response(self) -> tide::Result<tide::Response> {
Ok(self)
}
}
impl<R: Responder> Responder for tide::Result<R> {
fn into_response(self) -> tide::Result<tide::Response> {
self.and_then(|r| r.into_response())
}
}