macros: Refactor ResponseField
This commit is contained in:
		
							parent
							
								
									a59a648d04
								
							
						
					
					
						commit
						2dbaf19ded
					
				| @ -64,22 +64,22 @@ impl Response { | |||||||
|     fn has_body_fields(&self) -> bool { |     fn has_body_fields(&self) -> bool { | ||||||
|         self.fields |         self.fields | ||||||
|             .iter() |             .iter() | ||||||
|             .any(|f| matches!(f, ResponseField::Body(_) | &ResponseField::NewtypeBody(_))) |             .any(|f| matches!(&f.kind, ResponseFieldKind::Body | &ResponseFieldKind::NewtypeBody)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Whether or not this request has a single newtype body field.
 |     /// Whether or not this request has a single newtype body field.
 | ||||||
|     fn has_newtype_body(&self) -> bool { |     fn has_newtype_body(&self) -> bool { | ||||||
|         self.fields.iter().any(|f| matches!(f, ResponseField::NewtypeBody(_))) |         self.fields.iter().any(|f| matches!(&f.kind, ResponseFieldKind::NewtypeBody)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Whether or not this request has a single raw body field.
 |     /// Whether or not this request has a single raw body field.
 | ||||||
|     fn has_raw_body(&self) -> bool { |     fn has_raw_body(&self) -> bool { | ||||||
|         self.fields.iter().any(|f| matches!(f, ResponseField::RawBody(_))) |         self.fields.iter().any(|f| matches!(&f.kind, ResponseFieldKind::RawBody)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Whether or not this request has any data in the URL path.
 |     /// Whether or not this request has any data in the URL path.
 | ||||||
|     fn has_header_fields(&self) -> bool { |     fn has_header_fields(&self) -> bool { | ||||||
|         self.fields.iter().any(|f| matches!(f, &ResponseField::Header(..))) |         self.fields.iter().any(|f| matches!(&f.kind, &ResponseFieldKind::Header(_))) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn expand_all(&self) -> TokenStream { |     fn expand_all(&self) -> TokenStream { | ||||||
| @ -127,10 +127,9 @@ impl Response { | |||||||
|             "This macro doesn't support generic types" |             "This macro doesn't support generic types" | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         let newtype_body_fields = self |         let newtype_body_fields = self.fields.iter().filter(|f| { | ||||||
|             .fields |             matches!(&f.kind, ResponseFieldKind::NewtypeBody | ResponseFieldKind::RawBody) | ||||||
|             .iter() |         }); | ||||||
|             .filter(|f| matches!(f, ResponseField::NewtypeBody(_) | ResponseField::RawBody(_))); |  | ||||||
| 
 | 
 | ||||||
|         let has_newtype_body_field = match newtype_body_fields.count() { |         let has_newtype_body_field = match newtype_body_fields.count() { | ||||||
|             0 => false, |             0 => false, | ||||||
| @ -143,7 +142,8 @@ impl Response { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let has_body_fields = self.fields.iter().any(|f| matches!(f, ResponseField::Body(_))); |         let has_body_fields = | ||||||
|  |             self.fields.iter().any(|f| matches!(&f.kind, ResponseFieldKind::Body)); | ||||||
|         if has_newtype_body_field && has_body_fields { |         if has_newtype_body_field && has_body_fields { | ||||||
|             return Err(syn::Error::new_spanned( |             return Err(syn::Error::new_spanned( | ||||||
|                 &self.ident, |                 &self.ident, | ||||||
| @ -155,65 +155,60 @@ impl Response { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// The types of fields that a response can have.
 | /// A field of the response struct.
 | ||||||
| enum ResponseField { | struct ResponseField { | ||||||
|  |     inner: Field, | ||||||
|  |     kind: ResponseFieldKind, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// The kind of a response field.
 | ||||||
|  | enum ResponseFieldKind { | ||||||
|     /// JSON data in the body of the response.
 |     /// JSON data in the body of the response.
 | ||||||
|     Body(Field), |     Body, | ||||||
| 
 | 
 | ||||||
|     /// Data in an HTTP header.
 |     /// Data in an HTTP header.
 | ||||||
|     Header(Field, Ident), |     Header(Ident), | ||||||
| 
 | 
 | ||||||
|     /// A specific data type in the body of the response.
 |     /// A specific data type in the body of the response.
 | ||||||
|     NewtypeBody(Field), |     NewtypeBody, | ||||||
| 
 | 
 | ||||||
|     /// Arbitrary bytes in the body of the response.
 |     /// Arbitrary bytes in the body of the response.
 | ||||||
|     RawBody(Field), |     RawBody, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ResponseField { | impl ResponseField { | ||||||
|     /// Creates a new `ResponseField`.
 |     /// Creates a new `ResponseField`.
 | ||||||
|     fn new(field: Field, kind_attr: Option<ResponseMeta>) -> Self { |     fn new(inner: Field, kind_attr: Option<ResponseMeta>) -> Self { | ||||||
|         if let Some(attr) = kind_attr { |         let kind = match kind_attr { | ||||||
|             match attr { |             Some(ResponseMeta::NewtypeBody) => ResponseFieldKind::NewtypeBody, | ||||||
|                 ResponseMeta::NewtypeBody => ResponseField::NewtypeBody(field), |             Some(ResponseMeta::RawBody) => ResponseFieldKind::RawBody, | ||||||
|                 ResponseMeta::RawBody => ResponseField::RawBody(field), |             Some(ResponseMeta::Header(header)) => ResponseFieldKind::Header(header), | ||||||
|                 ResponseMeta::Header(header) => ResponseField::Header(field, header), |             None => ResponseFieldKind::Body, | ||||||
|             } |         }; | ||||||
|         } else { |  | ||||||
|             ResponseField::Body(field) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /// Gets the inner `Field` value.
 |         Self { inner, kind } | ||||||
|     fn field(&self) -> &Field { |  | ||||||
|         match self { |  | ||||||
|             ResponseField::Body(field) |  | ||||||
|             | ResponseField::Header(field, _) |  | ||||||
|             | ResponseField::NewtypeBody(field) |  | ||||||
|             | ResponseField::RawBody(field) => field, |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Return the contained field if this response field is a body kind.
 |     /// Return the contained field if this response field is a body kind.
 | ||||||
|     fn as_body_field(&self) -> Option<&Field> { |     fn as_body_field(&self) -> Option<&Field> { | ||||||
|         match self { |         match &self.kind { | ||||||
|             ResponseField::Body(field) | ResponseField::NewtypeBody(field) => Some(field), |             ResponseFieldKind::Body | ResponseFieldKind::NewtypeBody => Some(&self.inner), | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Return the contained field if this response field is a raw body kind.
 |     /// Return the contained field if this response field is a raw body kind.
 | ||||||
|     fn as_raw_body_field(&self) -> Option<&Field> { |     fn as_raw_body_field(&self) -> Option<&Field> { | ||||||
|         match self { |         match &self.kind { | ||||||
|             ResponseField::RawBody(field) => Some(field), |             ResponseFieldKind::RawBody => Some(&self.inner), | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Return the contained field and HTTP header ident if this response field is a header kind.
 |     /// Return the contained field and HTTP header ident if this response field is a header kind.
 | ||||||
|     fn as_header_field(&self) -> Option<(&Field, &Ident)> { |     fn as_header_field(&self) -> Option<(&Field, &Ident)> { | ||||||
|         match self { |         match &self.kind { | ||||||
|             ResponseField::Header(field, ident) => Some((field, ident)), |             ResponseFieldKind::Header(ident) => Some((&self.inner, ident)), | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -257,7 +252,7 @@ impl Parse for ResponseField { | |||||||
| 
 | 
 | ||||||
| impl ToTokens for ResponseField { | impl ToTokens for ResponseField { | ||||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { |     fn to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|         self.field().to_tokens(tokens); |         self.inner.to_tokens(tokens); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ use proc_macro2::TokenStream; | |||||||
| use quote::quote; | use quote::quote; | ||||||
| use syn::Type; | use syn::Type; | ||||||
| 
 | 
 | ||||||
| use super::{Response, ResponseField}; | use super::{Response, ResponseFieldKind}; | ||||||
| 
 | 
 | ||||||
| impl Response { | impl Response { | ||||||
|     pub fn expand_incoming(&self, error_ty: &Type, ruma_common: &TokenStream) -> TokenStream { |     pub fn expand_incoming(&self, error_ty: &Type, ruma_common: &TokenStream) -> TokenStream { | ||||||
| @ -38,20 +38,20 @@ impl Response { | |||||||
|             let mut raw_body = None; |             let mut raw_body = None; | ||||||
| 
 | 
 | ||||||
|             for response_field in &self.fields { |             for response_field in &self.fields { | ||||||
|                 let field = response_field.field(); |                 let field = &response_field.inner; | ||||||
|                 let field_name = |                 let field_name = | ||||||
|                     field.ident.as_ref().expect("expected field to have an identifier"); |                     field.ident.as_ref().expect("expected field to have an identifier"); | ||||||
|                 let cfg_attrs = |                 let cfg_attrs = | ||||||
|                     field.attrs.iter().filter(|a| a.path.is_ident("cfg")).collect::<Vec<_>>(); |                     field.attrs.iter().filter(|a| a.path.is_ident("cfg")).collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|                 fields.push(match response_field { |                 fields.push(match &response_field.kind { | ||||||
|                     ResponseField::Body(_) | ResponseField::NewtypeBody(_) => { |                     ResponseFieldKind::Body | ResponseFieldKind::NewtypeBody => { | ||||||
|                         quote! { |                         quote! { | ||||||
|                             #( #cfg_attrs )* |                             #( #cfg_attrs )* | ||||||
|                             #field_name: response_body.#field_name |                             #field_name: response_body.#field_name | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     ResponseField::Header(_, header_name) => { |                     ResponseFieldKind::Header(header_name) => { | ||||||
|                         let optional_header = match &field.ty { |                         let optional_header = match &field.ty { | ||||||
|                             syn::Type::Path(syn::TypePath { |                             syn::Type::Path(syn::TypePath { | ||||||
|                                 path: syn::Path { segments, .. }, |                                 path: syn::Path { segments, .. }, | ||||||
| @ -81,7 +81,7 @@ impl Response { | |||||||
|                     // This field must be instantiated last to avoid `use of move value` error.
 |                     // This field must be instantiated last to avoid `use of move value` error.
 | ||||||
|                     // We are guaranteed only one new body field because of a check in
 |                     // We are guaranteed only one new body field because of a check in
 | ||||||
|                     // `parse_response`.
 |                     // `parse_response`.
 | ||||||
|                     ResponseField::RawBody(_) => { |                     ResponseFieldKind::RawBody => { | ||||||
|                         raw_body = Some(quote! { |                         raw_body = Some(quote! { | ||||||
|                             #( #cfg_attrs )* |                             #( #cfg_attrs )* | ||||||
|                             #field_name: { |                             #field_name: { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user