use std::borrow::{Borrow, Cow};
use std::ops::Deref;
use std::str::FromStr;
use std::fmt;
use ext::IntoCollection;
use http::{Header, MediaType, Source};
use http::hyper::mime::Mime;
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct ContentType(pub MediaType);
macro_rules! content_types {
($($name:ident ($check:ident): $str:expr, $t:expr,
$s:expr $(; $k:expr => $v:expr)*),+) => {
$(
#[doc="Content-Type for <b>"] #[doc=$str] #[doc="</b>: <i>"]
#[doc=$t] #[doc="/"] #[doc=$s]
$(#[doc="; "] #[doc=$k] #[doc=" = "] #[doc=$v])*
#[doc="</i>"]
#[allow(non_upper_case_globals)]
pub const $name: ContentType = ContentType(MediaType::$name);
)+
};
}
impl ContentType {
#[inline(always)]
pub fn new<T, S>(top: T, sub: S) -> ContentType
where T: Into<Cow<'static, str>>, S: Into<Cow<'static, str>>
{
ContentType(MediaType::new(top, sub))
}
#[inline]
pub fn from_extension(ext: &str) -> Option<ContentType> {
MediaType::from_extension(ext).map(ContentType)
}
#[inline]
pub fn with_params<T, S, K, V, P>(top: T, sub: S, ps: P) -> ContentType
where T: Into<Cow<'static, str>>, S: Into<Cow<'static, str>>,
K: Into<Cow<'static, str>>, V: Into<Cow<'static, str>>,
P: IntoCollection<(K, V)>
{
ContentType(MediaType::with_params(top, sub, ps))
}
#[inline(always)]
pub fn media_type(&self) -> &MediaType {
&self.0
}
known_media_types!(content_types);
}
impl Default for ContentType {
#[inline(always)]
fn default() -> ContentType {
ContentType::Any
}
}
impl Deref for ContentType {
type Target = MediaType;
#[inline(always)]
fn deref(&self) -> &MediaType {
&self.0
}
}
#[doc(hidden)]
impl<T: Borrow<Mime>> From<T> for ContentType {
#[inline(always)]
default fn from(mime: T) -> ContentType {
let mime: Mime = mime.borrow().clone();
ContentType::from(mime)
}
}
#[doc(hidden)]
impl From<Mime> for ContentType {
#[inline]
fn from(mime: Mime) -> ContentType {
let params = mime.2.into_iter()
.map(|(attr, value)| (attr.to_string(), value.to_string()))
.collect::<Vec<_>>();
ContentType::with_params(mime.0.to_string(), mime.1.to_string(), params)
}
}
impl FromStr for ContentType {
type Err = String;
#[inline(always)]
fn from_str(raw: &str) -> Result<ContentType, String> {
MediaType::from_str(raw).map(|mt| ContentType(mt))
}
}
impl fmt::Display for ContentType {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Into<Header<'static>> for ContentType {
#[inline(always)]
fn into(self) -> Header<'static> {
if let Source::Known(src) = self.0.source {
Header::new("Content-Type", src)
} else {
Header::new("Content-Type", self.to_string())
}
}
}