api: Add manual_body_serde derive attribute for responses
This commit is contained in:
parent
82becb86c8
commit
e0d7ea3ed1
@ -43,15 +43,15 @@ impl<V: Parse> Parse for MetaNameValue<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Like syn::Meta, but only parses ruma_api attributes
|
/// Like syn::Meta, but only parses ruma_api attributes
|
||||||
pub enum Meta {
|
pub enum Meta<T> {
|
||||||
/// A single word, like `query` in `#[ruma_api(query)]`
|
/// A single word, like `query` in `#[ruma_api(query)]`
|
||||||
Word(Ident),
|
Word(Ident),
|
||||||
|
|
||||||
/// A name-value pair, like `header = CONTENT_TYPE` in `#[ruma_api(header = CONTENT_TYPE)]`
|
/// A name-value pair, like `header = CONTENT_TYPE` in `#[ruma_api(header = CONTENT_TYPE)]`
|
||||||
NameValue(MetaNameValue<Ident>),
|
NameValue(MetaNameValue<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Meta {
|
impl<T: Parse> Meta<T> {
|
||||||
/// Check if the given attribute is a ruma_api attribute.
|
/// Check if the given attribute is a ruma_api attribute.
|
||||||
///
|
///
|
||||||
/// If it is, parse it.
|
/// If it is, parse it.
|
||||||
@ -64,7 +64,7 @@ impl Meta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Meta {
|
impl<T: Parse> Parse for Meta<T> {
|
||||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
let ident = input.parse()?;
|
let ident = input.parse()?;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
mem,
|
mem,
|
||||||
|
ops::Not,
|
||||||
};
|
};
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
@ -13,7 +14,7 @@ use syn::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attribute::{Meta, MetaNameValue, MetaValue},
|
attribute::{Meta, MetaNameValue},
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,19 +28,25 @@ pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let fields = fields.into_iter().map(ResponseField::try_from).collect::<syn::Result<_>>()?;
|
let fields = fields.into_iter().map(ResponseField::try_from).collect::<syn::Result<_>>()?;
|
||||||
|
let mut manual_body_serde = false;
|
||||||
let mut error_ty = None;
|
let mut error_ty = None;
|
||||||
for attr in input.attrs {
|
for attr in input.attrs {
|
||||||
if !attr.path.is_ident("ruma_api") {
|
if !attr.path.is_ident("ruma_api") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let meta = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?;
|
let metas = attr.parse_args_with(Punctuated::<Meta<Type>, Token![,]>::parse_terminated)?;
|
||||||
for MetaNameValue { name, value } in meta {
|
for meta in metas {
|
||||||
match value {
|
match meta {
|
||||||
MetaValue::Type(t) if name == "error_ty" => {
|
Meta::Word(w) if w == "manual_body_serde" => {
|
||||||
error_ty = Some(t);
|
manual_body_serde = true;
|
||||||
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
_ => unreachable!("invalid ruma_api({}) attribute", name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,6 +55,7 @@ pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
ident: input.ident,
|
ident: input.ident,
|
||||||
generics: input.generics,
|
generics: input.generics,
|
||||||
fields,
|
fields,
|
||||||
|
manual_body_serde,
|
||||||
error_ty: error_ty.unwrap(),
|
error_ty: error_ty.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,6 +67,7 @@ struct Response {
|
|||||||
ident: Ident,
|
ident: Ident,
|
||||||
generics: Generics,
|
generics: Generics,
|
||||||
fields: Vec<ResponseField>,
|
fields: Vec<ResponseField>,
|
||||||
|
manual_body_serde: bool,
|
||||||
error_ty: Type,
|
error_ty: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +101,10 @@ impl Response {
|
|||||||
let serde = quote! { #ruma_api::exports::serde };
|
let serde = quote! { #ruma_api::exports::serde };
|
||||||
|
|
||||||
let response_body_struct = (!self.has_raw_body()).then(|| {
|
let response_body_struct = (!self.has_raw_body()).then(|| {
|
||||||
|
let serde_derives = self.manual_body_serde.not().then(|| {
|
||||||
|
quote! { #serde::Deserialize, #serde::Serialize }
|
||||||
|
});
|
||||||
|
|
||||||
let serde_attr = self.has_newtype_body().then(|| quote! { #[serde(transparent)] });
|
let serde_attr = self.has_newtype_body().then(|| quote! { #[serde(transparent)] });
|
||||||
let fields = self.fields.iter().filter_map(ResponseField::as_body_field);
|
let fields = self.fields.iter().filter_map(ResponseField::as_body_field);
|
||||||
|
|
||||||
@ -101,8 +114,7 @@ impl Response {
|
|||||||
Debug,
|
Debug,
|
||||||
#ruma_api_macros::_FakeDeriveRumaApi,
|
#ruma_api_macros::_FakeDeriveRumaApi,
|
||||||
#ruma_serde::Outgoing,
|
#ruma_serde::Outgoing,
|
||||||
#serde::Deserialize,
|
#serde_derives
|
||||||
#serde::Serialize,
|
|
||||||
)]
|
)]
|
||||||
#serde_attr
|
#serde_attr
|
||||||
struct ResponseBody { #(#fields),* }
|
struct ResponseBody { #(#fields),* }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user