use std::convert::TryFrom;
use std::sync::Arc;
use http::header::{HeaderMap, HeaderName, HeaderValue};
use self::sealed::{WithDefaultHeader_, WithHeader_, WithHeaders_};
use crate::filter::{Filter, Map, WrapSealed};
use crate::reply::Reply;
pub fn header<K, V>(name: K, value: V) -> WithHeader
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let (name, value) = assert_name_and_value(name, value);
WithHeader { name, value }
}
pub fn headers(headers: HeaderMap) -> WithHeaders {
WithHeaders {
headers: Arc::new(headers),
}
}
pub fn default_header<K, V>(name: K, value: V) -> WithDefaultHeader
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let (name, value) = assert_name_and_value(name, value);
WithDefaultHeader { name, value }
}
#[derive(Clone, Debug)]
pub struct WithHeader {
name: HeaderName,
value: HeaderValue,
}
impl<F, R> WrapSealed<F> for WithHeader
where
F: Filter<Extract = (R,)>,
R: Reply,
{
type Wrapped = Map<F, WithHeader_>;
fn wrap(&self, filter: F) -> Self::Wrapped {
let with = WithHeader_ { with: self.clone() };
filter.map(with)
}
}
#[derive(Clone, Debug)]
pub struct WithHeaders {
headers: Arc<HeaderMap>,
}
impl<F, R> WrapSealed<F> for WithHeaders
where
F: Filter<Extract = (R,)>,
R: Reply,
{
type Wrapped = Map<F, WithHeaders_>;
fn wrap(&self, filter: F) -> Self::Wrapped {
let with = WithHeaders_ { with: self.clone() };
filter.map(with)
}
}
#[derive(Clone, Debug)]
pub struct WithDefaultHeader {
name: HeaderName,
value: HeaderValue,
}
impl<F, R> WrapSealed<F> for WithDefaultHeader
where
F: Filter<Extract = (R,)>,
R: Reply,
{
type Wrapped = Map<F, WithDefaultHeader_>;
fn wrap(&self, filter: F) -> Self::Wrapped {
let with = WithDefaultHeader_ { with: self.clone() };
filter.map(with)
}
}
fn assert_name_and_value<K, V>(name: K, value: V) -> (HeaderName, HeaderValue)
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let name = <HeaderName as TryFrom<K>>::try_from(name)
.map_err(Into::into)
.unwrap_or_else(|_| panic!("invalid header name"));
let value = <HeaderValue as TryFrom<V>>::try_from(value)
.map_err(Into::into)
.unwrap_or_else(|_| panic!("invalid header value"));
(name, value)
}
mod sealed {
use super::{WithDefaultHeader, WithHeader, WithHeaders};
use crate::generic::{Func, One};
use crate::reply::{Reply, Reply_};
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct WithHeader_ {
pub(super) with: WithHeader,
}
impl<R: Reply> Func<One<R>> for WithHeader_ {
type Output = Reply_;
fn call(&self, args: One<R>) -> Self::Output {
let mut resp = args.0.into_response();
resp.headers_mut()
.insert(&self.with.name, self.with.value.clone());
Reply_(resp)
}
}
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct WithHeaders_ {
pub(super) with: WithHeaders,
}
impl<R: Reply> Func<One<R>> for WithHeaders_ {
type Output = Reply_;
fn call(&self, args: One<R>) -> Self::Output {
let mut resp = args.0.into_response();
for (name, value) in &*self.with.headers {
resp.headers_mut().insert(name, value.clone());
}
Reply_(resp)
}
}
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct WithDefaultHeader_ {
pub(super) with: WithDefaultHeader,
}
impl<R: Reply> Func<One<R>> for WithDefaultHeader_ {
type Output = Reply_;
fn call(&self, args: One<R>) -> Self::Output {
let mut resp = args.0.into_response();
resp.headers_mut()
.entry(&self.with.name)
.or_insert_with(|| self.with.value.clone());
Reply_(resp)
}
}
}