mirror of https://github.com/rwf2/Rocket.git
Allow shorthand for route format specifiers.
This commit is contained in:
parent
29d56900c6
commit
362f0ccdac
|
@ -23,6 +23,7 @@ fn method_to_path(ecx: &ExtCtxt, method: Method) -> Path {
|
|||
})
|
||||
}
|
||||
|
||||
// FIXME: I think we also want the attributes here.
|
||||
fn media_type_to_expr(ecx: &ExtCtxt, ct: Option<MediaType>) -> Option<P<Expr>> {
|
||||
ct.map(|ct| {
|
||||
let (top, sub) = (ct.top().as_str(), ct.sub().as_str());
|
||||
|
|
|
@ -258,7 +258,7 @@ fn parse_rank(ecx: &ExtCtxt, kv: &KVSpanned<LitKind>) -> isize {
|
|||
|
||||
fn parse_format(ecx: &ExtCtxt, kv: &KVSpanned<LitKind>) -> MediaType {
|
||||
if let LitKind::Str(ref s, _) = *kv.value() {
|
||||
if let Ok(ct) = MediaType::from_str(&s.as_str()) {
|
||||
if let Some(ct) = MediaType::parse_flexible(&s.as_str()) {
|
||||
if !ct.is_known() {
|
||||
let msg = format!("'{}' is not a known media type", s);
|
||||
ecx.span_warn(kv.value.span, &msg);
|
||||
|
@ -273,7 +273,8 @@ fn parse_format(ecx: &ExtCtxt, kv: &KVSpanned<LitKind>) -> MediaType {
|
|||
ecx.struct_span_err(kv.span, r#"`format` must be a "media/type""#)
|
||||
.help(r#"format, if specified, must be a key-value pair where
|
||||
the key is `format` and the value is a string representing the
|
||||
media type accepted. e.g: format = "application/json""#)
|
||||
media type accepted. e.g: format = "application/json".
|
||||
shorthand is also accepted: format = "json"#)
|
||||
.emit();
|
||||
|
||||
MediaType::Any
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// must-compile-successfully
|
||||
|
||||
#![feature(plugin, decl_macro)]
|
||||
#![plugin(rocket_codegen)]
|
||||
|
||||
|
@ -12,7 +14,4 @@ fn two() -> &'static str { "hi" }
|
|||
#[get("/", format = "x-custom/x-custom")] //~ WARNING not a known media type
|
||||
fn three() -> &'static str { "hi" }
|
||||
|
||||
// Make the test fail here so we can actually check for the warnings above.
|
||||
assert!(false);
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -30,4 +30,4 @@ error[E0277]: the trait bound `S: rocket::http::uri::FromUriParam<_>` is not sat
|
|||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0277"
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -19,8 +19,9 @@ struct Person {
|
|||
|
||||
// In a `GET` request and all other non-payload supporting request types, the
|
||||
// preferred media type in the Accept header is matched against the `format` in
|
||||
// the route attribute.
|
||||
#[get("/<name>/<age>", format = "application/json")]
|
||||
// the route attribute. Note: if this was a real application, we'd use
|
||||
// `rocket_contrib`'s built-in JSON support and return a `JsonValue` instead.
|
||||
#[get("/<name>/<age>", format = "json")]
|
||||
fn get_hello(name: String, age: u8) -> content::Json<String> {
|
||||
// In a real application, we'd use the JSON contrib type.
|
||||
let person = Person { name: name, age: age, };
|
||||
|
@ -29,7 +30,7 @@ fn get_hello(name: String, age: u8) -> content::Json<String> {
|
|||
|
||||
// In a `POST` request and all other payload supporting request types, the
|
||||
// content type is matched against the `format` in the route attribute.
|
||||
#[post("/<age>", format = "text/plain", data = "<name>")]
|
||||
#[post("/<age>", format = "plain", data = "<name>")]
|
||||
fn post_hello(age: u8, name: String) -> content::Json<String> {
|
||||
let person = Person { name: name, age: age, };
|
||||
content::Json(serde_json::to_string(&person).unwrap())
|
||||
|
|
|
@ -25,7 +25,7 @@ struct Message {
|
|||
}
|
||||
|
||||
// TODO: This example can be improved by using `route` with multiple HTTP verbs.
|
||||
#[post("/<id>", format = "application/json", data = "<message>")]
|
||||
#[post("/<id>", format = "json", data = "<message>")]
|
||||
fn new(id: ID, message: Json<Message>, map: State<MessageMap>) -> JsonValue {
|
||||
let mut hashmap = map.lock().expect("map lock.");
|
||||
if hashmap.contains_key(&id) {
|
||||
|
@ -39,7 +39,7 @@ fn new(id: ID, message: Json<Message>, map: State<MessageMap>) -> JsonValue {
|
|||
}
|
||||
}
|
||||
|
||||
#[put("/<id>", format = "application/json", data = "<message>")]
|
||||
#[put("/<id>", format = "json", data = "<message>")]
|
||||
fn update(id: ID, message: Json<Message>, map: State<MessageMap>) -> Option<JsonValue> {
|
||||
let mut hashmap = map.lock().unwrap();
|
||||
if hashmap.contains_key(&id) {
|
||||
|
@ -50,7 +50,7 @@ fn update(id: ID, message: Json<Message>, map: State<MessageMap>) -> Option<Json
|
|||
}
|
||||
}
|
||||
|
||||
#[get("/<id>", format = "application/json")]
|
||||
#[get("/<id>", format = "json")]
|
||||
fn get(id: ID, map: State<MessageMap>) -> Option<Json<Message>> {
|
||||
let hashmap = map.lock().unwrap();
|
||||
hashmap.get(&id).map(|contents| {
|
||||
|
|
|
@ -15,7 +15,7 @@ struct Message {
|
|||
contents: String
|
||||
}
|
||||
|
||||
#[get("/<id>", format = "application/msgpack")]
|
||||
#[get("/<id>", format = "msgpack")]
|
||||
fn get(id: usize) -> MsgPack<Message> {
|
||||
MsgPack(Message {
|
||||
id: id,
|
||||
|
@ -23,7 +23,7 @@ fn get(id: usize) -> MsgPack<Message> {
|
|||
})
|
||||
}
|
||||
|
||||
#[post("/", data = "<data>", format = "application/msgpack")]
|
||||
#[post("/", data = "<data>", format = "msgpack")]
|
||||
fn create(data: MsgPack<Message>) -> Result<String, ()> {
|
||||
Ok(data.into_inner().contents)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ extern crate rocket;
|
|||
use std::io;
|
||||
use rocket::Data;
|
||||
|
||||
#[post("/upload", format = "text/plain", data = "<data>")]
|
||||
#[post("/upload", format = "plain", data = "<data>")]
|
||||
fn upload(data: Data) -> io::Result<String> {
|
||||
data.stream_to_file("/tmp/upload.txt").map(|n| n.to_string())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
macro_rules! docify {
|
||||
([$($doc:tt)*]; $($tt:tt)*) => {
|
||||
docify!([$($doc)*] [] $($tt)*);
|
||||
};
|
||||
|
||||
// FIXME: Treat $a just like everywhere else. What if we start with @[]?
|
||||
([$a:tt $($b:tt)*] [] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [stringify!($a), " "] $($tt)*);
|
||||
};
|
||||
|
||||
([@fence @$lang:tt $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, "\n\n```", stringify!($lang), "\n"] $($tt)*);
|
||||
};
|
||||
|
||||
([@fence $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, "\n\n```\n"] $($tt)*);
|
||||
};
|
||||
|
||||
([@{$($a:tt),*}! $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, $($a),*] $($tt)*);
|
||||
};
|
||||
|
||||
([@{$($a:tt),*} $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, $($a),*, " "] $($tt)*);
|
||||
};
|
||||
|
||||
([@code{$($a:tt)+}! $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, "`", $(stringify!($a)),*, "`"] $($tt)*);
|
||||
};
|
||||
|
||||
([@code{$($a:tt)+} $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, "`", $(stringify!($a)),*, "` "] $($tt)*);
|
||||
};
|
||||
|
||||
([@[$($a:tt)*]! $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, $(stringify!($a)),*] $($tt)*);
|
||||
};
|
||||
|
||||
([@[$($a:tt)*] $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, $(stringify!($a)),*, " "] $($tt)*);
|
||||
};
|
||||
|
||||
([@nl $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, "\n"] $($tt)*);
|
||||
};
|
||||
|
||||
(@punct [$a:tt $p:tt $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, stringify!($a), stringify!($p), " "] $($tt)*);
|
||||
};
|
||||
|
||||
(@upunct [$a:tt $p:tt $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, stringify!($a), stringify!($p)] $($tt)*);
|
||||
};
|
||||
|
||||
([$a:tt . $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a . $($b)*] $($rest)+); };
|
||||
([$a:tt , $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a , $($b)*] $($rest)+); };
|
||||
([$a:tt ; $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a ; $($b)*] $($rest)+); };
|
||||
([$a:tt : $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a : $($b)*] $($rest)+); };
|
||||
([$a:tt ! $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a ! $($b)*] $($rest)+); };
|
||||
([$a:tt ! $($b:tt)*] $($rest:tt)+) => { docify!(@punct [$a ! $($b)*] $($rest)+); };
|
||||
|
||||
([$a:tt :: $($b:tt)*] $($rest:tt)+) => { docify!(@upunct [$a :: $($b)*] $($rest)+); };
|
||||
|
||||
([$a:tt $($b:tt)*] [$($c:tt)+] $($tt:tt)*) => {
|
||||
docify!([$($b)*] [$($c)+, stringify!($a), " "] $($tt)*);
|
||||
};
|
||||
|
||||
([] [$($doc:expr),*] $($tt:tt)*) => {
|
||||
docify!(concat!($($doc),*), $($tt)*);
|
||||
};
|
||||
|
||||
($x:expr, $($tt:tt)*) => {
|
||||
#[doc = $x]
|
||||
$($tt)*
|
||||
};
|
||||
}
|
|
@ -45,15 +45,119 @@ 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>"]
|
||||
$(
|
||||
docify!([
|
||||
Content Type for @{"**"}! @{$str}! @{"**"}!: @{"`"} @{$t}! @[/]! @{$s}!
|
||||
$(; @{$k}! @[=]! @{$v}!)* @{"`"}!.
|
||||
];
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $name: ContentType = ContentType(MediaType::$name);
|
||||
)+
|
||||
};
|
||||
);
|
||||
)+
|
||||
}}
|
||||
|
||||
macro_rules! from_extension {
|
||||
($($ext:expr => $name:ident,)*) => (
|
||||
docify!([
|
||||
Returns the @[Content-Type] associated with the extension @code{ext}.
|
||||
Not all extensions are recognized. If an extensions is not recognized,
|
||||
@code{None} is returned. The currently recognized extensions are:
|
||||
|
||||
@nl
|
||||
$(* @{$ext} - @{"`ContentType::"}! @[$name]! @{"`"} @nl)*
|
||||
@nl
|
||||
|
||||
This list is likely to grow. Extensions are matched
|
||||
@[case-insensitively.]
|
||||
];
|
||||
/// # Example
|
||||
///
|
||||
/// Recognized content types:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let xml = ContentType::from_extension("xml");
|
||||
/// assert_eq!(xml, Some(ContentType::XML));
|
||||
///
|
||||
/// let xml = ContentType::from_extension("XML");
|
||||
/// assert_eq!(xml, Some(ContentType::XML));
|
||||
/// ```
|
||||
///
|
||||
/// An unrecognized content type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let foo = ContentType::from_extension("foo");
|
||||
/// assert!(foo.is_none());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_extension(ext: &str) -> Option<ContentType> {
|
||||
MediaType::from_extension(ext).map(ContentType)
|
||||
}
|
||||
);)
|
||||
}
|
||||
|
||||
macro_rules! parse_flexible {
|
||||
($($short:expr => $name:ident,)*) => (
|
||||
docify!([
|
||||
Flexibly parses @code{name} into a @code{ContentType}. The parse is
|
||||
@[_flexible_] because, in addition to stricly correct content types, it
|
||||
recognizes the following shorthands:
|
||||
|
||||
@nl
|
||||
$(* $short - @{"`ContentType::"}! @[$name]! @{"`"} @nl)*
|
||||
@nl
|
||||
];
|
||||
/// For regular parsing, use the
|
||||
/// [`ContentType::from_str()`](#impl-FromStr) method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Using a shorthand:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let html = ContentType::parse_flexible("html");
|
||||
/// assert_eq!(html, Some(ContentType::HTML));
|
||||
///
|
||||
/// let json = ContentType::parse_flexible("json");
|
||||
/// assert_eq!(json, Some(ContentType::JSON));
|
||||
/// ```
|
||||
///
|
||||
/// Using the full content-type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let html = ContentType::parse_flexible("text/html; charset=utf-8");
|
||||
/// assert_eq!(html, Some(ContentType::HTML));
|
||||
///
|
||||
/// let json = ContentType::parse_flexible("application/json");
|
||||
/// assert_eq!(json, Some(ContentType::JSON));
|
||||
///
|
||||
/// let custom = ContentType::parse_flexible("application/x+custom");
|
||||
/// assert_eq!(custom, Some(ContentType::new("application", "x+custom")));
|
||||
/// ```
|
||||
///
|
||||
/// An unrecognized content-type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let foo = ContentType::parse_flexible("foo");
|
||||
/// assert_eq!(foo, None);
|
||||
///
|
||||
/// let bar = ContentType::parse_flexible("foo/bar/baz");
|
||||
/// assert_eq!(bar, None);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn parse_flexible(name: &str) -> Option<ContentType> {
|
||||
MediaType::parse_flexible(name).map(ContentType)
|
||||
}
|
||||
);)
|
||||
}
|
||||
|
||||
impl ContentType {
|
||||
|
@ -79,39 +183,9 @@ impl ContentType {
|
|||
ContentType(MediaType::new(top, sub))
|
||||
}
|
||||
|
||||
/// Returns the Content-Type associated with the extension `ext` if the
|
||||
/// extension is recognized. Not all extensions are recognized. If an
|
||||
/// extensions is not recognized, then this method returns `None`. The
|
||||
/// currently recognized extensions are txt, html, htm, xml, csv, js, css,
|
||||
/// json, png, gif, bmp, jpeg, jpg, webp, svg, pdf, ttf, otf, woff, and
|
||||
/// woff2. Extensions are matched case-insensitively.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Recognized content types:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let xml = ContentType::from_extension("xml");
|
||||
/// assert_eq!(xml, Some(ContentType::XML));
|
||||
///
|
||||
/// let xml = ContentType::from_extension("XML");
|
||||
/// assert_eq!(xml, Some(ContentType::XML));
|
||||
/// ```
|
||||
///
|
||||
/// An unrecognized content type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::ContentType;
|
||||
///
|
||||
/// let foo = ContentType::from_extension("foo");
|
||||
/// assert!(foo.is_none());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_extension(ext: &str) -> Option<ContentType> {
|
||||
MediaType::from_extension(ext).map(ContentType)
|
||||
}
|
||||
known_shorthands!(parse_flexible);
|
||||
|
||||
known_extensions!(from_extension);
|
||||
|
||||
/// Creates a new `ContentType` with top-level type `top`, subtype `sub`,
|
||||
/// and parameters `ps`. This should _only_ be used to construct uncommon or
|
||||
|
|
|
@ -5,7 +5,7 @@ macro_rules! known_media_types {
|
|||
HTML (is_html): "HTML", "text", "html" ; "charset" => "utf-8",
|
||||
Plain (is_plain): "plain text", "text", "plain" ; "charset" => "utf-8",
|
||||
JSON (is_json): "JSON", "application", "json",
|
||||
MsgPack (is_msgpack): "MessagePack", "application", "msgpack",
|
||||
MsgPack (is_msgpack): "MsgPack", "application", "msgpack",
|
||||
Form (is_form): "forms", "application", "x-www-form-urlencoded",
|
||||
JavaScript (is_javascript): "JavaScript", "application", "javascript",
|
||||
CSS (is_css): "CSS", "text", "css" ; "charset" => "utf-8",
|
||||
|
@ -51,3 +51,19 @@ macro_rules! known_extensions {
|
|||
"woff2" => WOFF2,
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! known_shorthands {
|
||||
($cont:ident) => ($cont! {
|
||||
"any" => Any,
|
||||
"binary" => Binary,
|
||||
"html" => HTML,
|
||||
"plain" => Plain,
|
||||
"json" => JSON,
|
||||
"msgpack" => MsgPack,
|
||||
"form" => Form,
|
||||
"js" => JavaScript,
|
||||
"css" => CSS,
|
||||
"multipart" => FormData,
|
||||
"xml" => XML,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -106,11 +106,11 @@ macro_rules! media_str {
|
|||
macro_rules! media_types {
|
||||
($($name:ident ($check:ident): $str:expr, $t:expr,
|
||||
$s:expr $(; $k:expr => $v:expr)*,)+) => {
|
||||
$(
|
||||
#[doc="Media type for <b>"] #[doc=$str] #[doc="</b>: <i>"]
|
||||
#[doc=$t] #[doc="/"] #[doc=$s]
|
||||
$(#[doc="; "] #[doc=$k] #[doc=" = "] #[doc=$v])*
|
||||
#[doc="</i>"]
|
||||
$(
|
||||
docify!([
|
||||
Media Type for @{"**"}! @{$str}! @{"**"}!: @{"`"} @{$t}! @[/]! @{$s}!
|
||||
$(; @{$k}! @[=]! @{$v}!)* @{"`"}!.
|
||||
];
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $name: MediaType = MediaType {
|
||||
source: Source::Known(concat!($t, "/", $s, $("; ", $k, "=", $v),*)),
|
||||
|
@ -118,34 +118,48 @@ macro_rules! media_types {
|
|||
sub: media_str!($s),
|
||||
params: MediaParams::Static(&[$((media_str!($k), media_str!($v))),*])
|
||||
};
|
||||
);
|
||||
)+
|
||||
|
||||
#[doc="Returns `true` if `self` is the media type for <b>"]
|
||||
#[doc=$str]
|
||||
#[doc="</b>, "]
|
||||
/// without considering parameters.
|
||||
/// Returns `true` if this MediaType is known to Rocket. In other words,
|
||||
/// returns `true` if there is an associated constant for `self`.
|
||||
pub fn is_known(&self) -> bool {
|
||||
if let Source::Known(_) = self.source {
|
||||
return true;
|
||||
}
|
||||
|
||||
$(if self.$check() { return true })+
|
||||
false
|
||||
}
|
||||
|
||||
$(
|
||||
docify!([
|
||||
Returns @code{true} if the @[top-level] and sublevel types of
|
||||
@code{self} are the same as those of @{"`MediaType::"}! $name
|
||||
@{"`"}!.
|
||||
];
|
||||
#[inline(always)]
|
||||
pub fn $check(&self) -> bool {
|
||||
*self == MediaType::$name
|
||||
}
|
||||
)+
|
||||
|
||||
/// Returns `true` if this MediaType is known to Rocket, that is,
|
||||
/// there is an associated constant for `self`.
|
||||
pub fn is_known(&self) -> bool {
|
||||
$(if self.$check() { return true })+
|
||||
false
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
)+
|
||||
}}
|
||||
|
||||
macro_rules! from_extension {
|
||||
($($ext:expr => $name:ident,)*) => (
|
||||
/// Returns the Media-Type associated with the extension `ext`. Not all
|
||||
/// extensions are recognized. If an extensions is not recognized,
|
||||
/// `None` is returned. The currently recognized extensions are
|
||||
$(#[doc=$ext]#[doc=","])*
|
||||
/// and is likely to grow. Extensions are matched case-insensitively.
|
||||
///
|
||||
docify!([
|
||||
Returns the @[Media-Type] associated with the extension @code{ext}. Not
|
||||
all extensions are recognized. If an extensions is not recognized,
|
||||
@code{None} is returned. The currently recognized extensions are:
|
||||
|
||||
@nl
|
||||
$(* @{$ext} - @{"`MediaType::"}! @[$name]! @{"`"} @nl)*
|
||||
@nl
|
||||
|
||||
This list is likely to grow. Extensions are matched
|
||||
@[case-insensitively.]
|
||||
];
|
||||
/// # Example
|
||||
///
|
||||
/// Recognized media types:
|
||||
|
@ -174,7 +188,70 @@ macro_rules! from_extension {
|
|||
_ => None
|
||||
}
|
||||
}
|
||||
)
|
||||
);)
|
||||
}
|
||||
|
||||
macro_rules! parse_flexible {
|
||||
($($short:expr => $name:ident,)*) => (
|
||||
docify!([
|
||||
Flexibly parses @code{name} into a @code{MediaType}. The parse is
|
||||
@[_flexible_] because, in addition to stricly correct media types, it
|
||||
recognizes the following shorthands:
|
||||
|
||||
@nl
|
||||
$(* $short - @{"`MediaType::"}! @[$name]! @{"`"} @nl)*
|
||||
@nl
|
||||
];
|
||||
/// For regular parsing, use the
|
||||
/// [`MediaType::from_str()`](#impl-FromStr) method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Using a shorthand:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::MediaType;
|
||||
///
|
||||
/// let html = MediaType::parse_flexible("html");
|
||||
/// assert_eq!(html, Some(MediaType::HTML));
|
||||
///
|
||||
/// let json = MediaType::parse_flexible("json");
|
||||
/// assert_eq!(json, Some(MediaType::JSON));
|
||||
/// ```
|
||||
///
|
||||
/// Using the full media type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::MediaType;
|
||||
///
|
||||
/// let html = MediaType::parse_flexible("text/html; charset=utf-8");
|
||||
/// assert_eq!(html, Some(MediaType::HTML));
|
||||
///
|
||||
/// let json = MediaType::parse_flexible("application/json");
|
||||
/// assert_eq!(json, Some(MediaType::JSON));
|
||||
///
|
||||
/// let custom = MediaType::parse_flexible("application/x+custom");
|
||||
/// assert_eq!(custom, Some(MediaType::new("application", "x+custom")));
|
||||
/// ```
|
||||
///
|
||||
/// An unrecognized media type:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::MediaType;
|
||||
///
|
||||
/// let foo = MediaType::parse_flexible("foo");
|
||||
/// assert_eq!(foo, None);
|
||||
///
|
||||
/// let bar = MediaType::parse_flexible("foo/bar/baz");
|
||||
/// assert_eq!(bar, None);
|
||||
/// ```
|
||||
pub fn parse_flexible(name: &str) -> Option<MediaType> {
|
||||
match name {
|
||||
$(x if uncased_eq(x, $short) => Some(MediaType::$name)),*,
|
||||
_ => MediaType::from_str(name).ok(),
|
||||
}
|
||||
}
|
||||
);)
|
||||
}
|
||||
|
||||
impl MediaType {
|
||||
|
@ -240,7 +317,6 @@ impl MediaType {
|
|||
IndexedStr::Concrete(val.into())
|
||||
));
|
||||
|
||||
|
||||
MediaType {
|
||||
source: Source::None,
|
||||
top: IndexedStr::Concrete(top.into()),
|
||||
|
@ -249,6 +325,8 @@ impl MediaType {
|
|||
}
|
||||
}
|
||||
|
||||
known_shorthands!(parse_flexible);
|
||||
|
||||
known_extensions!(from_extension);
|
||||
|
||||
/// Returns the top-level type for this media type. The return type,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![feature(plugin, decl_macro)]
|
||||
#![feature(never_type)]
|
||||
#![feature(try_trait)]
|
||||
#![recursion_limit="256"]
|
||||
|
||||
#![plugin(pear_codegen)]
|
||||
|
||||
|
@ -118,6 +119,7 @@ extern crate isatty;
|
|||
#[cfg(test)] #[macro_use] extern crate lazy_static;
|
||||
|
||||
#[doc(hidden)] #[macro_use] pub mod logger;
|
||||
#[macro_use] mod docify;
|
||||
pub mod local;
|
||||
pub mod http;
|
||||
pub mod request;
|
||||
|
|
|
@ -90,4 +90,3 @@ ctrs! {
|
|||
Css: CSS, "CSS", "text/css",
|
||||
JavaScript: JavaScript, "JavaScript", "application/javascript"
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue