mirror of https://github.com/rwf2/Rocket.git
Initial implementation of typed URIs.
This is a breaking change. All Rocket applications using code generation must now additionally declare usage of the 'decl_macro' feature.
This commit is contained in:
parent
322c02f654
commit
084481a84e
|
@ -16,6 +16,7 @@ plugin = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
||||||
|
ordermap = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use ::{ROUTE_STRUCT_PREFIX, ROUTE_FN_PREFIX, PARAM_PREFIX};
|
use ::{ROUTE_STRUCT_PREFIX, ROUTE_FN_PREFIX, PARAM_PREFIX, URI_INFO_MACRO_PREFIX};
|
||||||
use ::{ROUTE_ATTR, ROUTE_INFO_ATTR};
|
use ::{ROUTE_ATTR, ROUTE_INFO_ATTR};
|
||||||
use parser::{Param, RouteParams};
|
use parser::{Param, RouteParams};
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
use syntax::codemap::{Span, Spanned};
|
use syntax::codemap::{Span, Spanned, dummy_spanned};
|
||||||
use syntax::tokenstream::TokenTree;
|
use syntax::tokenstream::TokenTree;
|
||||||
use syntax::ast::{Arg, Ident, Stmt, Expr, MetaItem, Path};
|
use syntax::ast::{Arg, Ident, Item, Stmt, Expr, MetaItem, Path};
|
||||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||||
use syntax::ext::build::AstBuilder;
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
@ -43,7 +43,8 @@ impl RouteParams {
|
||||||
fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>) {
|
fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>) {
|
||||||
let (fn_span, fn_name) = (self.annotated_fn.span(), self.annotated_fn.ident());
|
let (fn_span, fn_name) = (self.annotated_fn.span(), self.annotated_fn.ident());
|
||||||
ecx.struct_span_err(arg.span, &format!("unused dynamic parameter: `{}`", arg.node))
|
ecx.struct_span_err(arg.span, &format!("unused dynamic parameter: `{}`", arg.node))
|
||||||
.span_note(fn_span, &format!("expected argument named `{}` in `{}`", arg.node, fn_name))
|
.span_note(fn_span, &format!("expected argument named `{}` in `{}` handler",
|
||||||
|
arg.node, fn_name))
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +128,12 @@ impl RouteParams {
|
||||||
// an error/debug message if parsing a parameter fails.
|
// an error/debug message if parsing a parameter fails.
|
||||||
fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt> {
|
fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt> {
|
||||||
let mut fn_param_statements = vec![];
|
let mut fn_param_statements = vec![];
|
||||||
|
let params = Param::parse_many(ecx, self.uri.node.path(), self.uri.span.trim(1))
|
||||||
|
.unwrap_or_else(|mut diag| { diag.emit(); vec![] });
|
||||||
|
|
||||||
// Generate a statement for every declared paramter in the path.
|
// Generate a statement for every declared paramter in the path.
|
||||||
let mut declared_set = HashSet::new();
|
let mut declared_set = HashSet::new();
|
||||||
for (i, param) in self.path_params(ecx).enumerate() {
|
for (i, param) in params.iter().enumerate() {
|
||||||
declared_set.insert(param.ident().name);
|
declared_set.insert(param.ident().name);
|
||||||
let ty = match self.annotated_fn.find_input(¶m.ident().name) {
|
let ty = match self.annotated_fn.find_input(¶m.ident().name) {
|
||||||
Some(arg) => strip_ty_lifetimes(arg.ty.clone()),
|
Some(arg) => strip_ty_lifetimes(arg.ty.clone()),
|
||||||
|
@ -142,7 +145,7 @@ impl RouteParams {
|
||||||
|
|
||||||
// Note: the `None` case shouldn't happen if a route is matched.
|
// Note: the `None` case shouldn't happen if a route is matched.
|
||||||
let ident = param.ident().prepend(PARAM_PREFIX);
|
let ident = param.ident().prepend(PARAM_PREFIX);
|
||||||
let expr = match param {
|
let expr = match *param {
|
||||||
Param::Single(_) => quote_expr!(ecx, match __req.get_param_str($i) {
|
Param::Single(_) => quote_expr!(ecx, match __req.get_param_str($i) {
|
||||||
Some(s) => <$ty as ::rocket::request::FromParam>::from_param(s),
|
Some(s) => <$ty as ::rocket::request::FromParam>::from_param(s),
|
||||||
None => return ::rocket::Outcome::Forward(__data)
|
None => return ::rocket::Outcome::Forward(__data)
|
||||||
|
@ -213,6 +216,49 @@ impl RouteParams {
|
||||||
sep_by_tok(ecx, &args, token::Comma)
|
sep_by_tok(ecx, &args, token::Comma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_uri_macro(&self, ecx: &ExtCtxt) -> P<Item> {
|
||||||
|
let macro_args = parse_as_tokens(ecx, "$($token:tt)*");
|
||||||
|
let macro_exp = parse_as_tokens(ecx, "$($token)*");
|
||||||
|
let macro_name = self.annotated_fn.ident().prepend(URI_INFO_MACRO_PREFIX);
|
||||||
|
|
||||||
|
// What we return if we find an inconsistency throughout.
|
||||||
|
let dummy = quote_item!(ecx, pub macro $macro_name($macro_args) { }).unwrap();
|
||||||
|
|
||||||
|
// Hacky check to see if the user's URI was valid.
|
||||||
|
if self.uri.span == dummy_spanned(()).span {
|
||||||
|
return dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the route uri path and paramters from the uri.
|
||||||
|
let route_path = self.uri.node.to_string();
|
||||||
|
let params = match Param::parse_many(ecx, &route_path, self.uri.span.trim(1)) {
|
||||||
|
Ok(params) => params,
|
||||||
|
Err(mut diag) => {
|
||||||
|
diag.cancel();
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate the list of arguments for the URI.
|
||||||
|
let mut fn_uri_args = vec![];
|
||||||
|
for param in ¶ms {
|
||||||
|
if let Some(arg) = self.annotated_fn.find_input(¶m.ident().name) {
|
||||||
|
let (pat, ty) = (&arg.pat, &arg.ty);
|
||||||
|
fn_uri_args.push(quote_tokens!(ecx, $pat: $ty))
|
||||||
|
} else {
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the call to the internal URI macro with all the info.
|
||||||
|
let args = sep_by_tok(ecx, &fn_uri_args, token::Comma);
|
||||||
|
quote_item!(ecx,
|
||||||
|
pub macro $macro_name($macro_args) {
|
||||||
|
rocket_internal_uri!($route_path, ($args), $macro_exp)
|
||||||
|
}
|
||||||
|
).expect("consistent uri macro item")
|
||||||
|
}
|
||||||
|
|
||||||
fn explode(&self, ecx: &ExtCtxt) -> (InternedString, &str, Path, P<Expr>, P<Expr>) {
|
fn explode(&self, ecx: &ExtCtxt) -> (InternedString, &str, Path, P<Expr>, P<Expr>) {
|
||||||
let name = self.annotated_fn.ident().name.as_str();
|
let name = self.annotated_fn.ident().name.as_str();
|
||||||
let path = &self.uri.node.as_str();
|
let path = &self.uri.node.as_str();
|
||||||
|
@ -242,6 +288,7 @@ fn generic_route_decorator(known_method: Option<Spanned<Method>>,
|
||||||
let query_statement = route.generate_query_statement(ecx);
|
let query_statement = route.generate_query_statement(ecx);
|
||||||
let data_statement = route.generate_data_statement(ecx);
|
let data_statement = route.generate_data_statement(ecx);
|
||||||
let fn_arguments = route.generate_fn_arguments(ecx);
|
let fn_arguments = route.generate_fn_arguments(ecx);
|
||||||
|
let uri_macro = route.generate_uri_macro(ecx);
|
||||||
|
|
||||||
// Generate and emit the wrapping function with the Rocket handler signature.
|
// Generate and emit the wrapping function with the Rocket handler signature.
|
||||||
let user_fn_name = route.annotated_fn.ident();
|
let user_fn_name = route.annotated_fn.ident();
|
||||||
|
@ -288,6 +335,9 @@ fn generic_route_decorator(known_method: Option<Spanned<Method>>,
|
||||||
let route_attr = quote_attr!(ecx, #[$attr_name($struct_name)]);
|
let route_attr = quote_attr!(ecx, #[$attr_name($struct_name)]);
|
||||||
attach_and_emit(&mut output, route_attr, annotated);
|
attach_and_emit(&mut output, route_attr, annotated);
|
||||||
|
|
||||||
|
// Emit the per-route URI macro.
|
||||||
|
emit_item(&mut output, uri_macro);
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,7 @@ extern crate syntax;
|
||||||
extern crate syntax_ext;
|
extern crate syntax_ext;
|
||||||
extern crate rustc_plugin;
|
extern crate rustc_plugin;
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
extern crate ordermap;
|
||||||
|
|
||||||
#[macro_use] mod utils;
|
#[macro_use] mod utils;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
@ -166,6 +167,7 @@ const ROUTE_STRUCT_PREFIX: &'static str = "static_rocket_route_info_for_";
|
||||||
const CATCH_STRUCT_PREFIX: &'static str = "static_rocket_catch_info_for_";
|
const CATCH_STRUCT_PREFIX: &'static str = "static_rocket_catch_info_for_";
|
||||||
const ROUTE_FN_PREFIX: &'static str = "rocket_route_fn_";
|
const ROUTE_FN_PREFIX: &'static str = "rocket_route_fn_";
|
||||||
const CATCH_FN_PREFIX: &'static str = "rocket_catch_fn_";
|
const CATCH_FN_PREFIX: &'static str = "rocket_catch_fn_";
|
||||||
|
const URI_INFO_MACRO_PREFIX: &'static str = "rocket_uri_for_";
|
||||||
|
|
||||||
const ROUTE_ATTR: &'static str = "rocket_route";
|
const ROUTE_ATTR: &'static str = "rocket_route";
|
||||||
const ROUTE_INFO_ATTR: &'static str = "rocket_route_info";
|
const ROUTE_INFO_ATTR: &'static str = "rocket_route_info";
|
||||||
|
@ -188,6 +190,12 @@ macro_rules! register_derives {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! register_macros {
|
||||||
|
($reg:expr, $($n:expr => $f:ident),+) => (
|
||||||
|
$($reg.register_macro($n, macros::$f);)+
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Compiler hook for Rust to register plugins.
|
/// Compiler hook for Rust to register plugins.
|
||||||
#[plugin_registrar]
|
#[plugin_registrar]
|
||||||
pub fn plugin_registrar(reg: &mut Registry) {
|
pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
|
@ -196,8 +204,12 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
::rocket::logger::init(::rocket::config::LoggingLevel::Debug);
|
::rocket::logger::init(::rocket::config::LoggingLevel::Debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
reg.register_macro("routes", macros::routes);
|
register_macros!(reg,
|
||||||
reg.register_macro("errors", macros::errors);
|
"routes" => routes,
|
||||||
|
"errors" => errors,
|
||||||
|
"uri" => uri,
|
||||||
|
"rocket_internal_uri" => uri_internal
|
||||||
|
);
|
||||||
|
|
||||||
register_derives!(reg,
|
register_derives!(reg,
|
||||||
"derive_FromForm" => from_form_derive
|
"derive_FromForm" => from_form_derive
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod uri;
|
||||||
|
|
||||||
use {ROUTE_STRUCT_PREFIX, CATCH_STRUCT_PREFIX};
|
use {ROUTE_STRUCT_PREFIX, CATCH_STRUCT_PREFIX};
|
||||||
use utils::{sep_by_tok, ParserExt, IdentExt};
|
use utils::{sep_by_tok, ParserExt, IdentExt};
|
||||||
|
|
||||||
|
@ -8,26 +10,33 @@ use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacEager};
|
||||||
use syntax::parse::token::Token;
|
use syntax::parse::token::Token;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
pub use self::uri::{uri, uri_internal};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn prefix_path(prefix: &str, path: &mut Path) {
|
||||||
|
let last = path.segments.len() - 1;
|
||||||
|
let last_seg = &mut path.segments[last];
|
||||||
|
last_seg.identifier = last_seg.identifier.prepend(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prefix_paths(prefix: &str, paths: &mut Vec<Path>) {
|
pub fn prefix_paths(prefix: &str, paths: &mut Vec<Path>) {
|
||||||
for p in paths {
|
for p in paths {
|
||||||
let last = p.segments.len() - 1;
|
prefix_path(prefix, p);
|
||||||
let last_seg = &mut p.segments[last];
|
|
||||||
last_seg.identifier = last_seg.identifier.prepend(prefix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefixing_vec_macro<F>(prefix: &str,
|
pub fn prefixing_vec_macro<F>(
|
||||||
|
prefix: &str,
|
||||||
mut to_expr: F,
|
mut to_expr: F,
|
||||||
ecx: &mut ExtCtxt,
|
ecx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
args: &[TokenTree])
|
args: &[TokenTree]) -> Box<MacResult + 'static>
|
||||||
-> Box<MacResult + 'static>
|
where F: FnMut(&ExtCtxt, Path) -> P<Expr>
|
||||||
where F: FnMut(&ExtCtxt, Path) -> P<Expr>
|
|
||||||
{
|
{
|
||||||
let mut parser = ecx.new_parser_from_tts(args);
|
let mut parser = ecx.new_parser_from_tts(args);
|
||||||
let paths = parser.parse_paths();
|
match parser.parse_paths() {
|
||||||
if let Ok(mut paths) = paths {
|
Ok(mut paths) => {
|
||||||
// Prefix each path terminator and build up the P<Expr> for each path.
|
// Prefix each path terminator and build up the P<Expr> for each path.
|
||||||
prefix_paths(prefix, &mut paths);
|
prefix_paths(prefix, &mut paths);
|
||||||
let path_exprs: Vec<P<Expr>> = paths.into_iter()
|
let path_exprs: Vec<P<Expr>> = paths.into_iter()
|
||||||
|
@ -38,10 +47,12 @@ pub fn prefixing_vec_macro<F>(prefix: &str,
|
||||||
let path_list = sep_by_tok(ecx, &path_exprs, Token::Comma);
|
let path_list = sep_by_tok(ecx, &path_exprs, Token::Comma);
|
||||||
let output = quote_expr!(ecx, vec![$path_list]).unwrap();
|
let output = quote_expr!(ecx, vec![$path_list]).unwrap();
|
||||||
MacEager::expr(P(output))
|
MacEager::expr(P(output))
|
||||||
} else {
|
}
|
||||||
paths.unwrap_err().emit();
|
Err(mut e) => {
|
||||||
|
e.emit();
|
||||||
DummyResult::expr(sp)
|
DummyResult::expr(sp)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt_skip]
|
#[rustfmt_skip]
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
extern crate syntax_pos;
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use URI_INFO_MACRO_PREFIX;
|
||||||
|
use super::prefix_path;
|
||||||
|
|
||||||
|
use parser::{UriParams, InternalUriParams, Validation};
|
||||||
|
|
||||||
|
use syntax::codemap::Span;
|
||||||
|
use syntax::ext::base::{DummyResult, ExtCtxt, MacEager, MacResult};
|
||||||
|
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||||
|
use syntax::ast::{self, Ident};
|
||||||
|
use syntax::parse::PResult;
|
||||||
|
use syntax::ext::build::AstBuilder;
|
||||||
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
/// FIXME: Implement `MultiSpan::From<Vec<Span>>`.
|
||||||
|
use self::syntax_pos::MultiSpan as MS;
|
||||||
|
|
||||||
|
pub fn uri(
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
|
sp: Span,
|
||||||
|
args: &[TokenTree],
|
||||||
|
) -> Box<MacResult + 'static> {
|
||||||
|
// Generate the path to the internal macro.
|
||||||
|
let mut parser = ecx.new_parser_from_tts(args);
|
||||||
|
let (_, mut macro_path) = try_parse!(sp, UriParams::parse_prelude(&mut parser));
|
||||||
|
prefix_path(URI_INFO_MACRO_PREFIX, &mut macro_path);
|
||||||
|
|
||||||
|
// It's incredibly important we use `sp` as the Span for the generated code
|
||||||
|
// so that errors from the `internal` call show up on the user's code.
|
||||||
|
let expr = parser.mk_mac_expr(sp,
|
||||||
|
ast::Mac_ {
|
||||||
|
path: macro_path,
|
||||||
|
tts: args.to_vec().into_iter().collect::<TokenStream>().into(),
|
||||||
|
},
|
||||||
|
::syntax::util::ThinVec::new(),
|
||||||
|
);
|
||||||
|
|
||||||
|
MacEager::expr(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_exprs<'a>(
|
||||||
|
ecx: &ExtCtxt<'a>,
|
||||||
|
internal: &InternalUriParams,
|
||||||
|
) -> PResult<'a, Vec<P<ast::Expr>>> {
|
||||||
|
let route_name = &internal.uri_params.route_path;
|
||||||
|
match internal.validate() {
|
||||||
|
Validation::Ok(exprs) => Ok(exprs),
|
||||||
|
Validation::Unnamed(expected, actual) => {
|
||||||
|
let mut diag = ecx.struct_span_err(internal.uri_params.args_span(),
|
||||||
|
&format!("`{}` route uri expects {} but {} supplied",
|
||||||
|
route_name, p!(expected, "parameter"), p!(actual, "was")));
|
||||||
|
|
||||||
|
if expected > 0 {
|
||||||
|
let ps = p!("parameter", expected);
|
||||||
|
diag.note(&format!("expected {}: {}", ps, internal.fn_args_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(diag)
|
||||||
|
}
|
||||||
|
Validation::Named(missing, extra, dup) => {
|
||||||
|
let ps = p!("parameter", internal.fn_args.len());
|
||||||
|
let e = &format!("invalid {} for `{}` route uri", ps, route_name);
|
||||||
|
let mut diag = ecx.struct_span_err(internal.uri_params.args_span(), e);
|
||||||
|
diag.note(&format!("expected {}: {}", ps, internal.fn_args_str()));
|
||||||
|
|
||||||
|
fn join<S: Display, T: Iterator<Item = S>>(iter: T) -> (&'static str, String) {
|
||||||
|
let items: Vec<_> = iter.map(|i| format!("`{}`", i)).collect();
|
||||||
|
(p!("parameter", items.len()), items.join(", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !extra.is_empty() {
|
||||||
|
let (ps, msg) = join(extra.iter().map(|id| id.node));
|
||||||
|
let sp: Vec<_> = extra.iter().map(|ident| ident.span).collect();
|
||||||
|
diag.span_help(MS::from_spans(sp), &format!("unknown {}: {}", ps, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dup.is_empty() {
|
||||||
|
let (ps, msg) = join(dup.iter().map(|id| id.node));
|
||||||
|
let sp: Vec<_> = dup.iter().map(|ident| ident.span).collect();
|
||||||
|
diag.span_help(MS::from_spans(sp), &format!("duplicate {}: {}", ps, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !missing.is_empty() {
|
||||||
|
let (ps, msg) = join(missing.iter());
|
||||||
|
diag.help(&format!("missing {}: {}", ps, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(diag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub fn uri_internal(
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
|
sp: Span,
|
||||||
|
tt: &[TokenTree],
|
||||||
|
) -> Box<MacResult + 'static> {
|
||||||
|
// Parse the internal invocation and the user's URI param expressions.
|
||||||
|
let mut parser = ecx.new_parser_from_tts(tt);
|
||||||
|
let internal = try_parse!(sp, InternalUriParams::parse(ecx, &mut parser));
|
||||||
|
let exprs = try_parse!(sp, extract_exprs(ecx, &internal));
|
||||||
|
|
||||||
|
// Generate the statements to typecheck each parameter. First, the mount.
|
||||||
|
let mut argument_stmts = vec![];
|
||||||
|
let mut format_assign_tokens = vec![];
|
||||||
|
if let Some(mount_point) = internal.uri_params.mount_point {
|
||||||
|
// TODO: Should all expressions, not just string literals, be allowed?
|
||||||
|
// let as_ref = ecx.expr_method_call(span, expr, Ident::from_str("as_ref"), v![]);
|
||||||
|
let mount_string = mount_point.node;
|
||||||
|
argument_stmts.push(ecx.stmt_let_typed(
|
||||||
|
mount_point.span,
|
||||||
|
false,
|
||||||
|
Ident::from_str("mount"),
|
||||||
|
quote_ty!(ecx, &str),
|
||||||
|
quote_expr!(ecx, $mount_string),
|
||||||
|
));
|
||||||
|
|
||||||
|
format_assign_tokens.push(quote_tokens!(ecx, mount = mount,));
|
||||||
|
} else {
|
||||||
|
format_assign_tokens.push(quote_tokens!(ecx, mount = "/",));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the user's parameters.
|
||||||
|
for (i, &(ident, ref ty)) in internal.fn_args.iter().enumerate() {
|
||||||
|
let (span, expr) = (exprs[i].span, exprs[i].clone());
|
||||||
|
let into = ecx.expr_method_call(span, expr, Ident::from_str("into"), vec![]);
|
||||||
|
let stmt = ecx.stmt_let_typed(span, false, ident.node, ty.clone(), into);
|
||||||
|
|
||||||
|
argument_stmts.push(stmt);
|
||||||
|
format_assign_tokens.push(quote_tokens!(ecx,
|
||||||
|
$ident = &$ident as &::rocket::http::uri::UriDisplay,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_path = internal.uri.node.replace('<', "{").replace('>', "}");
|
||||||
|
let route_uri = "{mount}".to_string() + &user_path;
|
||||||
|
MacEager::expr(quote_expr!(ecx, {
|
||||||
|
$argument_stmts
|
||||||
|
::rocket::http::uri::URI::from(format!($route_uri, $format_assign_tokens))
|
||||||
|
}))
|
||||||
|
}
|
|
@ -4,9 +4,11 @@ mod error;
|
||||||
mod param;
|
mod param;
|
||||||
mod function;
|
mod function;
|
||||||
mod uri;
|
mod uri;
|
||||||
|
mod uri_macro;
|
||||||
|
|
||||||
pub use self::keyvalue::KVSpanned;
|
pub use self::keyvalue::KVSpanned;
|
||||||
pub use self::route::RouteParams;
|
pub use self::route::RouteParams;
|
||||||
pub use self::error::ErrorParams;
|
pub use self::error::ErrorParams;
|
||||||
pub use self::param::{Param, ParamIter};
|
pub use self::param::Param;
|
||||||
pub use self::function::Function;
|
pub use self::function::Function;
|
||||||
|
pub use self::uri_macro::{Args, InternalUriParams, UriParams, Validation};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use syntax::ast::Ident;
|
use syntax::ast::Ident;
|
||||||
|
use syntax::codemap::{Span, Spanned};
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
use syntax::codemap::{Span, Spanned, BytePos};
|
use utils::SpanExt;
|
||||||
|
use syntax::parse::PResult;
|
||||||
use utils::span;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Param {
|
pub enum Param {
|
||||||
|
@ -22,64 +22,45 @@ impl Param {
|
||||||
Param::Single(ref ident) | Param::Many(ref ident) => &ident.node,
|
Param::Single(ref ident) | Param::Many(ref ident) => &ident.node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ParamIter<'s, 'a, 'c: 'a> {
|
pub fn parse_many<'a>(
|
||||||
ctxt: &'a ExtCtxt<'c>,
|
ecx: &ExtCtxt<'a>,
|
||||||
span: Span,
|
mut string: &str,
|
||||||
string: &'s str,
|
mut span: Span
|
||||||
}
|
) -> PResult<'a, Vec<Param>> {
|
||||||
|
let err = |sp, msg| { Err(ecx.struct_span_err(sp, msg)) };
|
||||||
impl<'s, 'a, 'c: 'a> ParamIter<'s, 'a, 'c> {
|
|
||||||
pub fn new(c: &'a ExtCtxt<'c>, s: &'s str, p: Span) -> ParamIter<'s, 'a, 'c> {
|
|
||||||
ParamIter { ctxt: c, span: p, string: s }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a, 'c> Iterator for ParamIter<'s, 'a, 'c> {
|
|
||||||
type Item = Param;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Param> {
|
|
||||||
let err = |ecx: &ExtCtxt, sp: Span, msg: &str| {
|
|
||||||
ecx.span_err(sp, msg);
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let mut params = vec![];
|
||||||
|
loop {
|
||||||
// Find the start and end indexes for the next parameter, if any.
|
// Find the start and end indexes for the next parameter, if any.
|
||||||
let (start, end) = match self.string.find('<') {
|
let (start, end) = match string.find('<') {
|
||||||
Some(i) => match self.string.find('>') {
|
Some(i) => match string.find('>') {
|
||||||
Some(j) => (i, j),
|
Some(j) if j > i => (i, j),
|
||||||
None => return err(self.ctxt, self.span, "malformed parameters")
|
Some(_) => return err(span, "malformed parameters"),
|
||||||
|
None => return err(span, "malformed parameters")
|
||||||
},
|
},
|
||||||
_ => return None,
|
_ => return Ok(params)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure we found a valid parameter.
|
// Calculate the parameter's ident and span.
|
||||||
if end <= start {
|
let param_span = span.expand(start, end + 1);
|
||||||
return err(self.ctxt, self.span, "malformed parameters");
|
let full_param = &string[(start + 1)..end];
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the parameter's ident.
|
|
||||||
let full_param = &self.string[(start + 1)..end];
|
|
||||||
let (is_many, param) = if full_param.ends_with("..") {
|
let (is_many, param) = if full_param.ends_with("..") {
|
||||||
(true, &full_param[..(full_param.len() - 2)])
|
(true, &full_param[..(full_param.len() - 2)])
|
||||||
} else {
|
} else {
|
||||||
(false, full_param)
|
(false, full_param)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut param_span = self.span;
|
|
||||||
param_span.lo = self.span.lo + BytePos(start as u32);
|
|
||||||
param_span.hi = self.span.lo + BytePos((end + 1) as u32);
|
|
||||||
|
|
||||||
// Advance the string and span.
|
// Advance the string and span.
|
||||||
self.string = &self.string[(end + 1)..];
|
string = &string[(end + 1)..];
|
||||||
self.span.lo = self.span.lo + BytePos((end + 1) as u32);
|
span = span.trim_left(end + 1);
|
||||||
|
|
||||||
let spanned_ident = span(Ident::from_str(param), param_span);
|
let spanned_ident = param_span.wrap(Ident::from_str(param));
|
||||||
if is_many {
|
if is_many {
|
||||||
Some(Param::Many(spanned_ident))
|
params.push(Param::Many(spanned_ident))
|
||||||
} else {
|
} else {
|
||||||
Some(Param::Single(spanned_ident))
|
params.push(Param::Single(spanned_ident))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use syntax::ext::base::{ExtCtxt, Annotatable};
|
||||||
use syntax::codemap::{Span, Spanned, dummy_spanned};
|
use syntax::codemap::{Span, Spanned, dummy_spanned};
|
||||||
|
|
||||||
use utils::{span, MetaItemExt, SpanExt, is_valid_ident};
|
use utils::{span, MetaItemExt, SpanExt, is_valid_ident};
|
||||||
use super::{Function, ParamIter};
|
use super::Function;
|
||||||
use super::keyvalue::KVSpanned;
|
use super::keyvalue::KVSpanned;
|
||||||
use super::uri::validate_uri;
|
use super::uri::validate_uri;
|
||||||
use rocket::http::{Method, MediaType};
|
use rocket::http::{Method, MediaType};
|
||||||
|
@ -33,12 +33,13 @@ impl RouteParams {
|
||||||
/// Parses the route attribute from the given decorator context. If the
|
/// Parses the route attribute from the given decorator context. If the
|
||||||
/// parse is not successful, this function exits early with the appropriate
|
/// parse is not successful, this function exits early with the appropriate
|
||||||
/// error message to the user.
|
/// error message to the user.
|
||||||
pub fn from(ecx: &mut ExtCtxt,
|
pub fn from(
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
known_method: Option<Spanned<Method>>,
|
known_method: Option<Spanned<Method>>,
|
||||||
meta_item: &MetaItem,
|
meta_item: &MetaItem,
|
||||||
annotated: &Annotatable)
|
annotated: &Annotatable
|
||||||
-> RouteParams {
|
) -> RouteParams {
|
||||||
let function = Function::from(annotated).unwrap_or_else(|item_sp| {
|
let function = Function::from(annotated).unwrap_or_else(|item_sp| {
|
||||||
ecx.span_err(sp, "this attribute can only be used on functions...");
|
ecx.span_err(sp, "this attribute can only be used on functions...");
|
||||||
ecx.span_fatal(item_sp, "...but was applied to the item above.");
|
ecx.span_fatal(item_sp, "...but was applied to the item above.");
|
||||||
|
@ -125,12 +126,6 @@ impl RouteParams {
|
||||||
annotated_fn: function,
|
annotated_fn: function,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_params<'s, 'a, 'c: 'a>(&'s self,
|
|
||||||
ecx: &'a ExtCtxt<'c>)
|
|
||||||
-> ParamIter<'s, 'a, 'c> {
|
|
||||||
ParamIter::new(ecx, self.uri.node.path(), self.uri.span.trim(1))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_method(method: Method) -> bool {
|
fn is_valid_method(method: Method) -> bool {
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
use utils::{self, ParserExt, SpanExt};
|
||||||
|
|
||||||
|
use syntax::codemap::{Spanned, Span};
|
||||||
|
use syntax::ext::base::ExtCtxt;
|
||||||
|
use syntax::symbol::InternedString;
|
||||||
|
use syntax::ast::{self, Expr, Name, Ident, Path};
|
||||||
|
use syntax::parse::PResult;
|
||||||
|
use syntax::parse::token::{DelimToken, Token};
|
||||||
|
use syntax::parse::common::SeqSep;
|
||||||
|
use syntax::parse::parser::{Parser, PathStyle};
|
||||||
|
use syntax::print::pprust::ty_to_string;
|
||||||
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
use ordermap::OrderMap;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Arg {
|
||||||
|
Unnamed(P<Expr>),
|
||||||
|
Named(Spanned<Ident>, P<Expr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Args {
|
||||||
|
Unnamed(Vec<P<Expr>>),
|
||||||
|
Named(Vec<(Spanned<Ident>, P<Expr>)>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UriParams {
|
||||||
|
pub mount_point: Option<Spanned<InternedString>>,
|
||||||
|
pub route_path: Path,
|
||||||
|
pub arguments: Option<Spanned<Args>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InternalUriParams {
|
||||||
|
pub uri: Spanned<String>,
|
||||||
|
pub fn_args: Vec<(Spanned<ast::Ident>, P<ast::Ty>)>,
|
||||||
|
pub uri_params: UriParams,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arg {
|
||||||
|
fn is_named(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Arg::Named(..) => true,
|
||||||
|
Arg::Unnamed(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unnamed(self) -> P<Expr> {
|
||||||
|
match self {
|
||||||
|
Arg::Unnamed(expr) => expr,
|
||||||
|
_ => panic!("Called Arg::unnamed() on an Arg::named!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn named(self) -> (Spanned<Ident>, P<Expr>) {
|
||||||
|
match self {
|
||||||
|
Arg::Named(ident, expr) => (ident, expr),
|
||||||
|
_ => panic!("Called Arg::named() on an Arg::Unnamed!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UriParams {
|
||||||
|
// Parses the mount point, if any, and route identifier.
|
||||||
|
pub fn parse_prelude<'a>(
|
||||||
|
parser: &mut Parser<'a>
|
||||||
|
) -> PResult<'a, (Option<Spanned<InternedString>>, Path)> {
|
||||||
|
// Parse the mount point and suffixing ',', if any.
|
||||||
|
let mount_point = match parser.parse_optional_str() {
|
||||||
|
Some((symbol, _, _)) => {
|
||||||
|
let string = symbol.as_str();
|
||||||
|
let span = parser.prev_span;
|
||||||
|
parser.expect(&Token::Comma)?;
|
||||||
|
Some(span.wrap(string))
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse the route identifier, which must always exist.
|
||||||
|
let route_path = parser.parse_path(PathStyle::Mod)?;
|
||||||
|
Ok((mount_point, route_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Span to use when referring to all of the arguments.
|
||||||
|
pub fn args_span(&self) -> Span {
|
||||||
|
match self.arguments {
|
||||||
|
Some(ref args) => args.span,
|
||||||
|
None => self.route_path.span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse<'a>( ecx: &'a ExtCtxt, parser: &mut Parser<'a>,) -> PResult<'a, UriParams> {
|
||||||
|
// Parse the mount point and suffixing ',', if any.
|
||||||
|
let (mount_point, route_path) = Self::parse_prelude(parser)?;
|
||||||
|
|
||||||
|
// If there are no arguments, finish early.
|
||||||
|
if !parser.eat(&Token::Colon) {
|
||||||
|
parser.expect(&Token::Eof)?;
|
||||||
|
let arguments = None;
|
||||||
|
return Ok(UriParams { mount_point, route_path, arguments, });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse arguments.
|
||||||
|
let mut args_span = parser.span;
|
||||||
|
let comma = SeqSep::trailing_allowed(Token::Comma);
|
||||||
|
let arguments = parser.parse_seq_to_end(&Token::Eof, comma, |parser| {
|
||||||
|
let has_key = parser.look_ahead(1, |token| *token == Token::Eq);
|
||||||
|
|
||||||
|
if has_key {
|
||||||
|
let inner_ident = parser.parse_ident()?;
|
||||||
|
let ident = parser.prev_span.wrap(inner_ident);
|
||||||
|
parser.expect(&Token::Eq)?;
|
||||||
|
|
||||||
|
let expr = parser.parse_expr()?;
|
||||||
|
Ok(Arg::Named(ident, expr))
|
||||||
|
} else {
|
||||||
|
let expr = parser.parse_expr()?;
|
||||||
|
Ok(Arg::Unnamed(expr))
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Set the end of the args_span to be the end of the args.
|
||||||
|
args_span.hi = parser.prev_span.hi;
|
||||||
|
|
||||||
|
// A 'colon' was used but there are no arguments.
|
||||||
|
if arguments.is_empty() {
|
||||||
|
return Err(ecx.struct_span_err(parser.prev_span,
|
||||||
|
"expected argument list after `:`"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that both types of arguments were not used at once.
|
||||||
|
let (mut homogeneous_args, mut prev_named) = (true, None);
|
||||||
|
for arg in arguments.iter() {
|
||||||
|
match prev_named {
|
||||||
|
Some(prev_named) => homogeneous_args = prev_named == arg.is_named(),
|
||||||
|
None => prev_named = Some(arg.is_named()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !homogeneous_args {
|
||||||
|
return Err(ecx.struct_span_err(args_span,
|
||||||
|
"named and unnamed parameters cannot be mixed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the `Args` enum, which properly types one-kind-of-argument-ness.
|
||||||
|
let args = if prev_named.unwrap() {
|
||||||
|
Args::Named(arguments.into_iter().map(|arg| arg.named()).collect())
|
||||||
|
} else {
|
||||||
|
Args::Unnamed(arguments.into_iter().map(|arg| arg.unnamed()).collect())
|
||||||
|
};
|
||||||
|
|
||||||
|
let arguments = Some(args_span.wrap(args));
|
||||||
|
Ok(UriParams { mount_point, route_path, arguments, })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Validation {
|
||||||
|
// Number expected, what we actually got.
|
||||||
|
Unnamed(usize, usize),
|
||||||
|
// (Missing, Extra, Duplicate)
|
||||||
|
Named(Vec<Name>, Vec<Spanned<Ident>>, Vec<Spanned<Ident>>),
|
||||||
|
// Everything is okay.
|
||||||
|
Ok(Vec<P<Expr>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalUriParams {
|
||||||
|
pub fn parse<'a>(
|
||||||
|
ecx: &'a ExtCtxt,
|
||||||
|
parser: &mut Parser<'a>,
|
||||||
|
) -> PResult<'a, InternalUriParams> {
|
||||||
|
let uri_str = parser.parse_str_lit().map(|(s, _)| s.as_str().to_string())?;
|
||||||
|
let uri = parser.prev_span.wrap(uri_str);
|
||||||
|
parser.expect(&Token::Comma)?;
|
||||||
|
|
||||||
|
let start = Token::OpenDelim(DelimToken::Paren);
|
||||||
|
let end = Token::CloseDelim(DelimToken::Paren);
|
||||||
|
let comma = SeqSep::trailing_allowed(Token::Comma);
|
||||||
|
let fn_args = parser
|
||||||
|
.parse_seq(&start, &end, comma, |parser| {
|
||||||
|
let param = parser.parse_ident_inc_pat()?;
|
||||||
|
parser.expect(&Token::Colon)?;
|
||||||
|
let ty = utils::strip_ty_lifetimes(parser.parse_ty()?);
|
||||||
|
Ok((param, ty))
|
||||||
|
})?
|
||||||
|
.node;
|
||||||
|
|
||||||
|
parser.expect(&Token::Comma)?;
|
||||||
|
let uri_params = UriParams::parse(ecx, parser)?;
|
||||||
|
Ok(InternalUriParams { uri, fn_args, uri_params, })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fn_args_str(&self) -> String {
|
||||||
|
self.fn_args.iter()
|
||||||
|
.map(|&(ident, ref ty)| format!("{}: {}", ident.node, ty_to_string(&ty)))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validate(&self) -> Validation {
|
||||||
|
let unnamed = |args: &Vec<P<Expr>>| -> Validation {
|
||||||
|
let (expected, actual) = (self.fn_args.len(), args.len());
|
||||||
|
if expected != actual { Validation::Unnamed(expected, actual) }
|
||||||
|
else { Validation::Ok(args.clone()) }
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.uri_params.arguments {
|
||||||
|
None => unnamed(&vec![]),
|
||||||
|
Some(Spanned { node: Args::Unnamed(ref args), .. }) => unnamed(args),
|
||||||
|
Some(Spanned { node: Args::Named(ref args), .. }) => {
|
||||||
|
let mut params: OrderMap<Name, Option<P<Expr>>> = self.fn_args.iter()
|
||||||
|
.map(|&(ident, _)| (ident.node.name, None))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let (mut extra, mut dup) = (vec![], vec![]);
|
||||||
|
for &(ident, ref expr) in args {
|
||||||
|
match params.get_mut(&ident.node.name) {
|
||||||
|
Some(ref entry) if entry.is_some() => dup.push(ident),
|
||||||
|
Some(entry) => *entry = Some(expr.clone()),
|
||||||
|
None => extra.push(ident),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut missing, mut exprs) = (vec![], vec![]);
|
||||||
|
for (name, expr) in params.into_iter() {
|
||||||
|
match expr {
|
||||||
|
Some(expr) => exprs.push(expr),
|
||||||
|
None => missing.push(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extra.len() + dup.len() + missing.len()) == 0 {
|
||||||
|
Validation::Ok(exprs)
|
||||||
|
} else {
|
||||||
|
Validation::Named(missing, extra, dup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -70,23 +70,11 @@ pub fn attach_and_emit(out: &mut Vec<Annotatable>, attr: Attribute, to: Annotata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! quote_enum {
|
pub fn parse_as_tokens(ecx: &ExtCtxt, string: &str) -> Vec<TokenTree> {
|
||||||
($ecx:expr, $var:expr => $(::$root:ident)+
|
use syntax::parse::parse_stream_from_source_str as parse_stream;
|
||||||
{ $($variant:ident),+ ; $($extra:pat => $result:expr),* }) => ({
|
|
||||||
use syntax::codemap::DUMMY_SP;
|
let stream = parse_stream("<_>".into(), string.into(), ecx.parse_sess, None);
|
||||||
use syntax::ast::Ident;
|
stream.into_trees().collect()
|
||||||
use $(::$root)+::*;
|
|
||||||
let root_idents = vec![$(Ident::from_str(stringify!($root))),+];
|
|
||||||
match $var {
|
|
||||||
$($variant => {
|
|
||||||
let variant = Ident::from_str(stringify!($variant));
|
|
||||||
let mut idents = root_idents.clone();
|
|
||||||
idents.push(variant);
|
|
||||||
$ecx.path_global(DUMMY_SP, idents)
|
|
||||||
})+
|
|
||||||
$($extra => $result),*
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TyLifetimeRemover;
|
pub struct TyLifetimeRemover;
|
||||||
|
@ -140,3 +128,45 @@ pub fn is_valid_ident<S: AsRef<str>>(s: S) -> bool {
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! quote_enum {
|
||||||
|
($ecx:expr, $var:expr => $(::$root:ident)+
|
||||||
|
{ $($variant:ident),+ ; $($extra:pat => $result:expr),* }) => ({
|
||||||
|
use syntax::codemap::DUMMY_SP;
|
||||||
|
use syntax::ast::Ident;
|
||||||
|
use $(::$root)+::*;
|
||||||
|
let root_idents = vec![$(Ident::from_str(stringify!($root))),+];
|
||||||
|
match $var {
|
||||||
|
$($variant => {
|
||||||
|
let variant = Ident::from_str(stringify!($variant));
|
||||||
|
let mut idents = root_idents.clone();
|
||||||
|
idents.push(variant);
|
||||||
|
$ecx.path_global(DUMMY_SP, idents)
|
||||||
|
})+
|
||||||
|
$($extra => $result),*
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! try_parse {
|
||||||
|
($sp:expr, $parse:expr) => (
|
||||||
|
match $parse {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(mut e) => { e.emit(); return DummyResult::expr($sp); }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! p {
|
||||||
|
("parameter", $num:expr) => (
|
||||||
|
if $num == 1 { "parameter" } else { "parameters" }
|
||||||
|
);
|
||||||
|
|
||||||
|
($num:expr, "was") => (
|
||||||
|
if $num == 1 { "1 was".into() } else { format!("{} were", $num) }
|
||||||
|
);
|
||||||
|
|
||||||
|
($num:expr, "parameter") => (
|
||||||
|
if $num == 1 { "1 parameter".into() } else { format!("{} parameters", $num) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
|
use super::SpanExt;
|
||||||
|
|
||||||
use syntax::parse::parser::{PathStyle, Parser};
|
use syntax::parse::parser::{PathStyle, Parser};
|
||||||
use syntax::parse::PResult;
|
use syntax::parse::PResult;
|
||||||
use syntax::ast::Path;
|
use syntax::ast::{self, Path, StrStyle, Ident};
|
||||||
use syntax::parse::token::Token::{Eof, Comma};
|
use syntax::parse::token::Token::{Eof, Comma};
|
||||||
use syntax::parse::common::SeqSep;
|
use syntax::parse::common::SeqSep;
|
||||||
|
use syntax::codemap::Spanned;
|
||||||
|
use syntax::symbol::Symbol;
|
||||||
|
|
||||||
pub trait ParserExt<'a> {
|
pub trait ParserExt<'a> {
|
||||||
|
// Parse a comma-seperated list of paths: `a::b, b::c`.
|
||||||
fn parse_paths(&mut self) -> PResult<'a, Vec<Path>>;
|
fn parse_paths(&mut self) -> PResult<'a, Vec<Path>>;
|
||||||
|
|
||||||
|
// Just like `parse_str` but takes into account interpolated expressions.
|
||||||
|
fn parse_str_lit(&mut self) -> PResult<'a, (Symbol, StrStyle)>;
|
||||||
|
|
||||||
|
// Like `parse_ident` but also looks for an `ident` in a `Pat`.
|
||||||
|
fn parse_ident_inc_pat(&mut self) -> PResult<'a, Spanned<Ident>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParserExt<'a> for Parser<'a> {
|
impl<'a> ParserExt<'a> for Parser<'a> {
|
||||||
|
@ -14,4 +25,36 @@ impl<'a> ParserExt<'a> for Parser<'a> {
|
||||||
SeqSep::trailing_allowed(Comma),
|
SeqSep::trailing_allowed(Comma),
|
||||||
|p| p.parse_path(PathStyle::Mod))
|
|p| p.parse_path(PathStyle::Mod))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_str_lit(&mut self) -> PResult<'a, (Symbol, StrStyle)> {
|
||||||
|
self.parse_str()
|
||||||
|
.or_else(|mut e| {
|
||||||
|
let expr = self.parse_expr().map_err(|i| { e.cancel(); i })?;
|
||||||
|
let string_lit = match expr.node {
|
||||||
|
ast::ExprKind::Lit(ref lit) => match lit.node {
|
||||||
|
ast::LitKind::Str(symbol, style) => (symbol, style),
|
||||||
|
_ => return Err(e)
|
||||||
|
}
|
||||||
|
_ => return Err(e)
|
||||||
|
};
|
||||||
|
|
||||||
|
e.cancel();
|
||||||
|
Ok(string_lit)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ident_inc_pat(&mut self) -> PResult<'a, Spanned<Ident>> {
|
||||||
|
self.parse_ident()
|
||||||
|
.map(|ident| self.prev_span.wrap(ident))
|
||||||
|
.or_else(|mut e| {
|
||||||
|
let pat = self.parse_pat().map_err(|i| { e.cancel(); i })?;
|
||||||
|
let ident = match pat.node {
|
||||||
|
ast::PatKind::Ident(_, ident, _) => ident,
|
||||||
|
_ => return Err(e)
|
||||||
|
};
|
||||||
|
|
||||||
|
e.cancel();
|
||||||
|
Ok(ident)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use syntax::codemap::{Span, BytePos};
|
use syntax::codemap::{Span, Spanned, BytePos};
|
||||||
|
|
||||||
pub trait SpanExt {
|
pub trait SpanExt {
|
||||||
/// Trim the span on the left and right by `length`.
|
/// Trim the span on the left and right by `length`.
|
||||||
|
@ -15,6 +15,12 @@ pub trait SpanExt {
|
||||||
|
|
||||||
// Trim from the left so that the span is `length` in size.
|
// Trim from the left so that the span is `length` in size.
|
||||||
fn shorten_upto(self, length: usize) -> Span;
|
fn shorten_upto(self, length: usize) -> Span;
|
||||||
|
|
||||||
|
// Wrap `T` into a `Spanned<T>` with `self` as the span.
|
||||||
|
fn wrap<T>(self, node: T) -> Spanned<T>;
|
||||||
|
|
||||||
|
/// Expand the span on the left by `left` and right by `right`.
|
||||||
|
fn expand(self, left: usize, right: usize) -> Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpanExt for Span {
|
impl SpanExt for Span {
|
||||||
|
@ -43,4 +49,14 @@ impl SpanExt for Span {
|
||||||
self.hi = self.hi - BytePos(length);
|
self.hi = self.hi - BytePos(length);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wrap<T>(self, node: T) -> Spanned<T> {
|
||||||
|
Spanned { node: node, span: self }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand(mut self, left: usize, right: usize) -> Span {
|
||||||
|
self.lo = self.lo + BytePos(left as u32);
|
||||||
|
self.hi = self.lo + BytePos(right as u32);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[get("a")] //~ ERROR absolute
|
#[get("a")] //~ ERROR absolute
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[get("/a/b/c//d")] //~ ERROR paths cannot contain empty segments
|
#[get("/a/b/c//d")] //~ ERROR paths cannot contain empty segments
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[get("/<name>")] //~ ERROR unused dynamic parameter: `name`
|
#[get("/<name>")] //~ ERROR unused dynamic parameter: `name`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[get("/><")] //~ ERROR malformed
|
#[get("/><")] //~ ERROR malformed
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[get("/<param>")] //~ ERROR unused dynamic parameter: `param`
|
#[get("/<param>")] //~ ERROR unused dynamic parameter: `param`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate crossbeam;
|
extern crate crossbeam;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive, const_fn)]
|
#![feature(plugin, decl_macro, custom_derive, const_fn)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -35,7 +35,7 @@ use yansi::Color::*;
|
||||||
/// declared using the `error` decorator, as follows:
|
/// declared using the `error` decorator, as follows:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(plugin)]
|
/// #![feature(plugin, decl_macro)]
|
||||||
/// #![plugin(rocket_codegen)]
|
/// #![plugin(rocket_codegen)]
|
||||||
///
|
///
|
||||||
/// extern crate rocket;
|
/// extern crate rocket;
|
||||||
|
|
|
@ -156,7 +156,7 @@ impl<'a, S, E> IntoOutcome<S, (Status, E), Data> for Result<S, E> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![allow(unused_attributes)]
|
/// # #![allow(unused_attributes)]
|
||||||
/// # #![allow(unused_variables)]
|
/// # #![allow(unused_variables)]
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #
|
/// #
|
||||||
|
|
|
@ -35,7 +35,7 @@ use http::Header;
|
||||||
/// a handler to retrieve the value of a "message" cookie.
|
/// a handler to retrieve the value of a "message" cookie.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::http::Cookies;
|
/// use rocket::http::Cookies;
|
||||||
|
@ -56,7 +56,7 @@ use http::Header;
|
||||||
/// [private cookie]: /rocket/http/enum.Cookies.html#private-cookies
|
/// [private cookie]: /rocket/http/enum.Cookies.html#private-cookies
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #
|
/// #
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
//! Borrowed and owned string types for absolute URIs.
|
//! Borrowed and owned string types for absolute URIs.
|
||||||
|
|
||||||
use std::convert::From;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::convert::From;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::sync::atomic::{AtomicIsize, Ordering};
|
use std::sync::atomic::{AtomicIsize, Ordering};
|
||||||
|
|
||||||
|
use http::RawStr;
|
||||||
|
|
||||||
use url;
|
use url;
|
||||||
|
|
||||||
/// Index (start, end) into a string, to prevent borrowing.
|
/// Index (start, end) into a string, to prevent borrowing.
|
||||||
|
@ -346,6 +348,45 @@ impl<'a> fmt::Display for URI<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait UriDisplay {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> UriDisplay for T {
|
||||||
|
#[inline(always)]
|
||||||
|
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
<Self as fmt::Display>::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for &'a UriDisplay {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
(**self).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> UriDisplay for &'a RawStr {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", URI::percent_encode((*self).as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> UriDisplay for &'a str {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", URI::percent_encode(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> UriDisplay for String {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", URI::percent_encode(self.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterator over the segments of an absolute URI path. Skips empty segments.
|
/// Iterator over the segments of an absolute URI path. Skips empty segments.
|
||||||
///
|
///
|
||||||
/// ### Examples
|
/// ### Examples
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![feature(conservative_impl_trait)]
|
#![feature(conservative_impl_trait)]
|
||||||
#![feature(drop_types_in_const)]
|
#![feature(drop_types_in_const)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(try_trait)]
|
#![feature(try_trait)]
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
//! Then, add the following to the top of your `main.rs` file:
|
//! Then, add the following to the top of your `main.rs` file:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! #![feature(plugin)]
|
//! #![feature(plugin, decl_macro)]
|
||||||
//! # #![allow(unused_attributes)]
|
//! # #![allow(unused_attributes)]
|
||||||
//! #![plugin(rocket_codegen)]
|
//! #![plugin(rocket_codegen)]
|
||||||
//!
|
//!
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
//! write Rocket applications. Here's a simple example to get you started:
|
//! write Rocket applications. Here's a simple example to get you started:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! #![feature(plugin)]
|
//! #![feature(plugin, decl_macro)]
|
||||||
//! #![plugin(rocket_codegen)]
|
//! #![plugin(rocket_codegen)]
|
||||||
//!
|
//!
|
||||||
//! extern crate rocket;
|
//! extern crate rocket;
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
//! consider the following complete "Hello, world!" application, with testing.
|
//! consider the following complete "Hello, world!" application, with testing.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! #![feature(plugin)]
|
//! #![feature(plugin, decl_macro)]
|
||||||
//! #![plugin(rocket_codegen)]
|
//! #![plugin(rocket_codegen)]
|
||||||
//!
|
//!
|
||||||
//! extern crate rocket;
|
//! extern crate rocket;
|
||||||
|
|
|
@ -49,7 +49,7 @@ use request::form::{FromForm, FormItems};
|
||||||
/// The simplest data structure with a reference into form data looks like this:
|
/// The simplest data structure with a reference into form data looks like this:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
@ -65,7 +65,7 @@ use request::form::{FromForm, FormItems};
|
||||||
/// a string. A handler for this type can be written as:
|
/// a string. A handler for this type can be written as:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![allow(deprecated, unused_attributes)]
|
/// # #![allow(deprecated, unused_attributes)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
@ -91,7 +91,7 @@ use request::form::{FromForm, FormItems};
|
||||||
/// The owned analog of the `UserInput` type above is:
|
/// The owned analog of the `UserInput` type above is:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
@ -105,7 +105,7 @@ use request::form::{FromForm, FormItems};
|
||||||
/// The handler is written similarly:
|
/// The handler is written similarly:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![allow(deprecated, unused_attributes)]
|
/// # #![allow(deprecated, unused_attributes)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
@ -170,7 +170,7 @@ impl<'f, T: FromForm<'f> + 'f> Form<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::Form;
|
/// use rocket::request::Form;
|
||||||
|
@ -198,7 +198,7 @@ impl<'f, T: FromForm<'f> + 'f> Form<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::Form;
|
/// use rocket::request::Form;
|
||||||
|
@ -269,7 +269,7 @@ impl<'f, T: FromForm<'f> + 'static> Form<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::Form;
|
/// use rocket::request::Form;
|
||||||
|
|
|
@ -14,7 +14,7 @@ use request::FormItems;
|
||||||
/// validation.
|
/// validation.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(plugin, custom_derive)]
|
/// #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// #![plugin(rocket_codegen)]
|
/// #![plugin(rocket_codegen)]
|
||||||
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
||||||
///
|
///
|
||||||
|
@ -34,7 +34,7 @@ use request::FormItems;
|
||||||
/// data via the `data` parameter and `Form` type.
|
/// data via the `data` parameter and `Form` type.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
/// # #![allow(deprecated, dead_code, unused_attributes)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl<'f, T: FromForm<'f> + 'f> LenientForm<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::LenientForm;
|
/// use rocket::request::LenientForm;
|
||||||
|
@ -84,7 +84,7 @@ impl<'f, T: FromForm<'f> + 'f> LenientForm<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::LenientForm;
|
/// use rocket::request::LenientForm;
|
||||||
|
@ -114,7 +114,7 @@ impl<'f, T: FromForm<'f> + 'static> LenientForm<'f, T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin, custom_derive)]
|
/// # #![feature(plugin, decl_macro, custom_derive)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::request::LenientForm;
|
/// use rocket::request::LenientForm;
|
||||||
|
|
|
@ -167,7 +167,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
/// `senstive` handler.
|
/// `senstive` handler.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #
|
/// #
|
||||||
|
|
|
@ -20,7 +20,7 @@ use http::RawStr;
|
||||||
/// handler for the dynamic `"/<id>"` path:
|
/// handler for the dynamic `"/<id>"` path:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #[get("/<id>")]
|
/// #[get("/<id>")]
|
||||||
|
@ -56,7 +56,7 @@ use http::RawStr;
|
||||||
/// parameter as follows:
|
/// parameter as follows:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # use rocket::http::RawStr;
|
/// # use rocket::http::RawStr;
|
||||||
|
@ -163,7 +163,7 @@ use http::RawStr;
|
||||||
/// dynamic path segment:
|
/// dynamic path segment:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # use rocket::request::FromParam;
|
/// # use rocket::request::FromParam;
|
||||||
|
|
|
@ -21,7 +21,7 @@ use http::Status;
|
||||||
/// following example does just this:
|
/// following example does just this:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::State;
|
/// use rocket::State;
|
||||||
|
|
|
@ -46,7 +46,7 @@ const FLASH_COOKIE_NAME: &'static str = "_flash";
|
||||||
/// message on both the request and response sides.
|
/// message on both the request and response sides.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// #
|
/// #
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
|
|
|
@ -137,7 +137,7 @@ use request::Request;
|
||||||
/// following `Responder` implementation accomplishes this:
|
/// following `Responder` implementation accomplishes this:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #
|
/// #
|
||||||
|
|
|
@ -448,7 +448,7 @@ impl Rocket {
|
||||||
/// dispatched to the `hi` route.
|
/// dispatched to the `hi` route.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// #
|
/// #
|
||||||
|
@ -514,7 +514,7 @@ impl Rocket {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(plugin)]
|
/// #![feature(plugin, decl_macro)]
|
||||||
/// #![plugin(rocket_codegen)]
|
/// #![plugin(rocket_codegen)]
|
||||||
///
|
///
|
||||||
/// extern crate rocket;
|
/// extern crate rocket;
|
||||||
|
@ -573,7 +573,7 @@ impl Rocket {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::State;
|
/// use rocket::State;
|
||||||
|
@ -609,7 +609,7 @@ impl Rocket {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::Rocket;
|
/// use rocket::Rocket;
|
||||||
|
@ -711,7 +711,7 @@ impl Rocket {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::Rocket;
|
/// use rocket::Rocket;
|
||||||
|
@ -748,7 +748,7 @@ impl Rocket {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin, decl_macro)]
|
||||||
/// # #![plugin(rocket_codegen)]
|
/// # #![plugin(rocket_codegen)]
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// use rocket::Rocket;
|
/// use rocket::Rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin, custom_derive)]
|
#![feature(plugin, decl_macro, custom_derive)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(plugin)]
|
#![feature(plugin, decl_macro)]
|
||||||
#![plugin(rocket_codegen)]
|
#![plugin(rocket_codegen)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue