#[cfg(feature = "cookie")]
use crate::types::cookie::CookieParam;
use crate::{
response::Response,
types::{Form, Header, Json, Path, Query, Text},
};
#[cfg(feature = "cookie")]
use cookie::{Cookie, CookieJar};
use hyper::{body::Bytes, header::HeaderValue, StatusCode};
macro_rules! status_responder {
( $( $x:ty ),+ ) => {
$(
impl Responder for $x {
#[inline]
fn response(self, builder: Response) -> Response {
builder.status(self as u16)
}
}
)+
}
}
macro_rules! body_responder {
( $( $x:ty ),+ ) => {
$(
impl Responder for $x {
#[inline]
fn response(self, builder: Response) -> Response {
builder.body(self)
}
}
)+
}
}
macro_rules! plain_body_responder {
( $( $x:ty ),+ ) => {
$(
impl Responder for $x {
#[inline]
fn response(self, builder: Response) -> Response {
builder.content_type("text/plain; charset=utf-8").body(self)
}
}
)+
}
}
macro_rules! tuple_responder {
( $($idx:tt -> $T:ident),+ ) => {
impl<$($T:Responder),+> Responder for ($($T),+) {
#[inline]
fn response(self, builder: Response) -> Response {
$(let builder = self.$idx.response(builder);)+
builder
}
}
}
}
status_responder!(u16, i16, u32, i32, u64, i64, usize, isize);
plain_body_responder!(String, &'static str);
body_responder!(Vec<u8>, &'static [u8], hyper::body::Bytes);
tuple_responder!(0->A, 1->B);
tuple_responder!(0->A, 1->B, 2->C);
tuple_responder!(0->A, 1->B, 2->C, 3->D);
tuple_responder!(0->A, 1->B, 2->C, 3->D, 4->E);
tuple_responder!(0->A, 1->B, 2->C, 3->D, 4->E, 5->F);
pub trait Responder {
fn response(self, builder: Response) -> Response;
}
impl<T> Responder for Vec<T>
where
T: Responder,
{
#[inline]
fn response(self, mut builder: Response) -> Response {
for responder in self {
builder = responder.response(builder);
}
builder
}
}
impl<T> Responder for &'static [T]
where
T: Responder + Clone,
{
#[inline]
fn response(self, mut builder: Response) -> Response {
for responder in self {
builder = responder.clone().response(builder);
}
builder
}
}
impl Responder for StatusCode {
#[inline]
fn response(self, builder: Response) -> Response {
builder.status(self)
}
}
impl Responder for () {
#[inline]
fn response(self, builder: Response) -> Response {
builder.status(200)
}
}
impl<T: Responder> Responder for Option<T> {
#[inline]
fn response(self, builder: Response) -> Response {
if let Some(r) = self {
r.response(builder).status_if_not_set(200)
} else {
builder.status_if_not_set(404)
}
}
}
impl<T: Responder, E: Responder> Responder for Result<T, E> {
#[inline]
fn response(self, builder: Response) -> Response {
match self {
Ok(r) => r.response(builder).status_if_not_set(200),
Err(r) => r.response(builder).status_if_not_set(500),
}
}
}
impl Responder for hyper::Error {
#[inline]
fn response(self, builder: Response) -> Response {
builder.status(500)
}
}
impl Responder for Response {
#[inline]
fn response(self, _builder: Response) -> Response {
self
}
}
#[cfg(feature = "cookie")]
impl<T: serde::Serialize> Responder for CookieParam<T, true> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
#[cfg(feature = "cookie")]
impl<T: serde::Serialize> Responder for CookieParam<T, false> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
impl<T: serde::Serialize> Responder for Header<T, true> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
impl<T: serde::Serialize> Responder for Header<T, false> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
impl<T: serde::Serialize> Responder for Path<T> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.0)
}
}
impl<T: serde::Serialize> Responder for Query<T, true> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
impl<T: serde::Serialize> Responder for Query<T, false> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.inner())
}
}
impl<T: serde::Serialize> Responder for Json<T> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.json(&self.0)
}
}
impl<T: serde::Serialize> Responder for Form<T> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.form(&self.0)
}
}
#[cfg(feature = "cookie")]
impl Responder for Cookie<'static> {
#[inline]
fn response(self, builder: Response) -> Response {
builder.cookie(self)
}
}
#[cfg(feature = "cookie")]
impl Responder for CookieJar {
#[inline]
fn response(self, mut builder: Response) -> Response {
*builder.cookies_mut() = self;
builder
}
}
impl<C> Responder for Text<C>
where
C: Into<Bytes>,
{
fn response(self, mut builder: Response) -> Response {
let (ctype, content) = match self {
Self::Plain(content) => (
HeaderValue::from_static("text/plain; charset=utf-8"),
content,
),
Self::Json(content) => (
HeaderValue::from_static("application/json; charset=utf-8"),
content,
),
Self::Xml(content) => (
HeaderValue::from_static("application/xml; charset=utf-8"),
content,
),
Self::Html(content) => (
HeaderValue::from_static("text/html; charset=utf-8"),
content,
),
Self::Js(content) => (
HeaderValue::from_static("text/javascript; charset=utf-8"),
content,
),
Self::Css(content) => (HeaderValue::from_static("text/css; charset=utf-8"), content),
Self::Csv(content) => (HeaderValue::from_static("text/csv; charset=utf-8"), content),
Self::Atom(content) => (
HeaderValue::from_static("application/atom+xml; charset=utf-8"),
content,
),
Self::Rss(content) => (
HeaderValue::from_static("application/rss+xml; charset=utf-8"),
content,
),
Self::Rdf(content) => (
HeaderValue::from_static("application/rdf+xml; charset=utf-8"),
content,
),
};
builder.headers_mut().insert("content-type", ctype);
builder.body(content)
}
}