Fix remaining compiler errors.

This commit is contained in:
Jimmy Cuadra 2018-05-11 08:50:39 -07:00
parent 09e377d68e
commit 8f6bc5af77
4 changed files with 156 additions and 102 deletions

View File

@ -22,43 +22,82 @@ impl From<ExprStruct> for Metadata {
let mut requires_authentication = None;
for field in expr.fields {
let Member::Named(identifier) = field.member;
let identifier = match field.member {
Member::Named(identifier) => identifier,
_ => panic!("expected Member::Named"),
};
match identifier.as_ref() {
"description" => {
let Expr::Lit(expr_lit) = field.expr;
let Lit::Str(lit_str) = expr_lit.lit;
let expr_lit = match field.expr {
Expr::Lit(expr_lit) => expr_lit,
_ => panic!("expected Expr::Lit"),
};
let lit_str = match expr_lit.lit {
Lit::Str(lit_str) => lit_str,
_ => panic!("expected Lit::Str"),
};
description = Some(lit_str.value());
}
"method" => {
let Expr::Path(expr_path) = field.expr;
let expr_path = match field.expr {
Expr::Path(expr_path) => expr_path,
_ => panic!("expected Expr::Path"),
};
let path = expr_path.path;
let segments = path.segments;
if segments.len() != 1 {
panic!("ruma_api! expects a one component path for `metadata` `method`");
}
let pair = segments.first().unwrap(); // safe because we just checked
let Pair::End(method_name) = pair;
let method_name = match pair {
Pair::End(method_name) => method_name,
_ => panic!("expected Pair::End"),
};
method = Some(method_name.ident.to_string());
}
"name" => {
let Expr::Lit(expr_lit) = field.expr;
let Lit::Str(lit_str) = expr_lit.lit;
let expr_lit = match field.expr {
Expr::Lit(expr_lit) => expr_lit,
_ => panic!("expected Expr::Lit"),
};
let lit_str = match expr_lit.lit {
Lit::Str(lit_str) => lit_str,
_ => panic!("expected Lit::Str"),
};
name = Some(lit_str.value());
}
"path" => {
let Expr::Lit(expr_lit) = field.expr;
let Lit::Str(lit_str) = expr_lit.lit;
let expr_lit = match field.expr {
Expr::Lit(expr_lit) => expr_lit,
_ => panic!("expected Expr::Lit"),
};
let lit_str = match expr_lit.lit {
Lit::Str(lit_str) => lit_str,
_ => panic!("expected Lit::Str"),
};
path = Some(lit_str.value());
}
"rate_limited" => {
let Expr::Lit(expr_lit) = field.expr;
let Lit::Bool(lit_bool) = expr_lit.lit;
let expr_lit = match field.expr {
Expr::Lit(expr_lit) => expr_lit,
_ => panic!("expected Expr::Lit"),
};
let lit_bool = match expr_lit.lit {
Lit::Bool(lit_bool) => lit_bool,
_ => panic!("expected Lit::Bool"),
};
rate_limited = Some(lit_bool.value)
}
"requires_authentication" => {
let Expr::Lit(expr_lit) = field.expr;
let Lit::Bool(lit_bool) = expr_lit.lit;
let expr_lit = match field.expr {
Expr::Lit(expr_lit) => expr_lit,
_ => panic!("expected Expr::Lit"),
};
let lit_bool = match expr_lit.lit {
Lit::Bool(lit_bool) => lit_bool,
_ => panic!("expected Lit::Bool"),
};
requires_authentication = Some(lit_bool.value)
}
_ => panic!("ruma_api! metadata included unexpected field"),

View File

@ -1,7 +1,7 @@
use quote::{ToTokens, Tokens};
use syn::punctuated::Pair;
use syn::synom::Synom;
use syn::{Expr, FieldValue, Ident, Meta};
use syn::{Expr, FieldValue, Ident, Member, Meta};
mod metadata;
mod request;
@ -18,7 +18,10 @@ pub fn strip_serde_attrs(field_value: &FieldValue) -> FieldValue {
let meta = attr.interpret_meta()
.expect("ruma_api! could not parse field attributes");
let Meta::List(meta_list) = meta;
let meta_list = match meta {
Meta::List(meta_list) => meta_list,
_ => panic!("expected Meta::List"),
};
if meta_list.ident.as_ref() != "serde" {
return true;
@ -52,13 +55,16 @@ impl From<Vec<Expr>> for Api {
_ => panic!("ruma_api! blocks should use struct syntax"),
};
let segments = expr.path.segments;
let segments = expr.path.segments.clone();
if segments.len() != 1 {
panic!("ruma_api! blocks must be one of: metadata, request, or response");
}
let Pair::End(last_segment) = segments.last().unwrap();
let last_segment = match segments.last().unwrap() {
Pair::End(last_segment) => last_segment,
_ => panic!("expected Pair::End"),
};
match last_segment.ident.as_ref() {
"metadata" => metadata = Some(expr.into()),
@ -138,23 +144,21 @@ impl ToTokens for Api {
};
for segment in path_str[1..].split('/') {
tokens.append(quote! {
tokens.append_all(quote! {
path_segments.push
});
tokens.append("(");
if segment.starts_with(':') {
tokens.append("&request_path.");
tokens.append(&segment[1..]);
tokens.append(".to_string()");
} else {
tokens.append("\"");
tokens.append(segment);
tokens.append("\"");
}
let what_is_this = &segment[1..];
tokens.append(");");
tokens.append_all(quote! {
(&request_path.#what_is_this.to_string());
});
} else {
tokens.append_all(quote! {
("#segment");
});
}
}
tokens
@ -179,7 +183,10 @@ impl ToTokens for Api {
};
let add_body_to_request = if let Some(field) = self.request.newtype_body_field() {
let field_name = field.ident.as_ref().expect("expected body field to have a name");
let field_name = match field.member {
Member::Named(field_name) => field_name,
_ => panic!("expected Member::Named"),
};
quote! {
let request_body = RequestBody(request.#field_name);
@ -201,10 +208,13 @@ impl ToTokens for Api {
};
let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() {
let field_type = &field.ty;
let field_type = match field.expr {
Expr::Path(ref field_type) => field_type,
_ => panic!("expected Expr::Path"),
};
let mut tokens = Tokens::new();
tokens.append(quote! {
tokens.append_all(quote! {
let future_response = hyper_response.body()
.fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| {
bytes.write_all(&chunk)?;
@ -218,13 +228,13 @@ impl ToTokens for Api {
})
});
tokens.append(".and_then(move |response_body| {");
tokens.append_all(".and_then(move |response_body| {".into_tokens());
tokens
} else if self.response.has_body_fields() {
let mut tokens = Tokens::new();
tokens.append(quote! {
tokens.append_all(quote! {
let future_response = hyper_response.body()
.fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| {
bytes.write_all(&chunk)?;
@ -238,23 +248,23 @@ impl ToTokens for Api {
})
});
tokens.append(".and_then(move |response_body| {");
tokens.append_all(".and_then(move |response_body| {".into_tokens());
tokens
} else {
let mut tokens = Tokens::new();
tokens.append(quote! {
tokens.append_all(quote! {
let future_response = ::futures::future::ok(())
});
tokens.append(".and_then(move |_| {");
tokens.append_all(".and_then(move |_| {".into_tokens());
tokens
};
let mut closure_end = Tokens::new();
closure_end.append("});");
closure_end.append_all("});".into_tokens());
let extract_headers = if self.response.has_header_fields() {
quote! {
@ -270,7 +280,7 @@ impl ToTokens for Api {
Tokens::new()
};
tokens.append(quote! {
tokens.append_all(quote! {
#[allow(unused_imports)]
use std::io::Write as _Write;

View File

@ -1,6 +1,6 @@
use quote::{ToTokens, Tokens};
use syn::synom::Synom;
use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Meta, NestedMeta};
use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta};
use api::strip_serde_attrs;
@ -54,9 +54,12 @@ impl Request {
let mut tokens = Tokens::new();
for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
let field_name = field.ident.as_ref().expect("expected body field to have a name");
let field_name = match field.member {
Member::Named(field_name) => field_name,
_ => panic!("expected Member::Named"),
};
tokens.append(quote! {
tokens.append_all(quote! {
#field_name: request.#field_name,
});
}
@ -76,7 +79,10 @@ impl From<ExprStruct> for Request {
let meta = attr.interpret_meta()
.expect("ruma_api! could not parse request field attributes");
let Meta::List(meta_list) = meta;
let meta_list = match meta {
Meta::List(meta_list) => meta_list,
_ => panic!("expected Meta::List"),
};
if meta_list.ident.as_ref() != "ruma_api" {
return true;
@ -132,109 +138,102 @@ impl From<ExprStruct> for Request {
impl ToTokens for Request {
fn to_tokens(&self, mut tokens: &mut Tokens) {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data for a request to this API endpoint.
#[derive(Debug)]
pub struct Request
});
if self.fields.len() == 0 {
tokens.append(";");
tokens.append_all(";".into_tokens());
} else {
tokens.append("{");
tokens.append_all("{".into_tokens());
for request_field in self.fields.iter() {
strip_serde_attrs(request_field.field()).to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
if let Some(newtype_body_field) = self.newtype_body_field() {
let mut field = newtype_body_field.clone();
let expr = field.expr;
field.ident = None;
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the request body.
#[derive(Debug, Serialize)]
struct RequestBody
struct RequestBody(#expr);
});
tokens.append("(");
field.to_tokens(&mut tokens);
tokens.append(");");
} else if self.has_body_fields() {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the request body.
#[derive(Debug, Serialize)]
struct RequestBody
});
tokens.append("{");
tokens.append_all("{".into_tokens());
for request_field in self.fields.iter() {
match *request_field {
RequestField::Body(ref field) => {
field.to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
_ => {}
}
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
if self.has_path_fields() {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the request path.
#[derive(Debug, Serialize)]
struct RequestPath
});
tokens.append("{");
tokens.append_all("{".into_tokens());
for request_field in self.fields.iter() {
match *request_field {
RequestField::Path(ref field) => {
field.to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
_ => {}
}
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
if self.has_query_fields() {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the request's query string.
#[derive(Debug, Serialize)]
struct RequestQuery
});
tokens.append("{");
tokens.append_all("{".into_tokens());
for request_field in self.fields.iter() {
match *request_field {
RequestField::Query(ref field) => {
field.to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
_ => {}
}
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
}
}

View File

@ -1,5 +1,5 @@
use quote::{ToTokens, Tokens};
use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Meta, NestedMeta};
use syn::{Expr, ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta};
use api::strip_serde_attrs;
@ -26,28 +26,38 @@ impl Response {
for response_field in self.fields.iter() {
match *response_field {
ResponseField::Body(ref field) => {
let field_name = field.ident.as_ref()
.expect("expected body field to have a name");
let field_name = match field.member {
Member::Named(field_name) => field_name,
_ => panic!("expected Member::Named"),
};
tokens.append(quote! {
tokens.append_all(quote! {
#field_name: response_body.#field_name,
});
}
ResponseField::Header(ref field) => {
let field_name = field.ident.as_ref()
.expect("expected body field to have a name");
let field_type = &field.ty;
let field_name = match field.member {
Member::Named(field_name) => field_name,
_ => panic!("expected Member::Named"),
};
tokens.append(quote! {
let field_type = match field.expr {
Expr::Path(ref field_type) => field_type,
_ => panic!("expected Expr::Path"),
};
tokens.append_all(quote! {
#field_name: headers.remove::<#field_type>()
.expect("missing expected request header"),
});
}
ResponseField::NewtypeBody(ref field) => {
let field_name = field.ident.as_ref()
.expect("expected body field to have a name");
let field_name = match field.member {
Member::Named(field_name) => field_name,
_ => panic!("expected Member::Named"),
};
tokens.append(quote! {
tokens.append_all(quote! {
#field_name: response_body,
});
}
@ -57,7 +67,7 @@ impl Response {
tokens
}
pub fn newtype_body_field(&self) -> Option<&Field> {
pub fn newtype_body_field(&self) -> Option<&FieldValue> {
for response_field in self.fields.iter() {
match *response_field {
ResponseField::NewtypeBody(ref field) => {
@ -84,7 +94,10 @@ impl From<ExprStruct> for Response {
let meta = attr.interpret_meta()
.expect("ruma_api! could not parse response field attributes");
let Meta::List(meta_list) = meta;
let meta_list = match meta {
Meta::List(meta_list) => meta_list,
_ => panic!("expected Meta::List"),
};
if meta_list.ident.as_ref() != "ruma_api" {
return true;
@ -141,63 +154,56 @@ impl From<ExprStruct> for Response {
impl ToTokens for Response {
fn to_tokens(&self, mut tokens: &mut Tokens) {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the response from this API endpoint.
#[derive(Debug)]
pub struct Response
});
if self.fields.len() == 0 {
tokens.append(";");
tokens.append_all(";".into_tokens());
} else {
tokens.append("{");
tokens.append_all("{".into_tokens());
for response_field in self.fields.iter() {
strip_serde_attrs(response_field.field()).to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
if let Some(newtype_body_field) = self.newtype_body_field() {
let mut field = newtype_body_field.clone();
let expr = field.expr;
field.ident = None;
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the response body.
#[derive(Debug, Deserialize)]
struct ResponseBody
struct ResponseBody(#expr);
});
tokens.append("(");
field.to_tokens(&mut tokens);
tokens.append(");");
} else if self.has_body_fields() {
tokens.append(quote! {
tokens.append_all(quote! {
/// Data in the response body.
#[derive(Debug, Deserialize)]
struct ResponseBody
});
tokens.append("{");
tokens.append_all("{".into_tokens());
for response_field in self.fields.iter() {
match *response_field {
ResponseField::Body(ref field) => {
field.to_tokens(&mut tokens);
tokens.append(",");
tokens.append_all(",".into_tokens());
}
_ => {}
}
}
tokens.append("}");
tokens.append_all("}".into_tokens());
}
}
}