aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive/src/input.rs
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2018-06-25 14:19:31 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2018-06-25 14:19:31 +0200
commit4ecd886c6f557eee0446315fd5ad6f132cdca578 (patch)
treeb88aa93a23a3c9c20bb7cafe207731a28ba22100 /askama_derive/src/input.rs
parent9a3c57ac34c3507282828de4ef4f7ebbfb014f81 (diff)
downloadaskama-4ecd886c6f557eee0446315fd5ad6f132cdca578.tar.gz
askama-4ecd886c6f557eee0446315fd5ad6f132cdca578.tar.bz2
askama-4ecd886c6f557eee0446315fd5ad6f132cdca578.zip
Improve attribute handling code for efficiency and robustness
Diffstat (limited to 'askama_derive/src/input.rs')
-rw-r--r--askama_derive/src/input.rs104
1 files changed, 57 insertions, 47 deletions
diff --git a/askama_derive/src/input.rs b/askama_derive/src/input.rs
index afa4226..be9446f 100644
--- a/askama_derive/src/input.rs
+++ b/askama_derive/src/input.rs
@@ -1,3 +1,7 @@
+use proc_macro2::TokenStream;
+
+use quote::ToTokens;
+
use shared::path;
use std::path::{Path, PathBuf};
@@ -16,59 +20,65 @@ pub struct TemplateInput<'a> {
impl<'a> TemplateInput<'a> {
pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
- let attr = ast.attrs
- .iter()
- .find(|a| a.interpret_meta().unwrap().name() == "template");
- if attr.is_none() {
- panic!(format!(
- "'template' attribute not found on struct '{}'",
- ast.ident
- ));
+ let mut meta = None;
+ for attr in &ast.attrs {
+ match attr.interpret_meta() {
+ Some(m) => if m.name() == "template" {
+ meta = Some(m)
+ },
+ None => {
+ let mut tokens = TokenStream::new();
+ attr.to_tokens(&mut tokens);
+ panic!("unable to interpret attribute: {}", tokens)
+ }
+ }
}
- let attr = attr.unwrap();
+ let meta_list = match meta.expect("no attribute 'template' found") {
+ syn::Meta::List(inner) => inner,
+ _ => panic!("attribute 'template' has incorrect type"),
+ };
+
let mut source = None;
let mut print = Print::None;
let mut escaping = None;
let mut ext = None;
- 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.to_string().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.value()));
- } else {
- panic!("template path must be string literal");
- },
- "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.value()));
- } else {
- panic!("template source must be string literal");
- },
- "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) = pair.lit {
- escaping = Some(s.value().into());
- } else {
- panic!("escape value must be string literal");
- },
- "ext" => if let syn::Lit::Str(ref s) = pair.lit {
- ext = Some(s.value());
- } else {
- panic!("ext value must be string literal");
- },
- attr => panic!("unsupported annotation key '{}' found", attr),
- }
+ for nm_item in meta_list.nested {
+ if let syn::NestedMeta::Meta(ref item) = nm_item {
+ if let syn::Meta::NameValue(ref pair) = item {
+ match pair.ident.to_string().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.value()));
+ } else {
+ panic!("template path must be string literal");
+ },
+ "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.value()));
+ } else {
+ panic!("template source must be string literal");
+ },
+ "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) = pair.lit {
+ escaping = Some(s.value().into());
+ } else {
+ panic!("escape value must be string literal");
+ },
+ "ext" => if let syn::Lit::Str(ref s) = pair.lit {
+ ext = Some(s.value());
+ } else {
+ panic!("ext value must be string literal");
+ },
+ attr => panic!("unsupported annotation key '{}' found", attr),
}
}
}