use std::{borrow::Cow, convert::Infallible};
use bytes::{Bytes, BytesMut};
use http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::{
body::ResponseBody, either::Either, error::BoxError, media_type::MediaType, response::Response,
response_error::ResponseError,
};
pub trait IntoResponse {
type Error: ResponseError;
fn into_response(self) -> Result<Response, Self::Error>;
}
impl<B> IntoResponse for Response<B>
where
B: http_body::Body<Data = Bytes> + Send + 'static,
B::Error: Into<BoxError>,
{
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
Ok(self.map(ResponseBody::new))
}
}
impl IntoResponse for http::response::Parts {
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
Ok(Response::from_parts(self, ResponseBody::empty()))
}
}
impl IntoResponse for ResponseBody {
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
Ok(Response::new(self))
}
}
impl IntoResponse for () {
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
ResponseBody::empty().into_response()
}
}
impl IntoResponse for StatusCode {
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
let mut response = ().into_response()?;
*response.status_mut() = self;
Ok(response)
}
}
impl IntoResponse for Infallible {
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
match self {}
}
}
macro_rules! some_impl {
($ty:ty; $($desc:tt)+) => {
impl $($desc)+
{
type Error = Infallible;
fn into_response(self) -> Result<Response, Self::Error> {
let mut response = Response::new(self.into());
response
.headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static(<$ty as MediaType>::MEDIA_TYPE));
Ok(response)
}
}
};
}
some_impl!(String; IntoResponse for &'static str);
some_impl!(String; IntoResponse for Cow<'static, str>);
some_impl!(String; IntoResponse for String);
some_impl!(String; IntoResponse for Box<str>);
some_impl!(Vec<u8>; IntoResponse for &'static [u8]);
some_impl!(Vec<u8>; IntoResponse for Cow<'static, [u8]>);
some_impl!(Vec<u8>; IntoResponse for Vec<u8>);
some_impl!(Vec<u8>; IntoResponse for Bytes);
some_impl!(Vec<u8>; IntoResponse for BytesMut);
some_impl!(Vec<u8>; IntoResponse for Box<[u8]>);
some_impl!([u8; N]; <const N: usize> IntoResponse for [u8; N]);
some_impl!([u8; N]; <const N: usize> IntoResponse for &'static [u8; N]);
impl<T, E> IntoResponse for Result<T, E>
where
T: IntoResponse,
E: ResponseError,
{
type Error = Either<T::Error, E>;
fn into_response(self) -> Result<Response, Self::Error> {
match self {
Ok(t) => t.into_response().map_err(Either::Left),
Err(e) => Err(Either::Right(e)),
}
}
}