Use a custom parser for the raw input.
This commit is contained in:
		
							parent
							
								
									8f6bc5af77
								
							
						
					
					
						commit
						38746660b6
					
				| @ -1,7 +1,5 @@ | |||||||
| use quote::{ToTokens, Tokens}; |  | ||||||
| use syn::punctuated::Pair; | use syn::punctuated::Pair; | ||||||
| use syn::synom::Synom; | use syn::{Expr, FieldValue, Lit, Member}; | ||||||
| use syn::{Expr, ExprStruct, Ident, Lit, Member}; |  | ||||||
| 
 | 
 | ||||||
| pub struct Metadata { | pub struct Metadata { | ||||||
|     pub description: String, |     pub description: String, | ||||||
| @ -12,8 +10,8 @@ pub struct Metadata { | |||||||
|     pub requires_authentication: bool, |     pub requires_authentication: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<ExprStruct> for Metadata { | impl From<Vec<FieldValue>> for Metadata { | ||||||
|     fn from(expr: ExprStruct) -> Self { |     fn from(field_values: Vec<FieldValue>) -> Self { | ||||||
|         let mut description = None; |         let mut description = None; | ||||||
|         let mut method = None; |         let mut method = None; | ||||||
|         let mut name = None; |         let mut name = None; | ||||||
| @ -21,15 +19,15 @@ impl From<ExprStruct> for Metadata { | |||||||
|         let mut rate_limited = None; |         let mut rate_limited = None; | ||||||
|         let mut requires_authentication = None; |         let mut requires_authentication = None; | ||||||
| 
 | 
 | ||||||
|         for field in expr.fields { |         for field_value in field_values { | ||||||
|             let identifier = match field.member { |             let identifier = match field_value.member { | ||||||
|                 Member::Named(identifier) => identifier, |                 Member::Named(identifier) => identifier, | ||||||
|                 _ => panic!("expected Member::Named"), |                 _ => panic!("expected Member::Named"), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             match identifier.as_ref() { |             match identifier.as_ref() { | ||||||
|                 "description" => { |                 "description" => { | ||||||
|                     let expr_lit = match field.expr { |                     let expr_lit = match field_value.expr { | ||||||
|                         Expr::Lit(expr_lit) => expr_lit, |                         Expr::Lit(expr_lit) => expr_lit, | ||||||
|                         _ => panic!("expected Expr::Lit"), |                         _ => panic!("expected Expr::Lit"), | ||||||
|                     }; |                     }; | ||||||
| @ -40,7 +38,7 @@ impl From<ExprStruct> for Metadata { | |||||||
|                     description = Some(lit_str.value()); |                     description = Some(lit_str.value()); | ||||||
|                 } |                 } | ||||||
|                 "method" => { |                 "method" => { | ||||||
|                     let expr_path = match field.expr { |                     let expr_path = match field_value.expr { | ||||||
|                         Expr::Path(expr_path) => expr_path, |                         Expr::Path(expr_path) => expr_path, | ||||||
|                         _ => panic!("expected Expr::Path"), |                         _ => panic!("expected Expr::Path"), | ||||||
|                     }; |                     }; | ||||||
| @ -57,7 +55,7 @@ impl From<ExprStruct> for Metadata { | |||||||
|                     method = Some(method_name.ident.to_string()); |                     method = Some(method_name.ident.to_string()); | ||||||
|                 } |                 } | ||||||
|                 "name" => { |                 "name" => { | ||||||
|                     let expr_lit = match field.expr { |                     let expr_lit = match field_value.expr { | ||||||
|                         Expr::Lit(expr_lit) => expr_lit, |                         Expr::Lit(expr_lit) => expr_lit, | ||||||
|                         _ => panic!("expected Expr::Lit"), |                         _ => panic!("expected Expr::Lit"), | ||||||
|                     }; |                     }; | ||||||
| @ -68,7 +66,7 @@ impl From<ExprStruct> for Metadata { | |||||||
|                     name = Some(lit_str.value()); |                     name = Some(lit_str.value()); | ||||||
|                 } |                 } | ||||||
|                 "path" => { |                 "path" => { | ||||||
|                     let expr_lit = match field.expr { |                     let expr_lit = match field_value.expr { | ||||||
|                         Expr::Lit(expr_lit) => expr_lit, |                         Expr::Lit(expr_lit) => expr_lit, | ||||||
|                         _ => panic!("expected Expr::Lit"), |                         _ => panic!("expected Expr::Lit"), | ||||||
|                     }; |                     }; | ||||||
| @ -79,7 +77,7 @@ impl From<ExprStruct> for Metadata { | |||||||
|                     path = Some(lit_str.value()); |                     path = Some(lit_str.value()); | ||||||
|                 } |                 } | ||||||
|                 "rate_limited" => { |                 "rate_limited" => { | ||||||
|                     let expr_lit = match field.expr { |                     let expr_lit = match field_value.expr { | ||||||
|                         Expr::Lit(expr_lit) => expr_lit, |                         Expr::Lit(expr_lit) => expr_lit, | ||||||
|                         _ => panic!("expected Expr::Lit"), |                         _ => panic!("expected Expr::Lit"), | ||||||
|                     }; |                     }; | ||||||
| @ -90,7 +88,7 @@ impl From<ExprStruct> for Metadata { | |||||||
|                     rate_limited = Some(lit_bool.value) |                     rate_limited = Some(lit_bool.value) | ||||||
|                 } |                 } | ||||||
|                 "requires_authentication" => { |                 "requires_authentication" => { | ||||||
|                     let expr_lit = match field.expr { |                     let expr_lit = match field_value.expr { | ||||||
|                         Expr::Lit(expr_lit) => expr_lit, |                         Expr::Lit(expr_lit) => expr_lit, | ||||||
|                         _ => panic!("expected Expr::Lit"), |                         _ => panic!("expected Expr::Lit"), | ||||||
|                     }; |                     }; | ||||||
|  | |||||||
							
								
								
									
										103
									
								
								src/api/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/api/mod.rs
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | |||||||
| use quote::{ToTokens, Tokens}; | use quote::{ToTokens, Tokens}; | ||||||
| use syn::punctuated::Pair; | use syn::punctuated::Punctuated; | ||||||
| use syn::synom::Synom; | use syn::synom::Synom; | ||||||
| use syn::{Expr, FieldValue, Ident, Member, Meta}; | use syn::{Field, FieldValue, Meta}; | ||||||
| 
 | 
 | ||||||
| mod metadata; | mod metadata; | ||||||
| mod request; | mod request; | ||||||
| @ -11,10 +11,10 @@ use self::metadata::Metadata; | |||||||
| use self::request::Request; | use self::request::Request; | ||||||
| use self::response::Response; | use self::response::Response; | ||||||
| 
 | 
 | ||||||
| pub fn strip_serde_attrs(field_value: &FieldValue) -> FieldValue { | pub fn strip_serde_attrs(field: &Field) -> Field { | ||||||
|     let mut field_value = field_value.clone(); |     let mut field = field.clone(); | ||||||
| 
 | 
 | ||||||
|     field_value.attrs = field_value.attrs.into_iter().filter(|attr| { |     field.attrs = field.attrs.into_iter().filter(|attr| { | ||||||
|         let meta = attr.interpret_meta() |         let meta = attr.interpret_meta() | ||||||
|             .expect("ruma_api! could not parse field attributes"); |             .expect("ruma_api! could not parse field attributes"); | ||||||
| 
 | 
 | ||||||
| @ -30,7 +30,7 @@ pub fn strip_serde_attrs(field_value: &FieldValue) -> FieldValue { | |||||||
|         false |         false | ||||||
|     }).collect(); |     }).collect(); | ||||||
| 
 | 
 | ||||||
|     field_value |     field | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct Api { | pub struct Api { | ||||||
| @ -39,59 +39,13 @@ pub struct Api { | |||||||
|     response: Response, |     response: Response, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<Vec<Expr>> for Api { | impl From<RawApi> for Api { | ||||||
|     fn from(exprs: Vec<Expr>) -> Self { |     fn from(raw_api: RawApi) -> Self { | ||||||
|         if exprs.len() != 3 { |  | ||||||
|             panic!("ruma_api! expects 3 blocks: metadata, request, and response"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let mut metadata = None; |  | ||||||
|         let mut request = None; |  | ||||||
|         let mut response = None; |  | ||||||
| 
 |  | ||||||
|         for expr in exprs { |  | ||||||
|             let expr = match expr { |  | ||||||
|                 Expr::Struct(expr) => expr, |  | ||||||
|                 _ => panic!("ruma_api! blocks should use struct syntax"), |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             let segments = expr.path.segments.clone(); |  | ||||||
| 
 |  | ||||||
|             if segments.len() != 1 { |  | ||||||
|                 panic!("ruma_api! blocks must be one of: metadata, request, or response"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             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()), |  | ||||||
|                 "request" => request = Some(expr.into()), |  | ||||||
|                 "response" => response = Some(expr.into()), |  | ||||||
|                 _ => panic!("ruma_api! blocks must be one of: metadata, request, or response"), |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if metadata.is_none() { |  | ||||||
|             panic!("ruma_api! is missing metadata"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if request.is_none() { |  | ||||||
|             panic!("ruma_api! is missing request"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if response.is_none() { |  | ||||||
|             panic!("ruma_api! is missing response"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         Api { |         Api { | ||||||
|             metadata: metadata.unwrap(), |             metadata: raw_api.metadata.into(), | ||||||
|             request: request.unwrap(), |             request: raw_api.request.into(), | ||||||
|             response: response.unwrap(), |             response: raw_api.response.into(), | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -183,10 +137,7 @@ impl ToTokens for Api { | |||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let add_body_to_request = if let Some(field) = self.request.newtype_body_field() { |         let add_body_to_request = if let Some(field) = self.request.newtype_body_field() { | ||||||
|             let field_name = match field.member { |             let field_name = field.ident.expect("expected field to have an identifier"); | ||||||
|                 Member::Named(field_name) => field_name, |  | ||||||
|                 _ => panic!("expected Member::Named"), |  | ||||||
|             }; |  | ||||||
| 
 | 
 | ||||||
|             quote! { |             quote! { | ||||||
|                 let request_body = RequestBody(request.#field_name); |                 let request_body = RequestBody(request.#field_name); | ||||||
| @ -208,10 +159,8 @@ impl ToTokens for Api { | |||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() { |         let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() { | ||||||
|             let field_type = match field.expr { |             let field_type = &field.ty; | ||||||
|                 Expr::Path(ref field_type) => field_type, | 
 | ||||||
|                 _ => panic!("expected Expr::Path"), |  | ||||||
|             }; |  | ||||||
|             let mut tokens = Tokens::new(); |             let mut tokens = Tokens::new(); | ||||||
| 
 | 
 | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
| @ -362,15 +311,27 @@ impl ToTokens for Api { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct Exprs { | type ParseMetadata = Punctuated<FieldValue, Token![,]>; | ||||||
|     pub inner: Vec<Expr>, | type ParseFields = Punctuated<Field, Token![,]>; | ||||||
|  | 
 | ||||||
|  | pub struct RawApi { | ||||||
|  |     pub metadata: Vec<FieldValue>, | ||||||
|  |     pub request: Vec<Field>, | ||||||
|  |     pub response: Vec<Field>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Synom for Exprs { | impl Synom for RawApi { | ||||||
|     named!(parse -> Self, do_parse!( |     named!(parse -> Self, do_parse!( | ||||||
|         exprs: many0!(syn!(Expr)) >> |         custom_keyword!(metadata) >> | ||||||
|         (Exprs { |         metadata: braces!(ParseMetadata::parse_terminated) >> | ||||||
|             inner: exprs, |         custom_keyword!(request) >> | ||||||
|  |         request: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >> | ||||||
|  |         custom_keyword!(response) >> | ||||||
|  |         response: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >> | ||||||
|  |         (RawApi { | ||||||
|  |             metadata: metadata.1.into_iter().collect(), | ||||||
|  |             request: request.1.into_iter().collect(), | ||||||
|  |             response: response.1.into_iter().collect(), | ||||||
|         }) |         }) | ||||||
|     )); |     )); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| use quote::{ToTokens, Tokens}; | use quote::{ToTokens, Tokens}; | ||||||
| use syn::synom::Synom; | use syn::{Field, Meta, NestedMeta}; | ||||||
| use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta}; |  | ||||||
| 
 | 
 | ||||||
| use api::strip_serde_attrs; | use api::strip_serde_attrs; | ||||||
| 
 | 
 | ||||||
| @ -25,7 +24,7 @@ impl Request { | |||||||
|         self.fields.iter().filter(|field| field.is_path()).count() |         self.fields.iter().filter(|field| field.is_path()).count() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn newtype_body_field(&self) -> Option<&FieldValue> { |     pub fn newtype_body_field(&self) -> Option<&Field> { | ||||||
|         for request_field in self.fields.iter() { |         for request_field in self.fields.iter() { | ||||||
|             match *request_field { |             match *request_field { | ||||||
|                 RequestField::NewtypeBody(ref field) => { |                 RequestField::NewtypeBody(ref field) => { | ||||||
| @ -54,10 +53,7 @@ impl Request { | |||||||
|         let mut tokens = Tokens::new(); |         let mut tokens = Tokens::new(); | ||||||
| 
 | 
 | ||||||
|         for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) { |         for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) { | ||||||
|             let field_name = match field.member { |             let field_name = field.ident.expect("expected field to have an identifier"); | ||||||
|                 Member::Named(field_name) => field_name, |  | ||||||
|                 _ => panic!("expected Member::Named"), |  | ||||||
|             }; |  | ||||||
| 
 | 
 | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
|                 #field_name: request.#field_name, |                 #field_name: request.#field_name, | ||||||
| @ -68,14 +64,14 @@ impl Request { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<ExprStruct> for Request { | impl From<Vec<Field>> for Request { | ||||||
|     fn from(expr: ExprStruct) -> Self { |     fn from(fields: Vec<Field>) -> Self { | ||||||
|         let mut has_newtype_body = false; |         let mut has_newtype_body = false; | ||||||
| 
 | 
 | ||||||
|         let fields = expr.fields.into_iter().map(|mut field_value| { |         let fields = fields.into_iter().map(|mut field| { | ||||||
|             let mut field_kind = RequestFieldKind::Body; |             let mut field_kind = RequestFieldKind::Body; | ||||||
| 
 | 
 | ||||||
|             field_value.attrs = field_value.attrs.into_iter().filter(|attr| { |             field.attrs = field.attrs.into_iter().filter(|attr| { | ||||||
|                 let meta = attr.interpret_meta() |                 let meta = attr.interpret_meta() | ||||||
|                     .expect("ruma_api! could not parse request field attributes"); |                     .expect("ruma_api! could not parse request field attributes"); | ||||||
| 
 | 
 | ||||||
| @ -127,7 +123,7 @@ impl From<ExprStruct> for Request { | |||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             RequestField::new(field_kind, field_value) |             RequestField::new(field_kind, field) | ||||||
|         }).collect(); |         }).collect(); | ||||||
| 
 | 
 | ||||||
|         Request { |         Request { | ||||||
| @ -160,12 +156,12 @@ impl ToTokens for Request { | |||||||
| 
 | 
 | ||||||
|         if let Some(newtype_body_field) = self.newtype_body_field() { |         if let Some(newtype_body_field) = self.newtype_body_field() { | ||||||
|             let mut field = newtype_body_field.clone(); |             let mut field = newtype_body_field.clone(); | ||||||
|             let expr = field.expr; |             let ty = field.ty; | ||||||
| 
 | 
 | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
|                 /// Data in the request body.
 |                 /// Data in the request body.
 | ||||||
|                 #[derive(Debug, Serialize)] |                 #[derive(Debug, Serialize)] | ||||||
|                 struct RequestBody(#expr); |                 struct RequestBody(#ty); | ||||||
|             }); |             }); | ||||||
|         } else if self.has_body_fields() { |         } else if self.has_body_fields() { | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
| @ -239,15 +235,15 @@ impl ToTokens for Request { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub enum RequestField { | pub enum RequestField { | ||||||
|     Body(FieldValue), |     Body(Field), | ||||||
|     Header(FieldValue), |     Header(Field), | ||||||
|     NewtypeBody(FieldValue), |     NewtypeBody(Field), | ||||||
|     Path(FieldValue), |     Path(Field), | ||||||
|     Query(FieldValue), |     Query(Field), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RequestField { | impl RequestField { | ||||||
|     fn new(kind: RequestFieldKind, field: FieldValue) -> RequestField { |     fn new(kind: RequestFieldKind, field: Field) -> RequestField { | ||||||
|         match kind { |         match kind { | ||||||
|             RequestFieldKind::Body => RequestField::Body(field), |             RequestFieldKind::Body => RequestField::Body(field), | ||||||
|             RequestFieldKind::Header => RequestField::Header(field), |             RequestFieldKind::Header => RequestField::Header(field), | ||||||
| @ -279,7 +275,7 @@ impl RequestField { | |||||||
|         self.kind() == RequestFieldKind::Query |         self.kind() == RequestFieldKind::Query | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn field(&self) -> &FieldValue { |     fn field(&self) -> &Field { | ||||||
|         match *self { |         match *self { | ||||||
|             RequestField::Body(ref field) => field, |             RequestField::Body(ref field) => field, | ||||||
|             RequestField::Header(ref field) => field, |             RequestField::Header(ref field) => field, | ||||||
| @ -289,7 +285,7 @@ impl RequestField { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn field_(&self, kind: RequestFieldKind) -> Option<&FieldValue> { |     fn field_(&self, kind: RequestFieldKind) -> Option<&Field> { | ||||||
|         if self.kind() == kind { |         if self.kind() == kind { | ||||||
|             Some(self.field()) |             Some(self.field()) | ||||||
|         } else { |         } else { | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use quote::{ToTokens, Tokens}; | use quote::{ToTokens, Tokens}; | ||||||
| use syn::{Expr, ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta}; | use syn::{Field, Meta, NestedMeta}; | ||||||
| 
 | 
 | ||||||
| use api::strip_serde_attrs; | use api::strip_serde_attrs; | ||||||
| 
 | 
 | ||||||
| @ -26,25 +26,15 @@ impl Response { | |||||||
|         for response_field in self.fields.iter() { |         for response_field in self.fields.iter() { | ||||||
|             match *response_field { |             match *response_field { | ||||||
|                 ResponseField::Body(ref field) => { |                 ResponseField::Body(ref field) => { | ||||||
|                     let field_name = match field.member { |                     let field_name = field.ident.expect("expected field to have an identifier"); | ||||||
|                         Member::Named(field_name) => field_name, |  | ||||||
|                         _ => panic!("expected Member::Named"), |  | ||||||
|                     }; |  | ||||||
| 
 | 
 | ||||||
|                     tokens.append_all(quote! { |                     tokens.append_all(quote! { | ||||||
|                         #field_name: response_body.#field_name, |                         #field_name: response_body.#field_name, | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|                 ResponseField::Header(ref field) => { |                 ResponseField::Header(ref field) => { | ||||||
|                     let field_name = match field.member { |                     let field_name = field.ident.expect("expected field to have an identifier"); | ||||||
|                         Member::Named(field_name) => field_name, |                     let field_type = &field.ty; | ||||||
|                         _ => panic!("expected Member::Named"), |  | ||||||
|                     }; |  | ||||||
| 
 |  | ||||||
|                     let field_type = match field.expr { |  | ||||||
|                         Expr::Path(ref field_type) => field_type, |  | ||||||
|                         _ => panic!("expected Expr::Path"), |  | ||||||
|                     }; |  | ||||||
| 
 | 
 | ||||||
|                     tokens.append_all(quote! { |                     tokens.append_all(quote! { | ||||||
|                         #field_name: headers.remove::<#field_type>() |                         #field_name: headers.remove::<#field_type>() | ||||||
| @ -52,10 +42,7 @@ impl Response { | |||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|                 ResponseField::NewtypeBody(ref field) => { |                 ResponseField::NewtypeBody(ref field) => { | ||||||
|                     let field_name = match field.member { |                     let field_name = field.ident.expect("expected field to have an identifier"); | ||||||
|                         Member::Named(field_name) => field_name, |  | ||||||
|                         _ => panic!("expected Member::Named"), |  | ||||||
|                     }; |  | ||||||
| 
 | 
 | ||||||
|                     tokens.append_all(quote! { |                     tokens.append_all(quote! { | ||||||
|                         #field_name: response_body, |                         #field_name: response_body, | ||||||
| @ -67,7 +54,7 @@ impl Response { | |||||||
|         tokens |         tokens | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn newtype_body_field(&self) -> Option<&FieldValue> { |     pub fn newtype_body_field(&self) -> Option<&Field> { | ||||||
|         for response_field in self.fields.iter() { |         for response_field in self.fields.iter() { | ||||||
|             match *response_field { |             match *response_field { | ||||||
|                 ResponseField::NewtypeBody(ref field) => { |                 ResponseField::NewtypeBody(ref field) => { | ||||||
| @ -83,14 +70,14 @@ impl Response { | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<ExprStruct> for Response { | impl From<Vec<Field>> for Response { | ||||||
|     fn from(expr: ExprStruct) -> Self { |     fn from(fields: Vec<Field>) -> Self { | ||||||
|         let mut has_newtype_body = false; |         let mut has_newtype_body = false; | ||||||
| 
 | 
 | ||||||
|         let fields = expr.fields.into_iter().map(|mut field_value| { |         let fields = fields.into_iter().map(|mut field| { | ||||||
|             let mut field_kind = ResponseFieldKind::Body; |             let mut field_kind = ResponseFieldKind::Body; | ||||||
| 
 | 
 | ||||||
|             field_value.attrs = field_value.attrs.into_iter().filter(|attr| { |             field.attrs = field.attrs.into_iter().filter(|attr| { | ||||||
|                 let meta = attr.interpret_meta() |                 let meta = attr.interpret_meta() | ||||||
|                     .expect("ruma_api! could not parse response field attributes"); |                     .expect("ruma_api! could not parse response field attributes"); | ||||||
| 
 | 
 | ||||||
| @ -138,11 +125,11 @@ impl From<ExprStruct> for Response { | |||||||
|                     if has_newtype_body { |                     if has_newtype_body { | ||||||
|                         panic!("ruma_api! responses cannot have both normal body fields and a newtype body field"); |                         panic!("ruma_api! responses cannot have both normal body fields and a newtype body field"); | ||||||
|                     } else { |                     } else { | ||||||
|                         return ResponseField::Body(field_value); |                         return ResponseField::Body(field); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 ResponseFieldKind::Header => ResponseField::Header(field_value), |                 ResponseFieldKind::Header => ResponseField::Header(field), | ||||||
|                 ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field_value), |                 ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field), | ||||||
|             } |             } | ||||||
|         }).collect(); |         }).collect(); | ||||||
| 
 | 
 | ||||||
| @ -176,12 +163,12 @@ impl ToTokens for Response { | |||||||
| 
 | 
 | ||||||
|         if let Some(newtype_body_field) = self.newtype_body_field() { |         if let Some(newtype_body_field) = self.newtype_body_field() { | ||||||
|             let mut field = newtype_body_field.clone(); |             let mut field = newtype_body_field.clone(); | ||||||
|             let expr = field.expr; |             let ty = field.ty; | ||||||
| 
 | 
 | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
|                 /// Data in the response body.
 |                 /// Data in the response body.
 | ||||||
|                 #[derive(Debug, Deserialize)] |                 #[derive(Debug, Deserialize)] | ||||||
|                 struct ResponseBody(#expr); |                 struct ResponseBody(#ty); | ||||||
|             }); |             }); | ||||||
|         } else if self.has_body_fields() { |         } else if self.has_body_fields() { | ||||||
|             tokens.append_all(quote! { |             tokens.append_all(quote! { | ||||||
| @ -209,13 +196,13 @@ impl ToTokens for Response { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub enum ResponseField { | pub enum ResponseField { | ||||||
|     Body(FieldValue), |     Body(Field), | ||||||
|     Header(FieldValue), |     Header(Field), | ||||||
|     NewtypeBody(FieldValue), |     NewtypeBody(Field), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ResponseField { | impl ResponseField { | ||||||
|     fn field(&self) -> &FieldValue { |     fn field(&self) -> &Field { | ||||||
|         match *self { |         match *self { | ||||||
|             ResponseField::Body(ref field) => field, |             ResponseField::Body(ref field) => field, | ||||||
|             ResponseField::Header(ref field) => field, |             ResponseField::Header(ref field) => field, | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -4,9 +4,8 @@ | |||||||
| //! See the documentation for the `ruma_api!` macro for usage details.
 | //! See the documentation for the `ruma_api!` macro for usage details.
 | ||||||
| 
 | 
 | ||||||
| #![deny(missing_debug_implementations)] | #![deny(missing_debug_implementations)] | ||||||
| #![feature(proc_macro, try_from)] | #![feature(proc_macro)] | ||||||
| #![recursion_limit="256"] | #![recursion_limit="256"] | ||||||
| #![allow(warnings)] |  | ||||||
| 
 | 
 | ||||||
| extern crate proc_macro; | extern crate proc_macro; | ||||||
| #[macro_use] extern crate quote; | #[macro_use] extern crate quote; | ||||||
| @ -14,11 +13,10 @@ extern crate ruma_api; | |||||||
| #[macro_use] extern crate syn; | #[macro_use] extern crate syn; | ||||||
| 
 | 
 | ||||||
| use proc_macro::TokenStream; | use proc_macro::TokenStream; | ||||||
| use std::convert::TryFrom; |  | ||||||
| 
 | 
 | ||||||
| use quote::{ToTokens, Tokens}; | use quote::ToTokens; | ||||||
| 
 | 
 | ||||||
| use api::{Api, Exprs}; | use api::{Api, RawApi}; | ||||||
| 
 | 
 | ||||||
| mod api; | mod api; | ||||||
| 
 | 
 | ||||||
| @ -195,9 +193,9 @@ mod api; | |||||||
| /// ```
 | /// ```
 | ||||||
| #[proc_macro] | #[proc_macro] | ||||||
| pub fn ruma_api(input: TokenStream) -> TokenStream { | pub fn ruma_api(input: TokenStream) -> TokenStream { | ||||||
|     let exprs: Exprs = syn::parse(input).expect("ruma_api! failed to parse input"); |     let raw_api: RawApi = syn::parse(input).expect("ruma_api! failed to parse input"); | ||||||
| 
 | 
 | ||||||
|     let api = Api::from(exprs.inner); |     let api = Api::from(raw_api); | ||||||
| 
 | 
 | ||||||
|     api.into_tokens().into() |     api.into_tokens().into() | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| #![feature(associated_consts, proc_macro, try_from)] | #![feature(associated_consts, proc_macro, try_from)] | ||||||
| 
 | 
 | ||||||
| extern crate futures; | extern crate futures; | ||||||
| extern crate hyper; |  | ||||||
| extern crate ruma_api; | extern crate ruma_api; | ||||||
| extern crate ruma_api_macros; | extern crate ruma_api_macros; | ||||||
| extern crate serde; | extern crate serde; | ||||||
| @ -17,7 +16,7 @@ pub mod some_endpoint { | |||||||
|     ruma_api! { |     ruma_api! { | ||||||
|         metadata { |         metadata { | ||||||
|             description: "Does something.", |             description: "Does something.", | ||||||
|             method: Method::Get, // A `hyper::Method` value. No need to import the name.
 |             method: GET, // An `http::Method` constant. No imports required.
 | ||||||
|             name: "some_endpoint", |             name: "some_endpoint", | ||||||
|             path: "/_matrix/some/endpoint/:baz", |             path: "/_matrix/some/endpoint/:baz", | ||||||
|             rate_limited: false, |             rate_limited: false, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user