Change syntax for meta items and remove them after use.

This commit is contained in:
Jimmy Cuadra 2017-05-14 17:34:21 -07:00
parent f624e1ff50
commit 24370f3d4c
2 changed files with 109 additions and 46 deletions

View File

@ -1,5 +1,5 @@
use quote::{ToTokens, Tokens}; use quote::{ToTokens, Tokens};
use syn::{Field, Lit, MetaItem}; use syn::{Field, MetaItem, NestedMetaItem};
#[derive(Debug)] #[derive(Debug)]
pub struct Request { pub struct Request {
@ -37,34 +37,56 @@ impl Request {
impl From<Vec<Field>> for Request { impl From<Vec<Field>> for Request {
fn from(fields: Vec<Field>) -> Self { fn from(fields: Vec<Field>) -> Self {
let request_fields = fields.into_iter().map(|field| { let request_fields = fields.into_iter().map(|mut field| {
for attr in field.attrs.clone().iter() { let mut request_field_kind = RequestFieldKind::Body;
match attr.value {
MetaItem::Word(ref ident) => { field.attrs = field.attrs.into_iter().filter(|attr| {
if ident == "query" { let (attr_ident, nested_meta_items) = match attr.value {
return RequestField::Query(field); MetaItem::List(ref attr_ident, ref nested_meta_items) => (attr_ident, nested_meta_items),
} _ => return true,
} };
MetaItem::List(_, _) => {}
MetaItem::NameValue(ref ident, ref lit) => { if attr_ident != "ruma_api" {
if ident == "header" { return true;
if let Lit::Str(ref name, _) = *lit { }
return RequestField::Header(name.clone(), field);
} else { for nested_meta_item in nested_meta_items {
panic!("ruma_api! header attribute expects a string value"); match *nested_meta_item {
} NestedMetaItem::MetaItem(ref meta_item) => {
} else if ident == "path" { match *meta_item {
if let Lit::Str(ref name, _) = *lit { MetaItem::Word(ref ident) => {
return RequestField::Path(name.clone(), field); if ident == "header" {
} else { request_field_kind = RequestFieldKind::Header;
panic!("ruma_api! path attribute expects a string value"); } else if ident == "path" {
request_field_kind = RequestFieldKind::Path;
} else if ident == "query" {
request_field_kind = RequestFieldKind::Query;
} else {
panic!(
"ruma_api! attribute meta item on requests must be: header, path, or query"
);
}
}
_ => panic!(
"ruma_api! attribute meta item on requests cannot be a list or name/value pair"
),
} }
} }
NestedMetaItem::Literal(_) => panic!(
"ruma_api! attribute meta item on requests must be: header, path, or query"
),
} }
} }
}
return RequestField::Body(field); false
}).collect();
match request_field_kind {
RequestFieldKind::Body => RequestField::Body(field),
RequestFieldKind::Header => RequestField::Header(field),
RequestFieldKind::Path => RequestField::Path(field),
RequestFieldKind::Query => RequestField::Query(field),
}
}).collect(); }).collect();
Request { Request {
@ -89,8 +111,8 @@ impl ToTokens for Request {
for request_field in self.fields.iter() { for request_field in self.fields.iter() {
match *request_field { match *request_field {
RequestField::Body(ref field) => field.to_tokens(&mut tokens), RequestField::Body(ref field) => field.to_tokens(&mut tokens),
RequestField::Header(_, ref field) => field.to_tokens(&mut tokens), RequestField::Header(ref field) => field.to_tokens(&mut tokens),
RequestField::Path(_, ref field) => field.to_tokens(&mut tokens), RequestField::Path(ref field) => field.to_tokens(&mut tokens),
RequestField::Query(ref field) => field.to_tokens(&mut tokens), RequestField::Query(ref field) => field.to_tokens(&mut tokens),
} }
@ -128,8 +150,8 @@ impl ToTokens for Request {
#[derive(Debug)] #[derive(Debug)]
pub enum RequestField { pub enum RequestField {
Body(Field), Body(Field),
Header(String, Field), Header(Field),
Path(String, Field), Path(Field),
Query(Field), Query(Field),
} }
@ -142,6 +164,13 @@ impl RequestField {
} }
} }
enum RequestFieldKind {
Body,
Header,
Path,
Query,
}
#[derive(Debug)] #[derive(Debug)]
pub struct RequestBodyFields<'a> { pub struct RequestBodyFields<'a> {
fields: &'a [RequestField], fields: &'a [RequestField],

View File

@ -1,5 +1,5 @@
use quote::{ToTokens, Tokens}; use quote::{ToTokens, Tokens};
use syn::{Field, Lit, MetaItem}; use syn::{Field, MetaItem, NestedMetaItem};
#[derive(Debug)] #[derive(Debug)]
pub struct Response { pub struct Response {
@ -28,14 +28,14 @@ impl Response {
#field_name: response_body.#field_name, #field_name: response_body.#field_name,
}); });
} }
ResponseField::Header(ref name, ref field) => { ResponseField::Header(ref field) => {
let field_name = field.ident.as_ref() let field_name = field.ident.as_ref()
.expect("expected body field to have a name"); .expect("expected body field to have a name");
tokens.append(quote! { tokens.append(quote! {
#field_name: hyper_response.headers() #field_name: hyper_response.headers()
.get_raw(#name) .get_raw(#field_name)
.expect("missing expected request header: {}", #name), .expect("missing expected request header: {}", #field_name),
}); });
} }
} }
@ -47,23 +47,52 @@ impl Response {
impl From<Vec<Field>> for Response { impl From<Vec<Field>> for Response {
fn from(fields: Vec<Field>) -> Self { fn from(fields: Vec<Field>) -> Self {
let response_fields = fields.into_iter().map(|field| { let response_fields = fields.into_iter().map(|mut field| {
for attr in field.attrs.clone().iter() { let mut response_field_kind = ResponseFieldKind::Body;
match attr.value {
MetaItem::Word(_) | MetaItem::List(_, _) => {} field.attrs = field.attrs.into_iter().filter(|attr| {
MetaItem::NameValue(ref ident, ref lit) => { let (attr_ident, nested_meta_items) = match attr.value {
if ident == "header" { MetaItem::List(ref attr_ident, ref nested_meta_items) => {
if let Lit::Str(ref name, _) = *lit { (attr_ident, nested_meta_items)
return ResponseField::Header(name.clone(), field); }
} else { _ => return true,
panic!("ruma_api! header attribute expects a string value"); };
if attr_ident != "ruma_api" {
return true;
}
for nested_meta_item in nested_meta_items {
match *nested_meta_item {
NestedMetaItem::MetaItem(ref meta_item) => {
match *meta_item {
MetaItem::Word(ref ident) => {
if ident == "header" {
response_field_kind = ResponseFieldKind::Header;
} else {
panic!(
"ruma_api! attribute meta item on responses must be: header"
);
}
}
_ => panic!(
"ruma_api! attribute meta item on requests cannot be a list or name/value pair"
),
} }
} }
NestedMetaItem::Literal(_) => panic!(
"ruma_api! attribute meta item on responses must be: header"
),
} }
} }
}
return ResponseField::Body(field); false
}).collect();
match response_field_kind {
ResponseFieldKind::Body => ResponseField::Body(field),
ResponseFieldKind::Header => ResponseField::Header(field),
}
}).collect(); }).collect();
Response { Response {
@ -88,7 +117,7 @@ impl ToTokens for Response {
for response in self.fields.iter() { for response in self.fields.iter() {
match *response { match *response {
ResponseField::Body(ref field) => field.to_tokens(&mut tokens), ResponseField::Body(ref field) => field.to_tokens(&mut tokens),
ResponseField::Header(_, ref field) => field.to_tokens(&mut tokens), ResponseField::Header(ref field) => field.to_tokens(&mut tokens),
} }
tokens.append(","); tokens.append(",");
@ -123,7 +152,7 @@ impl ToTokens for Response {
#[derive(Debug)] #[derive(Debug)]
pub enum ResponseField { pub enum ResponseField {
Body(Field), Body(Field),
Header(String, Field), Header(Field),
} }
impl ResponseField { impl ResponseField {
@ -134,3 +163,8 @@ impl ResponseField {
} }
} }
} }
enum ResponseFieldKind {
Body,
Header,
}