From a59a648d04e661deaaf5b05da17fec5e168e5f18 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Mon, 26 Sep 2022 15:48:45 +0200 Subject: [PATCH] macros: Refactor RequestField --- crates/ruma-macros/src/api/request.rs | 129 +++++++++--------- .../ruma-macros/src/api/request/incoming.rs | 7 +- .../ruma-macros/src/api/request/outgoing.rs | 7 +- 3 files changed, 67 insertions(+), 76 deletions(-) diff --git a/crates/ruma-macros/src/api/request.rs b/crates/ruma-macros/src/api/request.rs index a6ae1f68..865fe8f3 100644 --- a/crates/ruma-macros/src/api/request.rs +++ b/crates/ruma-macros/src/api/request.rs @@ -30,16 +30,16 @@ pub fn expand_derive_request(input: DeriveInput) -> syn::Result { .into_iter() .map(|f| { let f = RequestField::try_from(f)?; - let ty = &f.field().ty; + let ty = &f.inner.ty; - match &f { - RequestField::Header(..) => collect_lifetime_idents(&mut lifetimes.header, ty), - RequestField::Body(_) => collect_lifetime_idents(&mut lifetimes.body, ty), - RequestField::NewtypeBody(_) => collect_lifetime_idents(&mut lifetimes.body, ty), - RequestField::RawBody(_) => collect_lifetime_idents(&mut lifetimes.body, ty), - RequestField::Path(_) => collect_lifetime_idents(&mut lifetimes.path, ty), - RequestField::Query(_) => collect_lifetime_idents(&mut lifetimes.query, ty), - RequestField::QueryMap(_) => collect_lifetime_idents(&mut lifetimes.query, ty), + match &f.kind { + RequestFieldKind::Header(_) => collect_lifetime_idents(&mut lifetimes.header, ty), + RequestFieldKind::Body => collect_lifetime_idents(&mut lifetimes.body, ty), + RequestFieldKind::NewtypeBody => collect_lifetime_idents(&mut lifetimes.body, ty), + RequestFieldKind::RawBody => collect_lifetime_idents(&mut lifetimes.body, ty), + RequestFieldKind::Path => collect_lifetime_idents(&mut lifetimes.path, ty), + RequestFieldKind::Query => collect_lifetime_idents(&mut lifetimes.query, ty), + RequestFieldKind::QueryMap => collect_lifetime_idents(&mut lifetimes.query, ty), } Ok(f) @@ -119,23 +119,23 @@ impl Request { fn has_body_fields(&self) -> bool { self.fields .iter() - .any(|f| matches!(f, RequestField::Body(_) | RequestField::NewtypeBody(_))) + .any(|f| matches!(&f.kind, RequestFieldKind::Body | RequestFieldKind::NewtypeBody)) } fn has_newtype_body(&self) -> bool { - self.fields.iter().any(|f| matches!(f, RequestField::NewtypeBody(_))) + self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::NewtypeBody)) } fn has_header_fields(&self) -> bool { - self.fields.iter().any(|f| matches!(f, RequestField::Header(..))) + self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Header(_))) } fn has_path_fields(&self) -> bool { - self.fields.iter().any(|f| matches!(f, RequestField::Path(_))) + self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Path)) } fn has_query_fields(&self) -> bool { - self.fields.iter().any(|f| matches!(f, RequestField::Query(_))) + self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Query)) } fn has_lifetimes(&self) -> bool { @@ -145,8 +145,8 @@ impl Request { && self.lifetimes.header.is_empty()) } - fn header_fields(&self) -> impl Iterator { - self.fields.iter().filter(|f| matches!(f, RequestField::Header(..))) + fn header_fields(&self) -> impl Iterator { + self.fields.iter().filter_map(RequestField::as_header_field) } fn path_fields_ordered(&self) -> impl Iterator { @@ -259,8 +259,8 @@ impl Request { self.check_path(&path_fields, self.r0_path.as_ref())?; self.check_path(&path_fields, self.stable_path.as_ref())?; - let newtype_body_fields = self.fields.iter().filter(|field| { - matches!(field, RequestField::NewtypeBody(_) | RequestField::RawBody(_)) + let newtype_body_fields = self.fields.iter().filter(|f| { + matches!(&f.kind, RequestFieldKind::NewtypeBody | RequestFieldKind::RawBody) }); let has_newtype_body_field = match newtype_body_fields.count() { @@ -275,7 +275,7 @@ impl Request { }; let query_map_fields = - self.fields.iter().filter(|f| matches!(f, RequestField::QueryMap(_))); + self.fields.iter().filter(|f| matches!(&f.kind, RequestFieldKind::QueryMap)); let has_query_map_field = match query_map_fields.count() { 0 => false, 1 => true, @@ -287,8 +287,9 @@ impl Request { } }; - let has_body_fields = self.fields.iter().any(|f| matches!(f, RequestField::Body(_))); - let has_query_fields = self.fields.iter().any(|f| matches!(f, RequestField::Query(_))); + let has_body_fields = self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Body)); + let has_query_fields = + self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Query)); if has_newtype_body_field && has_body_fields { return Err(syn::Error::new_spanned( @@ -365,97 +366,97 @@ impl Request { } } -/// The types of fields that a request can have. -enum RequestField { +/// A field of the request struct. +struct RequestField { + inner: Field, + kind: RequestFieldKind, +} + +/// The kind of a request field. +enum RequestFieldKind { /// JSON data in the body of the request. - Body(Field), + Body, /// Data in an HTTP header. - Header(Field, Ident), + Header(Ident), /// A specific data type in the body of the request. - NewtypeBody(Field), + NewtypeBody, /// Arbitrary bytes in the body of the request. - RawBody(Field), + RawBody, /// Data that appears in the URL path. - Path(Field), + Path, /// Data that appears in the query string. - Query(Field), + Query, /// Data that appears in the query string as dynamic key-value pairs. - QueryMap(Field), + QueryMap, } impl RequestField { /// Creates a new `RequestField`. - fn new(field: Field, kind_attr: Option) -> Self { - if let Some(attr) = kind_attr { - match attr { - RequestMeta::NewtypeBody => RequestField::NewtypeBody(field), - RequestMeta::RawBody => RequestField::RawBody(field), - RequestMeta::Path => RequestField::Path(field), - RequestMeta::Query => RequestField::Query(field), - RequestMeta::QueryMap => RequestField::QueryMap(field), - RequestMeta::Header(header) => RequestField::Header(field, header), - } - } else { - RequestField::Body(field) - } + fn new(inner: Field, kind_attr: Option) -> Self { + let kind = match kind_attr { + Some(RequestMeta::NewtypeBody) => RequestFieldKind::NewtypeBody, + Some(RequestMeta::RawBody) => RequestFieldKind::RawBody, + Some(RequestMeta::Path) => RequestFieldKind::Path, + Some(RequestMeta::Query) => RequestFieldKind::Query, + Some(RequestMeta::QueryMap) => RequestFieldKind::QueryMap, + Some(RequestMeta::Header(header)) => RequestFieldKind::Header(header), + None => RequestFieldKind::Body, + }; + + Self { inner, kind } } /// Return the contained field if this request field is a body kind. pub fn as_body_field(&self) -> Option<&Field> { - match self { - RequestField::Body(field) | RequestField::NewtypeBody(field) => Some(field), + match &self.kind { + RequestFieldKind::Body | RequestFieldKind::NewtypeBody => Some(&self.inner), _ => None, } } /// Return the contained field if this request field is a raw body kind. pub fn as_raw_body_field(&self) -> Option<&Field> { - match self { - RequestField::RawBody(field) => Some(field), + match &self.kind { + RequestFieldKind::RawBody => Some(&self.inner), _ => None, } } /// Return the contained field if this request field is a path kind. pub fn as_path_field(&self) -> Option<&Field> { - match self { - RequestField::Path(field) => Some(field), + match &self.kind { + RequestFieldKind::Path => Some(&self.inner), _ => None, } } /// Return the contained field if this request field is a query kind. pub fn as_query_field(&self) -> Option<&Field> { - match self { - RequestField::Query(field) => Some(field), + match &self.kind { + RequestFieldKind::Query => Some(&self.inner), _ => None, } } /// Return the contained field if this request field is a query map kind. pub fn as_query_map_field(&self) -> Option<&Field> { - match self { - RequestField::QueryMap(field) => Some(field), + match &self.kind { + RequestFieldKind::QueryMap => Some(&self.inner), _ => None, } } - /// Gets the inner `Field` value. - pub fn field(&self) -> &Field { - match self { - RequestField::Body(field) - | RequestField::Header(field, _) - | RequestField::NewtypeBody(field) - | RequestField::RawBody(field) - | RequestField::Path(field) - | RequestField::Query(field) - | RequestField::QueryMap(field) => field, + /// Return the contained field and header ident if this request field is a header kind. + pub fn as_header_field(&self) -> Option<(&Field, &Ident)> { + match &self.kind { + RequestFieldKind::Header(header_name) => Some((&self.inner, header_name)), + _ => None, } } } @@ -491,6 +492,6 @@ impl Parse for RequestField { impl ToTokens for RequestField { fn to_tokens(&self, tokens: &mut TokenStream) { - self.field().to_tokens(tokens); + self.inner.to_tokens(tokens); } } diff --git a/crates/ruma-macros/src/api/request/incoming.rs b/crates/ruma-macros/src/api/request/incoming.rs index 2204c76f..5c406bdf 100644 --- a/crates/ruma-macros/src/api/request/incoming.rs +++ b/crates/ruma-macros/src/api/request/incoming.rs @@ -86,12 +86,7 @@ impl Request { let (parse_headers, header_vars) = if self.has_header_fields() { let (decls, names): (TokenStream, Vec<_>) = self .header_fields() - .map(|request_field| { - let (field, header_name) = match request_field { - RequestField::Header(field, header_name) => (field, header_name), - _ => panic!("expected request field to be header variant"), - }; - + .map(|(field, header_name)| { let cfg_attrs = field.attrs.iter().filter(|a| a.path.is_ident("cfg")).collect::>(); diff --git a/crates/ruma-macros/src/api/request/outgoing.rs b/crates/ruma-macros/src/api/request/outgoing.rs index 1a54fb63..ace4aba8 100644 --- a/crates/ruma-macros/src/api/request/outgoing.rs +++ b/crates/ruma-macros/src/api/request/outgoing.rs @@ -100,12 +100,7 @@ impl Request { TokenStream::new() }; - header_kvs.extend(self.header_fields().map(|request_field| { - let (field, header_name) = match request_field { - RequestField::Header(field, header_name) => (field, header_name), - _ => unreachable!("expected request field to be header variant"), - }; - + header_kvs.extend(self.header_fields().map(|(field, header_name)| { let field_name = &field.ident; match &field.ty {