mirror of
https://github.com/rwf2/Rocket.git
synced 2025-02-16 13:42:05 +00:00
Document ContentType.
This commit is contained in:
parent
4595338a39
commit
57f79ca867
@ -8,11 +8,20 @@ use std::fmt;
|
|||||||
|
|
||||||
use router::Collider;
|
use router::Collider;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
/// Rocket's representation of HTTP Content-Types.
|
||||||
pub struct ContentType(pub TopLevel, pub SubLevel, pub Option<Vec<Param>>);
|
///
|
||||||
|
/// This type wraps raw HTTP `Content-Type`s in a type-safe manner. It provides
|
||||||
|
/// methods to create and test against common HTTP content-types. It also
|
||||||
|
/// provides methods to parse HTTP Content-Type values
|
||||||
|
/// ([from_str](#method.from_str)) and to return the ContentType associated with
|
||||||
|
/// a file extension ([from_ext](#method.from_extension)).
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct ContentType(pub TopLevel, pub SubLevel, Option<Vec<Param>>);
|
||||||
|
|
||||||
macro_rules! is_some {
|
macro_rules! is_some {
|
||||||
($ct:ident, $name:ident: $top:ident/$sub:ident) => {
|
($ct:ident, $name:ident: $top:ident/$sub:ident) => {
|
||||||
|
/// Returns a new ContentType that matches the MIME for this method's
|
||||||
|
/// name.
|
||||||
pub fn $ct() -> ContentType {
|
pub fn $ct() -> ContentType {
|
||||||
ContentType::of(TopLevel::$top, SubLevel::$sub)
|
ContentType::of(TopLevel::$top, SubLevel::$sub)
|
||||||
}
|
}
|
||||||
@ -21,6 +30,8 @@ macro_rules! is_some {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($name:ident: $top:ident/$sub:ident) => {
|
($name:ident: $top:ident/$sub:ident) => {
|
||||||
|
/// Returns true if `self` is the content type matching the method's
|
||||||
|
/// name.
|
||||||
pub fn $name(&self) -> bool {
|
pub fn $name(&self) -> bool {
|
||||||
self.0 == TopLevel::$top && self.1 == SubLevel::$sub
|
self.0 == TopLevel::$top && self.1 == SubLevel::$sub
|
||||||
}
|
}
|
||||||
@ -28,21 +39,37 @@ macro_rules! is_some {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ContentType {
|
impl ContentType {
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(t: TopLevel, s: SubLevel, params: Option<Vec<Param>>) -> ContentType {
|
pub fn new(t: TopLevel, s: SubLevel, params: Option<Vec<Param>>) -> ContentType {
|
||||||
ContentType(t, s, params)
|
ContentType(t, s, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a new content type of the given top level and sub level
|
||||||
|
/// types.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
/// use rocket::response::mime::{TopLevel, SubLevel};
|
||||||
|
///
|
||||||
|
/// let html = ContentType::of(TopLevel::Application, SubLevel::Html);
|
||||||
|
/// assert!(html.is_html());
|
||||||
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn of(t: TopLevel, s: SubLevel) -> ContentType {
|
pub fn of(t: TopLevel, s: SubLevel) -> ContentType {
|
||||||
ContentType(t, s, None)
|
ContentType(t, s, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new ContentType for `*/*`, i.e., any.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn any() -> ContentType {
|
pub fn any() -> ContentType {
|
||||||
ContentType::of(TopLevel::Star, SubLevel::Star)
|
ContentType::of(TopLevel::Star, SubLevel::Star)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this content type is not one of the standard content
|
||||||
|
/// types, that if, if it is an "extended" content type.
|
||||||
pub fn is_ext(&self) -> bool {
|
pub fn is_ext(&self) -> bool {
|
||||||
if let TopLevel::Ext(_) = self.0 {
|
if let TopLevel::Ext(_) = self.0 {
|
||||||
true
|
true
|
||||||
@ -53,13 +80,49 @@ impl ContentType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the content type is JSON, i.e: `application/json`.
|
||||||
is_some!(json, is_json: Application/Json);
|
is_some!(json, is_json: Application/Json);
|
||||||
|
|
||||||
|
/// Returns true if the content type is XML, i.e: `application/xml`.
|
||||||
is_some!(xml, is_xml: Application/Xml);
|
is_some!(xml, is_xml: Application/Xml);
|
||||||
|
|
||||||
|
/// Returns true if the content type is any, i.e.: `*/*`.
|
||||||
is_some!(is_any: Star/Star);
|
is_some!(is_any: Star/Star);
|
||||||
|
|
||||||
|
/// Returns true if the content type is HTML, i.e.: `application/html`.
|
||||||
is_some!(html, is_html: Application/Html);
|
is_some!(html, is_html: Application/Html);
|
||||||
|
|
||||||
|
/// Returns true if the content type is that for non-data HTTP forms, i.e.:
|
||||||
|
/// `application/x-www-form-urlencoded`.
|
||||||
is_some!(is_form: Application/WwwFormUrlEncoded);
|
is_some!(is_form: Application/WwwFormUrlEncoded);
|
||||||
|
|
||||||
|
/// Returns true if the content type is that for data HTTP forms, i.e.:
|
||||||
|
/// `multipart/form-data`.
|
||||||
is_some!(is_data: Multipart/FormData);
|
is_some!(is_data: Multipart/FormData);
|
||||||
|
|
||||||
|
/// Returns the Content-Type associated with the extension `ext`. Not all
|
||||||
|
/// extensions are recognized. If an extensions is not recognized, then this
|
||||||
|
/// method returns a ContentType of `any`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// A recognized content type:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
///
|
||||||
|
/// let xml = ContentType::from_extension("xml");
|
||||||
|
/// assert!(xml.is_xml());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// An unrecognized content type:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
///
|
||||||
|
/// let foo = ContentType::from_extension("foo");
|
||||||
|
/// assert!(foo.is_any());
|
||||||
|
/// ```
|
||||||
pub fn from_extension(ext: &str) -> ContentType {
|
pub fn from_extension(ext: &str) -> ContentType {
|
||||||
let (top_level, sub_level) = match ext {
|
let (top_level, sub_level) = match ext {
|
||||||
"txt" => (TopLevel::Text, SubLevel::Plain),
|
"txt" => (TopLevel::Text, SubLevel::Plain),
|
||||||
@ -82,18 +145,21 @@ impl ContentType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ContentType {
|
impl Default for ContentType {
|
||||||
|
/// Returns a ContentType of `any`, or `*/*`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default() -> ContentType {
|
fn default() -> ContentType {
|
||||||
ContentType::any()
|
ContentType::any()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
impl Into<Mime> for ContentType {
|
impl Into<Mime> for ContentType {
|
||||||
fn into(self) -> Mime {
|
fn into(self) -> Mime {
|
||||||
Mime(self.0, self.1, self.2.unwrap_or_default())
|
Mime(self.0, self.1, self.2.unwrap_or_default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
impl<T: Borrow<Mime>> From<T> for ContentType {
|
impl<T: Borrow<Mime>> From<T> for ContentType {
|
||||||
default fn from(mime: T) -> ContentType {
|
default fn from(mime: T) -> ContentType {
|
||||||
let mime: Mime = mime.borrow().clone();
|
let mime: Mime = mime.borrow().clone();
|
||||||
@ -101,6 +167,7 @@ impl<T: Borrow<Mime>> From<T> for ContentType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
impl From<Mime> for ContentType {
|
impl From<Mime> for ContentType {
|
||||||
fn from(mime: Mime) -> ContentType {
|
fn from(mime: Mime) -> ContentType {
|
||||||
let params = match mime.2.len() {
|
let params = match mime.2.len() {
|
||||||
@ -129,6 +196,42 @@ fn is_valid_char(c: char) -> bool {
|
|||||||
impl FromStr for ContentType {
|
impl FromStr for ContentType {
|
||||||
type Err = &'static str;
|
type Err = &'static str;
|
||||||
|
|
||||||
|
/// Parses a ContentType from a given Content-Type header value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Parsing an `application/json`:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
/// use std::str::FromStr;
|
||||||
|
///
|
||||||
|
/// let json = ContentType::from_str("application/json");
|
||||||
|
/// assert_eq!(json, Ok(ContentType::json()));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Parsing a content-type extension:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
/// use std::str::FromStr;
|
||||||
|
/// use rocket::response::mime::{TopLevel, SubLevel};
|
||||||
|
///
|
||||||
|
/// let custom = ContentType::from_str("application/x-custom").unwrap();
|
||||||
|
/// assert!(custom.is_ext());
|
||||||
|
/// assert_eq!(custom.0, TopLevel::Application);
|
||||||
|
/// assert_eq!(custom.1, SubLevel::Ext("x-custom".into()));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Parsing an invalid Content-Type value:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
/// use std::str::FromStr;
|
||||||
|
///
|
||||||
|
/// let custom = ContentType::from_str("application//x-custom");
|
||||||
|
/// assert!(custom.is_err());
|
||||||
|
/// ```
|
||||||
fn from_str(raw: &str) -> Result<ContentType, &'static str> {
|
fn from_str(raw: &str) -> Result<ContentType, &'static str> {
|
||||||
let slash = match raw.find('/') {
|
let slash = match raw.find('/') {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
@ -165,6 +268,16 @@ impl FromStr for ContentType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ContentType {
|
impl fmt::Display for ContentType {
|
||||||
|
/// Formats the ContentType as an HTTP Content-Type value.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::ContentType;
|
||||||
|
///
|
||||||
|
/// let http_ct = format!("{}", ContentType::xml());
|
||||||
|
/// assert_eq!(http_ct, "application/xml".to_string());
|
||||||
|
/// ```
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}/{}", self.0.as_str(), self.1.as_str())?;
|
write!(f, "{}/{}", self.0.as_str(), self.1.as_str())?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user