use std::convert::Infallible;
use bytes::Bytes;
use http::StatusCode;
use http::header::HeaderName;
use http::header::HeaderValue;
use http_body_util::Full;
use crate::body::TakoBody;
use crate::types::Response;
pub const NOT_FOUND: (StatusCode, &str) = (StatusCode::NOT_FOUND, "Not Found");
#[doc(alias = "response")]
pub trait Responder {
fn into_response(self) -> Response;
}
impl Responder for Response {
fn into_response(self) -> Response {
self
}
}
impl Responder for TakoBody {
fn into_response(self) -> Response {
Response::new(self)
}
}
impl Responder for &'static str {
fn into_response(self) -> Response {
Response::new(TakoBody::full(Full::from(Bytes::from_static(
self.as_bytes(),
))))
}
}
impl Responder for String {
fn into_response(self) -> Response {
Response::new(TakoBody::full(Full::from(Bytes::from(self))))
}
}
impl Responder for () {
fn into_response(self) -> Response {
Response::new(TakoBody::empty())
}
}
impl Responder for Infallible {
fn into_response(self) -> Response {
match self {}
}
}
impl Responder for (StatusCode, &'static str) {
fn into_response(self) -> Response {
let (status, body) = self;
let mut res = Response::new(TakoBody::full(Full::from(Bytes::from_static(
body.as_bytes(),
))));
*res.status_mut() = status;
res
}
}
impl Responder for (StatusCode, String) {
fn into_response(self) -> Response {
let (status, body) = self;
let mut res = Response::new(TakoBody::full(Full::from(Bytes::from(body))));
*res.status_mut() = status;
res
}
}
impl Responder for (StatusCode, Vec<u8>) {
fn into_response(self) -> Response {
let (status, body) = self;
let mut res = Response::new(TakoBody::full(Full::from(Bytes::from(body))));
*res.status_mut() = status;
res
}
}
pub struct StaticHeaders<const N: usize>(pub [(HeaderName, &'static str); N]);
impl<const N: usize> Responder for (StatusCode, StaticHeaders<N>) {
fn into_response(self) -> Response {
let (status, StaticHeaders(headers)) = self;
let mut res = Response::new(TakoBody::empty());
*res.status_mut() = status;
for (name, value) in headers {
res
.headers_mut()
.append(name, HeaderValue::from_static(value));
}
res
}
}
impl<T> Responder for anyhow::Result<T>
where
T: Responder,
{
fn into_response(self) -> Response {
match self {
Ok(ok) => ok.into_response(),
Err(err) => {
let mut res = Response::new(TakoBody::from(err.to_string()));
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
res.headers_mut().insert(
http::header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
);
res
}
}
}
}