macros: Refactor RequestField
This commit is contained in:
parent
82dd050277
commit
a59a648d04
@ -30,16 +30,16 @@ pub fn expand_derive_request(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
let f = RequestField::try_from(f)?;
|
let f = RequestField::try_from(f)?;
|
||||||
let ty = &f.field().ty;
|
let ty = &f.inner.ty;
|
||||||
|
|
||||||
match &f {
|
match &f.kind {
|
||||||
RequestField::Header(..) => collect_lifetime_idents(&mut lifetimes.header, ty),
|
RequestFieldKind::Header(_) => collect_lifetime_idents(&mut lifetimes.header, ty),
|
||||||
RequestField::Body(_) => collect_lifetime_idents(&mut lifetimes.body, ty),
|
RequestFieldKind::Body => collect_lifetime_idents(&mut lifetimes.body, ty),
|
||||||
RequestField::NewtypeBody(_) => collect_lifetime_idents(&mut lifetimes.body, ty),
|
RequestFieldKind::NewtypeBody => collect_lifetime_idents(&mut lifetimes.body, ty),
|
||||||
RequestField::RawBody(_) => collect_lifetime_idents(&mut lifetimes.body, ty),
|
RequestFieldKind::RawBody => collect_lifetime_idents(&mut lifetimes.body, ty),
|
||||||
RequestField::Path(_) => collect_lifetime_idents(&mut lifetimes.path, ty),
|
RequestFieldKind::Path => collect_lifetime_idents(&mut lifetimes.path, ty),
|
||||||
RequestField::Query(_) => collect_lifetime_idents(&mut lifetimes.query, ty),
|
RequestFieldKind::Query => collect_lifetime_idents(&mut lifetimes.query, ty),
|
||||||
RequestField::QueryMap(_) => collect_lifetime_idents(&mut lifetimes.query, ty),
|
RequestFieldKind::QueryMap => collect_lifetime_idents(&mut lifetimes.query, ty),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(f)
|
Ok(f)
|
||||||
@ -119,23 +119,23 @@ impl Request {
|
|||||||
fn has_body_fields(&self) -> bool {
|
fn has_body_fields(&self) -> bool {
|
||||||
self.fields
|
self.fields
|
||||||
.iter()
|
.iter()
|
||||||
.any(|f| matches!(f, RequestField::Body(_) | RequestField::NewtypeBody(_)))
|
.any(|f| matches!(&f.kind, RequestFieldKind::Body | RequestFieldKind::NewtypeBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_newtype_body(&self) -> bool {
|
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 {
|
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 {
|
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 {
|
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 {
|
fn has_lifetimes(&self) -> bool {
|
||||||
@ -145,8 +145,8 @@ impl Request {
|
|||||||
&& self.lifetimes.header.is_empty())
|
&& self.lifetimes.header.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_fields(&self) -> impl Iterator<Item = &RequestField> {
|
fn header_fields(&self) -> impl Iterator<Item = (&Field, &Ident)> {
|
||||||
self.fields.iter().filter(|f| matches!(f, RequestField::Header(..)))
|
self.fields.iter().filter_map(RequestField::as_header_field)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_fields_ordered(&self) -> impl Iterator<Item = &Field> {
|
fn path_fields_ordered(&self) -> impl Iterator<Item = &Field> {
|
||||||
@ -259,8 +259,8 @@ impl Request {
|
|||||||
self.check_path(&path_fields, self.r0_path.as_ref())?;
|
self.check_path(&path_fields, self.r0_path.as_ref())?;
|
||||||
self.check_path(&path_fields, self.stable_path.as_ref())?;
|
self.check_path(&path_fields, self.stable_path.as_ref())?;
|
||||||
|
|
||||||
let newtype_body_fields = self.fields.iter().filter(|field| {
|
let newtype_body_fields = self.fields.iter().filter(|f| {
|
||||||
matches!(field, RequestField::NewtypeBody(_) | RequestField::RawBody(_))
|
matches!(&f.kind, RequestFieldKind::NewtypeBody | RequestFieldKind::RawBody)
|
||||||
});
|
});
|
||||||
|
|
||||||
let has_newtype_body_field = match newtype_body_fields.count() {
|
let has_newtype_body_field = match newtype_body_fields.count() {
|
||||||
@ -275,7 +275,7 @@ impl Request {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let query_map_fields =
|
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() {
|
let has_query_map_field = match query_map_fields.count() {
|
||||||
0 => false,
|
0 => false,
|
||||||
1 => true,
|
1 => true,
|
||||||
@ -287,8 +287,9 @@ impl Request {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_body_fields = self.fields.iter().any(|f| matches!(f, RequestField::Body(_)));
|
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, RequestField::Query(_)));
|
let has_query_fields =
|
||||||
|
self.fields.iter().any(|f| matches!(&f.kind, RequestFieldKind::Query));
|
||||||
|
|
||||||
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(
|
||||||
@ -365,97 +366,97 @@ impl Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The types of fields that a request can have.
|
/// A field of the request struct.
|
||||||
enum RequestField {
|
struct RequestField {
|
||||||
|
inner: Field,
|
||||||
|
kind: RequestFieldKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The kind of a request field.
|
||||||
|
enum RequestFieldKind {
|
||||||
/// JSON data in the body of the request.
|
/// JSON data in the body of the request.
|
||||||
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 request.
|
/// A specific data type in the body of the request.
|
||||||
NewtypeBody(Field),
|
NewtypeBody,
|
||||||
|
|
||||||
/// Arbitrary bytes in the body of the request.
|
/// Arbitrary bytes in the body of the request.
|
||||||
RawBody(Field),
|
RawBody,
|
||||||
|
|
||||||
/// Data that appears in the URL path.
|
/// Data that appears in the URL path.
|
||||||
Path(Field),
|
Path,
|
||||||
|
|
||||||
/// Data that appears in the query string.
|
/// Data that appears in the query string.
|
||||||
Query(Field),
|
Query,
|
||||||
|
|
||||||
/// Data that appears in the query string as dynamic key-value pairs.
|
/// Data that appears in the query string as dynamic key-value pairs.
|
||||||
QueryMap(Field),
|
QueryMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestField {
|
impl RequestField {
|
||||||
/// Creates a new `RequestField`.
|
/// Creates a new `RequestField`.
|
||||||
fn new(field: Field, kind_attr: Option<RequestMeta>) -> Self {
|
fn new(inner: Field, kind_attr: Option<RequestMeta>) -> Self {
|
||||||
if let Some(attr) = kind_attr {
|
let kind = match kind_attr {
|
||||||
match attr {
|
Some(RequestMeta::NewtypeBody) => RequestFieldKind::NewtypeBody,
|
||||||
RequestMeta::NewtypeBody => RequestField::NewtypeBody(field),
|
Some(RequestMeta::RawBody) => RequestFieldKind::RawBody,
|
||||||
RequestMeta::RawBody => RequestField::RawBody(field),
|
Some(RequestMeta::Path) => RequestFieldKind::Path,
|
||||||
RequestMeta::Path => RequestField::Path(field),
|
Some(RequestMeta::Query) => RequestFieldKind::Query,
|
||||||
RequestMeta::Query => RequestField::Query(field),
|
Some(RequestMeta::QueryMap) => RequestFieldKind::QueryMap,
|
||||||
RequestMeta::QueryMap => RequestField::QueryMap(field),
|
Some(RequestMeta::Header(header)) => RequestFieldKind::Header(header),
|
||||||
RequestMeta::Header(header) => RequestField::Header(field, header),
|
None => RequestFieldKind::Body,
|
||||||
}
|
};
|
||||||
} else {
|
|
||||||
RequestField::Body(field)
|
Self { inner, kind }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contained field if this request field is a body kind.
|
/// Return the contained field if this request field is a body kind.
|
||||||
pub fn as_body_field(&self) -> Option<&Field> {
|
pub fn as_body_field(&self) -> Option<&Field> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::Body(field) | RequestField::NewtypeBody(field) => Some(field),
|
RequestFieldKind::Body | RequestFieldKind::NewtypeBody => Some(&self.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contained field if this request field is a raw body kind.
|
/// Return the contained field if this request field is a raw body kind.
|
||||||
pub fn as_raw_body_field(&self) -> Option<&Field> {
|
pub fn as_raw_body_field(&self) -> Option<&Field> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::RawBody(field) => Some(field),
|
RequestFieldKind::RawBody => Some(&self.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contained field if this request field is a path kind.
|
/// Return the contained field if this request field is a path kind.
|
||||||
pub fn as_path_field(&self) -> Option<&Field> {
|
pub fn as_path_field(&self) -> Option<&Field> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::Path(field) => Some(field),
|
RequestFieldKind::Path => Some(&self.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contained field if this request field is a query kind.
|
/// Return the contained field if this request field is a query kind.
|
||||||
pub fn as_query_field(&self) -> Option<&Field> {
|
pub fn as_query_field(&self) -> Option<&Field> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::Query(field) => Some(field),
|
RequestFieldKind::Query => Some(&self.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contained field if this request field is a query map kind.
|
/// Return the contained field if this request field is a query map kind.
|
||||||
pub fn as_query_map_field(&self) -> Option<&Field> {
|
pub fn as_query_map_field(&self) -> Option<&Field> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::QueryMap(field) => Some(field),
|
RequestFieldKind::QueryMap => Some(&self.inner),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the inner `Field` value.
|
/// Return the contained field and header ident if this request field is a header kind.
|
||||||
pub fn field(&self) -> &Field {
|
pub fn as_header_field(&self) -> Option<(&Field, &Ident)> {
|
||||||
match self {
|
match &self.kind {
|
||||||
RequestField::Body(field)
|
RequestFieldKind::Header(header_name) => Some((&self.inner, header_name)),
|
||||||
| RequestField::Header(field, _)
|
_ => None,
|
||||||
| RequestField::NewtypeBody(field)
|
|
||||||
| RequestField::RawBody(field)
|
|
||||||
| RequestField::Path(field)
|
|
||||||
| RequestField::Query(field)
|
|
||||||
| RequestField::QueryMap(field) => field,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,6 +492,6 @@ impl Parse for RequestField {
|
|||||||
|
|
||||||
impl ToTokens for RequestField {
|
impl ToTokens for RequestField {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
self.field().to_tokens(tokens);
|
self.inner.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,12 +86,7 @@ impl Request {
|
|||||||
let (parse_headers, header_vars) = if self.has_header_fields() {
|
let (parse_headers, header_vars) = if self.has_header_fields() {
|
||||||
let (decls, names): (TokenStream, Vec<_>) = self
|
let (decls, names): (TokenStream, Vec<_>) = self
|
||||||
.header_fields()
|
.header_fields()
|
||||||
.map(|request_field| {
|
.map(|(field, header_name)| {
|
||||||
let (field, header_name) = match request_field {
|
|
||||||
RequestField::Header(field, header_name) => (field, header_name),
|
|
||||||
_ => panic!("expected request field to be header variant"),
|
|
||||||
};
|
|
||||||
|
|
||||||
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<_>>();
|
||||||
|
|
||||||
|
@ -100,12 +100,7 @@ impl Request {
|
|||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
header_kvs.extend(self.header_fields().map(|request_field| {
|
header_kvs.extend(self.header_fields().map(|(field, header_name)| {
|
||||||
let (field, header_name) = match request_field {
|
|
||||||
RequestField::Header(field, header_name) => (field, header_name),
|
|
||||||
_ => unreachable!("expected request field to be header variant"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let field_name = &field.ident;
|
let field_name = &field.ident;
|
||||||
|
|
||||||
match &field.ty {
|
match &field.ty {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user