macros: Refactor ruma_api attributes parsing
This commit is contained in:
parent
72fc21c342
commit
734770d2bc
@ -2,77 +2,147 @@
|
|||||||
|
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
Ident, Lit, Token, Type,
|
Ident, LitStr, Token, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Value type used for request and response struct attributes
|
mod kw {
|
||||||
#[allow(clippy::large_enum_variant)]
|
syn::custom_keyword!(body);
|
||||||
pub enum MetaValue {
|
syn::custom_keyword!(raw_body);
|
||||||
Lit(Lit),
|
syn::custom_keyword!(path);
|
||||||
Type(Type),
|
syn::custom_keyword!(query);
|
||||||
|
syn::custom_keyword!(query_map);
|
||||||
|
syn::custom_keyword!(header);
|
||||||
|
syn::custom_keyword!(authentication);
|
||||||
|
syn::custom_keyword!(method);
|
||||||
|
syn::custom_keyword!(error_ty);
|
||||||
|
syn::custom_keyword!(unstable);
|
||||||
|
syn::custom_keyword!(r0);
|
||||||
|
syn::custom_keyword!(stable);
|
||||||
|
syn::custom_keyword!(manual_body_serde);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MetaValue {
|
pub enum RequestMeta {
|
||||||
|
NewtypeBody,
|
||||||
|
RawBody,
|
||||||
|
Path,
|
||||||
|
Query,
|
||||||
|
QueryMap,
|
||||||
|
Header(Ident),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for RequestMeta {
|
||||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
if input.peek(Lit) {
|
let lookahead = input.lookahead1();
|
||||||
input.parse().map(Self::Lit)
|
if lookahead.peek(kw::body) {
|
||||||
} else {
|
let _: kw::body = input.parse()?;
|
||||||
input.parse().map(Self::Type)
|
Ok(Self::NewtypeBody)
|
||||||
}
|
} else if lookahead.peek(kw::raw_body) {
|
||||||
}
|
let _: kw::raw_body = input.parse()?;
|
||||||
}
|
Ok(Self::RawBody)
|
||||||
|
} else if lookahead.peek(kw::path) {
|
||||||
/// Like syn::MetaNameValue, but expects an identifier as the value.
|
let _: kw::path = input.parse()?;
|
||||||
///
|
Ok(Self::Path)
|
||||||
/// Also, we don't care about the the span of the equals sign, so we don't have the `eq_token` field
|
} else if lookahead.peek(kw::query) {
|
||||||
/// from syn::MetaNameValue.
|
let _: kw::query = input.parse()?;
|
||||||
pub struct MetaNameValue<V> {
|
Ok(Self::Query)
|
||||||
/// The part left of the equals sign
|
} else if lookahead.peek(kw::query_map) {
|
||||||
pub name: Ident,
|
let _: kw::query_map = input.parse()?;
|
||||||
|
Ok(Self::QueryMap)
|
||||||
/// The part right of the equals sign
|
} else if lookahead.peek(kw::header) {
|
||||||
pub value: V,
|
let _: kw::header = input.parse()?;
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: Parse> Parse for MetaNameValue<V> {
|
|
||||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
|
||||||
let ident = input.parse()?;
|
|
||||||
let _: Token![=] = input.parse()?;
|
|
||||||
Ok(MetaNameValue { name: ident, value: input.parse()? })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like syn::Meta, but only parses ruma_api attributes
|
|
||||||
pub enum Meta<T> {
|
|
||||||
/// A single word, like `query` in `#[ruma_api(query)]`
|
|
||||||
Word(Ident),
|
|
||||||
|
|
||||||
/// A name-value pair, like `header = CONTENT_TYPE` in `#[ruma_api(header = CONTENT_TYPE)]`
|
|
||||||
NameValue(MetaNameValue<T>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Parse> Meta<T> {
|
|
||||||
/// Check if the given attribute is a ruma_api attribute.
|
|
||||||
///
|
|
||||||
/// If it is, parse it.
|
|
||||||
pub fn from_attribute(attr: &syn::Attribute) -> syn::Result<Option<Self>> {
|
|
||||||
if attr.path.is_ident("ruma_api") {
|
|
||||||
attr.parse_args().map(Some)
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Parse> Parse for Meta<T> {
|
|
||||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
|
||||||
let ident = input.parse()?;
|
|
||||||
|
|
||||||
if input.peek(Token![=]) {
|
|
||||||
let _: Token![=] = input.parse()?;
|
let _: Token![=] = input.parse()?;
|
||||||
Ok(Meta::NameValue(MetaNameValue { name: ident, value: input.parse()? }))
|
input.parse().map(Self::Header)
|
||||||
} else {
|
} else {
|
||||||
Ok(Meta::Word(ident))
|
Err(lookahead.error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DeriveRequestMeta {
|
||||||
|
Authentication(Type),
|
||||||
|
Method(Type),
|
||||||
|
ErrorTy(Type),
|
||||||
|
UnstablePath(LitStr),
|
||||||
|
R0Path(LitStr),
|
||||||
|
StablePath(LitStr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for DeriveRequestMeta {
|
||||||
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
let lookahead = input.lookahead1();
|
||||||
|
if lookahead.peek(kw::authentication) {
|
||||||
|
let _: kw::authentication = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::Authentication)
|
||||||
|
} else if lookahead.peek(kw::method) {
|
||||||
|
let _: kw::method = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::Method)
|
||||||
|
} else if lookahead.peek(kw::error_ty) {
|
||||||
|
let _: kw::error_ty = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::ErrorTy)
|
||||||
|
} else if lookahead.peek(kw::unstable) {
|
||||||
|
let _: kw::unstable = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::UnstablePath)
|
||||||
|
} else if lookahead.peek(kw::r0) {
|
||||||
|
let _: kw::r0 = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::R0Path)
|
||||||
|
} else if lookahead.peek(kw::stable) {
|
||||||
|
let _: kw::stable = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::StablePath)
|
||||||
|
} else {
|
||||||
|
Err(lookahead.error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ResponseMeta {
|
||||||
|
NewtypeBody,
|
||||||
|
RawBody,
|
||||||
|
Header(Ident),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for ResponseMeta {
|
||||||
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
let lookahead = input.lookahead1();
|
||||||
|
if lookahead.peek(kw::body) {
|
||||||
|
let _: kw::body = input.parse()?;
|
||||||
|
Ok(Self::NewtypeBody)
|
||||||
|
} else if lookahead.peek(kw::raw_body) {
|
||||||
|
let _: kw::raw_body = input.parse()?;
|
||||||
|
Ok(Self::RawBody)
|
||||||
|
} else if lookahead.peek(kw::header) {
|
||||||
|
let _: kw::header = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::Header)
|
||||||
|
} else {
|
||||||
|
Err(lookahead.error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum DeriveResponseMeta {
|
||||||
|
ManualBodySerde,
|
||||||
|
ErrorTy(Type),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for DeriveResponseMeta {
|
||||||
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
let lookahead = input.lookahead1();
|
||||||
|
if lookahead.peek(kw::manual_body_serde) {
|
||||||
|
let _: kw::manual_body_serde = input.parse()?;
|
||||||
|
Ok(Self::ManualBodySerde)
|
||||||
|
} else if lookahead.peek(kw::error_ty) {
|
||||||
|
let _: kw::error_ty = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
input.parse().map(Self::ErrorTy)
|
||||||
|
} else {
|
||||||
|
Err(lookahead.error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, BTreeSet},
|
collections::{BTreeMap, BTreeSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
mem,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
@ -10,11 +9,11 @@ use syn::{
|
|||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
parse_quote,
|
parse_quote,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
DeriveInput, Field, Generics, Ident, Lifetime, Lit, LitStr, Token, Type,
|
DeriveInput, Field, Generics, Ident, Lifetime, LitStr, Token, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
attribute::{Meta, MetaNameValue, MetaValue},
|
attribute::{DeriveRequestMeta, RequestMeta},
|
||||||
auth_scheme::AuthScheme,
|
auth_scheme::AuthScheme,
|
||||||
util::collect_lifetime_idents,
|
util::collect_lifetime_idents,
|
||||||
};
|
};
|
||||||
@ -62,28 +61,16 @@ pub fn expand_derive_request(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let meta = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?;
|
let metas =
|
||||||
for MetaNameValue { name, value } in meta {
|
attr.parse_args_with(Punctuated::<DeriveRequestMeta, Token![,]>::parse_terminated)?;
|
||||||
match value {
|
for meta in metas {
|
||||||
MetaValue::Type(t) if name == "authentication" => {
|
match meta {
|
||||||
authentication = Some(parse_quote!(#t));
|
DeriveRequestMeta::Authentication(t) => authentication = Some(parse_quote!(#t)),
|
||||||
}
|
DeriveRequestMeta::Method(t) => method = Some(parse_quote!(#t)),
|
||||||
MetaValue::Type(t) if name == "method" => {
|
DeriveRequestMeta::ErrorTy(t) => error_ty = Some(t),
|
||||||
method = Some(parse_quote!(#t));
|
DeriveRequestMeta::UnstablePath(s) => unstable_path = Some(s),
|
||||||
}
|
DeriveRequestMeta::R0Path(s) => r0_path = Some(s),
|
||||||
MetaValue::Type(t) if name == "error_ty" => {
|
DeriveRequestMeta::StablePath(s) => stable_path = Some(s),
|
||||||
error_ty = Some(t);
|
|
||||||
}
|
|
||||||
MetaValue::Lit(Lit::Str(s)) if name == "unstable" => {
|
|
||||||
unstable_path = Some(s);
|
|
||||||
}
|
|
||||||
MetaValue::Lit(Lit::Str(s)) if name == "r0" => {
|
|
||||||
r0_path = Some(s);
|
|
||||||
}
|
|
||||||
MetaValue::Lit(Lit::Str(s)) if name == "stable" => {
|
|
||||||
stable_path = Some(s);
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid ruma_api({}) attribute", name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,17 +392,18 @@ enum RequestField {
|
|||||||
|
|
||||||
impl RequestField {
|
impl RequestField {
|
||||||
/// Creates a new `RequestField`.
|
/// Creates a new `RequestField`.
|
||||||
fn new(kind: RequestFieldKind, field: Field, header: Option<Ident>) -> Self {
|
fn new(field: Field, kind_attr: Option<RequestMeta>) -> Self {
|
||||||
match kind {
|
if let Some(attr) = kind_attr {
|
||||||
RequestFieldKind::Body => RequestField::Body(field),
|
match attr {
|
||||||
RequestFieldKind::Header => {
|
RequestMeta::NewtypeBody => RequestField::NewtypeBody(field),
|
||||||
RequestField::Header(field, header.expect("missing header name"))
|
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),
|
||||||
}
|
}
|
||||||
RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
|
} else {
|
||||||
RequestFieldKind::RawBody => RequestField::RawBody(field),
|
RequestField::Body(field)
|
||||||
RequestFieldKind::Path => RequestField::Path(field),
|
|
||||||
RequestFieldKind::Query => RequestField::Query(field),
|
|
||||||
RequestFieldKind::QueryMap => RequestField::QueryMap(field),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,55 +465,22 @@ impl TryFrom<Field> for RequestField {
|
|||||||
type Error = syn::Error;
|
type Error = syn::Error;
|
||||||
|
|
||||||
fn try_from(mut field: Field) -> syn::Result<Self> {
|
fn try_from(mut field: Field) -> syn::Result<Self> {
|
||||||
let mut field_kind = None;
|
let (mut api_attrs, attrs) =
|
||||||
let mut header = None;
|
field.attrs.into_iter().partition::<Vec<_>, _>(|attr| attr.path.is_ident("ruma_api"));
|
||||||
|
field.attrs = attrs;
|
||||||
|
|
||||||
for attr in mem::take(&mut field.attrs) {
|
let kind_attr = match api_attrs.as_slice() {
|
||||||
let meta = match Meta::from_attribute(&attr)? {
|
[] => None,
|
||||||
Some(m) => m,
|
[_] => Some(api_attrs.pop().unwrap().parse_args::<RequestMeta>()?),
|
||||||
None => {
|
_ => {
|
||||||
field.attrs.push(attr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if field_kind.is_some() {
|
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(
|
||||||
attr,
|
&api_attrs[1],
|
||||||
"There can only be one field kind attribute",
|
"multiple field kind attribute found, there can only be one",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
field_kind = Some(match meta {
|
Ok(RequestField::new(field, kind_attr))
|
||||||
Meta::Word(ident) => match &ident.to_string()[..] {
|
|
||||||
"body" => RequestFieldKind::NewtypeBody,
|
|
||||||
"raw_body" => RequestFieldKind::RawBody,
|
|
||||||
"path" => RequestFieldKind::Path,
|
|
||||||
"query" => RequestFieldKind::Query,
|
|
||||||
"query_map" => RequestFieldKind::QueryMap,
|
|
||||||
_ => {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
ident,
|
|
||||||
"Invalid #[ruma_api] argument, expected one of \
|
|
||||||
`body`, `raw_body`, `path`, `query`, `query_map`",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Meta::NameValue(MetaNameValue { name, value }) => {
|
|
||||||
if name != "header" {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
name,
|
|
||||||
"Invalid #[ruma_api] argument with value, expected `header`",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
header = Some(value);
|
|
||||||
RequestFieldKind::Header
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RequestField::new(field_kind.unwrap_or(RequestFieldKind::Body), field, header))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,15 +495,3 @@ impl ToTokens for RequestField {
|
|||||||
self.field().to_tokens(tokens)
|
self.field().to_tokens(tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The types of fields that a request can have, without their values.
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
enum RequestFieldKind {
|
|
||||||
Body,
|
|
||||||
Header,
|
|
||||||
NewtypeBody,
|
|
||||||
RawBody,
|
|
||||||
Path,
|
|
||||||
Query,
|
|
||||||
QueryMap,
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
mem,
|
|
||||||
ops::Not,
|
ops::Not,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13,7 +12,7 @@ use syn::{
|
|||||||
DeriveInput, Field, Generics, Ident, Lifetime, Token, Type,
|
DeriveInput, Field, Generics, Ident, Lifetime, Token, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::attribute::{Meta, MetaNameValue};
|
use super::attribute::{DeriveResponseMeta, ResponseMeta};
|
||||||
use crate::util::import_ruma_common;
|
use crate::util::import_ruma_common;
|
||||||
|
|
||||||
mod incoming;
|
mod incoming;
|
||||||
@ -33,18 +32,12 @@ pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let metas = attr.parse_args_with(Punctuated::<Meta<Type>, Token![,]>::parse_terminated)?;
|
let metas =
|
||||||
|
attr.parse_args_with(Punctuated::<DeriveResponseMeta, Token![,]>::parse_terminated)?;
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
match meta {
|
match meta {
|
||||||
Meta::Word(w) if w == "manual_body_serde" => {
|
DeriveResponseMeta::ManualBodySerde => manual_body_serde = true,
|
||||||
manual_body_serde = true;
|
DeriveResponseMeta::ErrorTy(t) => error_ty = Some(t),
|
||||||
}
|
|
||||||
Meta::NameValue(MetaNameValue { name, value }) if name == "error_ty" => {
|
|
||||||
error_ty = Some(value);
|
|
||||||
}
|
|
||||||
Meta::Word(name) | Meta::NameValue(MetaNameValue { name, .. }) => {
|
|
||||||
unreachable!("invalid ruma_api({}) attribute", name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,6 +173,19 @@ enum ResponseField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseField {
|
impl ResponseField {
|
||||||
|
/// Creates a new `ResponseField`.
|
||||||
|
fn new(field: Field, kind_attr: Option<ResponseMeta>) -> Self {
|
||||||
|
if let Some(attr) = kind_attr {
|
||||||
|
match attr {
|
||||||
|
ResponseMeta::NewtypeBody => ResponseField::NewtypeBody(field),
|
||||||
|
ResponseMeta::RawBody => ResponseField::RawBody(field),
|
||||||
|
ResponseMeta::Header(header) => ResponseField::Header(field, header),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ResponseField::Body(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the inner `Field` value.
|
/// Gets the inner `Field` value.
|
||||||
fn field(&self) -> &Field {
|
fn field(&self) -> &Field {
|
||||||
match self {
|
match self {
|
||||||
@ -226,58 +232,22 @@ impl TryFrom<Field> for ResponseField {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut field_kind = None;
|
let (mut api_attrs, attrs) =
|
||||||
let mut header = None;
|
field.attrs.into_iter().partition::<Vec<_>, _>(|attr| attr.path.is_ident("ruma_api"));
|
||||||
|
field.attrs = attrs;
|
||||||
|
|
||||||
for attr in mem::take(&mut field.attrs) {
|
let kind_attr = match api_attrs.as_slice() {
|
||||||
let meta = match Meta::from_attribute(&attr)? {
|
[] => None,
|
||||||
Some(m) => m,
|
[_] => Some(api_attrs.pop().unwrap().parse_args::<ResponseMeta>()?),
|
||||||
None => {
|
_ => {
|
||||||
field.attrs.push(attr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if field_kind.is_some() {
|
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(
|
||||||
attr,
|
&api_attrs[1],
|
||||||
"There can only be one field kind attribute",
|
"multiple field kind attribute found, there can only be one",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
field_kind = Some(match meta {
|
Ok(ResponseField::new(field, kind_attr))
|
||||||
Meta::Word(ident) => match &ident.to_string()[..] {
|
|
||||||
"body" => ResponseFieldKind::NewtypeBody,
|
|
||||||
"raw_body" => ResponseFieldKind::RawBody,
|
|
||||||
_ => {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
ident,
|
|
||||||
"Invalid #[ruma_api] argument with value, expected `body`",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Meta::NameValue(MetaNameValue { name, value }) => {
|
|
||||||
if name != "header" {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
name,
|
|
||||||
"Invalid #[ruma_api] argument with value, expected `header`",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
header = Some(value);
|
|
||||||
ResponseFieldKind::Header
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(match field_kind.unwrap_or(ResponseFieldKind::Body) {
|
|
||||||
ResponseFieldKind::Body => ResponseField::Body(field),
|
|
||||||
ResponseFieldKind::Header => {
|
|
||||||
ResponseField::Header(field, header.expect("missing header name"))
|
|
||||||
}
|
|
||||||
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
|
|
||||||
ResponseFieldKind::RawBody => ResponseField::RawBody(field),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,14 +263,6 @@ impl ToTokens for ResponseField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The types of fields that a response can have, without their values.
|
|
||||||
enum ResponseFieldKind {
|
|
||||||
Body,
|
|
||||||
Header,
|
|
||||||
NewtypeBody,
|
|
||||||
RawBody,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_lifetime(ty: &Type) -> bool {
|
fn has_lifetime(ty: &Type) -> bool {
|
||||||
struct Visitor {
|
struct Visitor {
|
||||||
found_lifetime: bool,
|
found_lifetime: bool,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user