use cfg_if::cfg_if;
use proc_macro2::TokenStream;
use quote::quote;
use super::{Body, Headers, MacroKind, ensure_feature_presence};
use crate::util::{RumaCommon, RumaCommonReexport};
mod incoming;
mod outgoing;
mod parse;
pub(crate) use self::parse::ResponseAttrs;
const KIND: MacroKind = MacroKind::Response;
pub fn expand_response(attrs: ResponseAttrs, item: syn::ItemStruct) -> TokenStream {
let ruma_common = RumaCommon::new();
let ruma_macros = ruma_common.reexported(RumaCommonReexport::RumaMacros);
let maybe_feature_error = ensure_feature_presence().map(syn::Error::to_compile_error);
let error_ty = attrs.error_ty_or_default(&ruma_common);
let status_ident = attrs.status_or_default();
cfg_if! {
if #[cfg(feature = "__internal_macro_expand")] {
use syn::parse_quote;
let mut derive_input = item.clone();
derive_input.attrs.push(parse_quote! {
#[ruma_api(error = #error_ty, status = #status_ident)]
});
crate::util::cfg_expand_struct(&mut derive_input);
let extra_derive = quote! { #ruma_macros::_FakeDeriveRumaApi };
let ruma_api_attribute = quote! {};
let response_impls =
expand_derive_response(derive_input).unwrap_or_else(syn::Error::into_compile_error);
} else {
let extra_derive = quote! { #ruma_macros::Response };
let ruma_api_attribute = quote! {
#[ruma_api(error = #error_ty, status = #status_ident)]
};
let response_impls = quote! {};
}
}
quote! {
#maybe_feature_error
#[derive(Clone, Debug, #ruma_common::serde::_FakeDeriveSerde, #extra_derive)]
#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
#ruma_api_attribute
#item
#response_impls
}
}
pub fn expand_derive_response(input: syn::ItemStruct) -> syn::Result<TokenStream> {
let response = Response::try_from(input)?;
Ok(response.expand_impls())
}
struct Response {
ident: syn::Ident,
generics: syn::Generics,
headers: Headers,
body: Body,
error_ty: syn::Type,
status: syn::Ident,
}
impl Response {
fn expand_impls(&self) -> TokenStream {
let ruma_common = RumaCommon::new();
let response_body_serde_struct =
self.body.expand_serde_struct_definition(KIND, &ruma_common);
let outgoing_response_impl = self.expand_outgoing(&ruma_common);
let incoming_response_impl = self.expand_incoming(&ruma_common);
quote! {
#response_body_serde_struct
#outgoing_response_impl
#incoming_response_impl
}
}
}