aboutsummaryrefslogtreecommitdiffstats
path: root/askama_shared/src
diff options
context:
space:
mode:
Diffstat (limited to 'askama_shared/src')
-rw-r--r--askama_shared/src/generator.rs89
-rw-r--r--askama_shared/src/input.rs86
-rw-r--r--askama_shared/src/lib.rs2
3 files changed, 70 insertions, 107 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index a1b090d..e4eb9ec 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -81,9 +81,12 @@ fn trait_name_for_path(base: &Option<&Expr>, path: &Path) -> String {
res
}
-fn get_parent_type(ast: &syn::DeriveInput) -> Option<&syn::Ty> {
- match ast.body {
- syn::Body::Struct(ref data) => data.fields().iter().filter_map(|f| {
+fn get_parent_type<'a>(ast: &'a syn::DeriveInput) -> Option<&'a syn::Type> {
+ match ast.data {
+ syn::Data::Struct(syn::DataStruct {
+ fields: syn::Fields::Named(ref fields),
+ ..
+ }) => fields.named.iter().filter_map(|f| {
f.ident.as_ref().and_then(|name| {
if name.as_ref() == "_parent" {
Some(&f.ty)
@@ -180,11 +183,11 @@ impl<'a> Generator<'a> {
}
// Implement `Deref<Parent>` for an inheriting context struct.
- fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Ty) {
+ fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Type) {
self.write_header(state, "::std::ops::Deref", &[]);
let mut tokens = Tokens::new();
parent_type.to_tokens(&mut tokens);
- self.writeln(&format!("type Target = {};", tokens.as_str()));
+ self.writeln(&format!("type Target = {};", tokens));
self.writeln("fn deref(&self) -> &Self::Target {");
self.writeln("&self._parent");
self.writeln("}");
@@ -254,7 +257,7 @@ impl<'a> Generator<'a> {
// Implement Rocket's `Responder`.
fn impl_responder(&mut self, state: &'a State) {
- self.write_header(state, "::askama::rocket::Responder<'r>", &["'r"]);
+ self.write_header(state, "::askama::rocket::Responder<'r>", &[quote!('r)]);
self.writeln("fn respond_to(self, _: &::askama::rocket::Request) \
-> ::askama::rocket::Result<'r> {");
@@ -270,64 +273,22 @@ impl<'a> Generator<'a> {
// Writes header for the `impl` for `TraitFromPathName` or `Template`
// for the given context struct.
- fn write_header(&mut self, state: &'a State, target: &str, extra_anno: &[&str]) {
- let mut full_anno = Tokens::new();
- let mut orig_anno = Tokens::new();
- let need_anno = !state.input.ast.generics.lifetimes.is_empty() ||
- !state.input.ast.generics.ty_params.is_empty() ||
- !extra_anno.is_empty();
- if need_anno {
- full_anno.append("<");
- orig_anno.append("<");
- }
-
- let (mut full_sep, mut orig_sep) = (false, false);
- for lt in &state.input.ast.generics.lifetimes {
- if full_sep {
- full_anno.append(",");
- }
- if orig_sep {
- orig_anno.append(",");
- }
- lt.to_tokens(&mut full_anno);
- lt.to_tokens(&mut orig_anno);
- full_sep = true;
- orig_sep = true;
- }
-
- for anno in extra_anno {
- if full_sep {
- full_anno.append(",");
- }
- full_anno.append(anno);
- full_sep = true;
- }
-
- for param in &state.input.ast.generics.ty_params {
- if full_sep {
- full_anno.append(",");
- }
- if orig_sep {
- orig_anno.append(",");
- }
- let mut impl_param = param.clone();
- impl_param.default = None;
- impl_param.to_tokens(&mut full_anno);
- param.ident.to_tokens(&mut orig_anno);
- full_sep = true;
- orig_sep = true;
- }
-
- if need_anno {
- full_anno.append(">");
- orig_anno.append(">");
- }
-
- let mut where_clause = Tokens::new();
- state.input.ast.generics.where_clause.to_tokens(&mut where_clause);
- self.writeln(&format!("impl{} {} for {}{}{} {{",
- full_anno.as_str(), target, state.input.ast.ident.as_ref(),
- orig_anno.as_str(), where_clause.as_str()));
+ fn write_header(&mut self, state: &'a State, target: &str, vars: &[Tokens]) {
+ let mut generics = state.input.ast.generics.clone();
+ for v in vars.iter() {
+ generics.params.push_value(parse_quote!(#v));
+ }
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let ident = state.input.ast.ident.as_ref();
+ self.writeln(
+ format!(
+ "{} {} for {}{} {{",
+ quote!(impl#impl_generics),
+ target,
+ ident,
+ quote!(#ty_generics #where_clause),
+ ).as_ref(),
+ );
}
/* Helper methods for handling node types */
diff --git a/askama_shared/src/input.rs b/askama_shared/src/input.rs
index 25382cb..e3b64da 100644
--- a/askama_shared/src/input.rs
+++ b/askama_shared/src/input.rs
@@ -1,6 +1,5 @@
use path;
-use std::borrow::Cow;
use std::path::{Path, PathBuf};
use syn;
@@ -8,26 +7,26 @@ use syn;
pub struct TemplateInput<'a> {
pub ast: &'a syn::DeriveInput,
- pub meta: TemplateMeta<'a>,
+ pub meta: TemplateMeta,
pub path: PathBuf,
- pub source: Cow<'a, str>,
+ pub source: String,
}
impl<'a> TemplateInput<'a> {
pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
let meta = TemplateMeta::new(ast);
let (path, source) = match meta.source {
- Source::Source(s) => {
+ Source::Source(ref s) => {
let path = match meta.ext {
- Some(v) => PathBuf::from(format!("_.{}", v)),
+ Some(ref v) => PathBuf::from(format!("_.{}", v)),
None => PathBuf::new(),
};
- (path, Cow::Borrowed(s))
+ (path, s.clone())
},
- Source::Path(s) => {
- let path = path::find_template_from_path(s, None);
+ Source::Path(ref s) => {
+ let path = path::find_template_from_path(&s, None);
let src = path::get_template_source(&path);
- (path, Cow::Owned(src))
+ (path, src)
},
};
TemplateInput { ast, meta, path, source }
@@ -35,16 +34,18 @@ impl<'a> TemplateInput<'a> {
}
// Holds metadata for the template, based on the `template()` attribute.
-pub struct TemplateMeta<'a> {
- source: Source<'a>,
+pub struct TemplateMeta {
+ source: Source,
pub print: Print,
pub escaping: EscapeMode,
- pub ext: Option<&'a str>,
+ pub ext: Option<String>,
}
-impl<'a> TemplateMeta<'a> {
- fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
- let attr = ast.attrs.iter().find(|a| a.name() == "template");
+impl TemplateMeta {
+ fn new(ast: &syn::DeriveInput) -> TemplateMeta {
+ let attr = ast.attrs
+ .iter()
+ .find(|a| a.interpret_meta().unwrap().name() == "template");
if attr.is_none() {
let msg = format!("'template' attribute not found on struct '{}'",
ast.ident.as_ref());
@@ -56,39 +57,39 @@ impl<'a> TemplateMeta<'a> {
let mut print = Print::None;
let mut escaping = None;
let mut ext = None;
- if let syn::MetaItem::List(_, ref inner) = attr.value {
- for nm_item in inner {
- if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
- if let syn::MetaItem::NameValue(ref key, ref val) = *item {
- match key.as_ref() {
- "path" => if let syn::Lit::Str(ref s, _) = *val {
+ if let syn::Meta::List(ref inner) = attr.interpret_meta().unwrap() {
+ for nm_item in inner.nested.iter() {
+ if let syn::NestedMeta::Meta(ref item) = *nm_item {
+ if let syn::Meta::NameValue(ref pair) = *item {
+ match pair.ident.as_ref() {
+ "path" => if let syn::Lit::Str(ref s) = pair.lit {
if source.is_some() {
panic!("must specify 'source' or 'path', not both");
}
- source = Some(Source::Path(s.as_ref()));
+ source = Some(Source::Path(s.value()));
} else {
panic!("template path must be string literal");
},
- "source" => if let syn::Lit::Str(ref s, _) = *val {
+ "source" => if let syn::Lit::Str(ref s) = pair.lit {
if source.is_some() {
panic!("must specify 'source' or 'path', not both");
}
- source = Some(Source::Source(s.as_ref()));
+ source = Some(Source::Source(s.value()));
} else {
panic!("template source must be string literal");
},
- "print" => if let syn::Lit::Str(ref s, _) = *val {
- print = (s.as_ref() as &str).into();
+ "print" => if let syn::Lit::Str(ref s) = pair.lit {
+ print = s.value().into();
} else {
panic!("print value must be string literal");
},
- "escape" => if let syn::Lit::Str(ref s, _) = *val {
- escaping = Some((s.as_ref() as &str).into());
+ "escape" => if let syn::Lit::Str(ref s) = pair.lit {
+ escaping = Some(s.value().into());
} else {
panic!("escape value must be string literal");
},
- "ext" => if let syn::Lit::Str(ref s, _) = *val {
- ext = Some((s.as_ref() as &str).into());
+ "ext" => if let syn::Lit::Str(ref s) = pair.lit {
+ ext = Some(s.value());
} else {
panic!("ext value must be string literal");
},
@@ -113,10 +114,9 @@ impl<'a> TemplateMeta<'a> {
Some(m) => m,
None => {
let ext = match source {
- Source::Path(p) => {
- Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or("")
- },
- Source::Source(_) => ext.unwrap(), // Already panicked if None
+ Source::Path(ref p) =>
+ Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or(""),
+ Source::Source(_) => ext.as_ref().unwrap(), // Already panicked if None
};
if HTML_EXTENSIONS.contains(&ext) {
EscapeMode::Html
@@ -129,9 +129,9 @@ impl<'a> TemplateMeta<'a> {
}
}
-enum Source<'a> {
- Path(&'a str),
- Source(&'a str),
+enum Source {
+ Path(String),
+ Source(String),
}
#[derive(PartialEq)]
@@ -140,10 +140,10 @@ pub enum EscapeMode {
None,
}
-impl<'a> From<&'a str> for EscapeMode {
- fn from(s: &'a str) -> EscapeMode {
+impl From<String> for EscapeMode {
+ fn from(s: String) -> EscapeMode {
use self::EscapeMode::*;
- match s {
+ match s.as_ref() {
"html" => Html,
"none" => None,
v => panic!("invalid value for escape option: {}", v),
@@ -159,10 +159,10 @@ pub enum Print {
None,
}
-impl<'a> From<&'a str> for Print {
- fn from(s: &'a str) -> Print {
+impl From<String> for Print {
+ fn from(s: String) -> Print {
use self::Print::*;
- match s {
+ match s.as_ref() {
"all" => All,
"ast" => Ast,
"code" => Code,
diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs
index 0f46b91..ed2357d 100644
--- a/askama_shared/src/lib.rs
+++ b/askama_shared/src/lib.rs
@@ -2,7 +2,9 @@
extern crate error_chain;
#[macro_use]
extern crate nom;
+#[macro_use]
extern crate quote;
+#[macro_use(parse_quote)]
extern crate syn;
#[cfg(feature = "serde-json")]