use proc_macro2::TokenStream;
use quote::quote;
use super::{KIND, Request, RequestPath, RequestQuery};
use crate::{
api::StructSuffix,
util::{RumaCommon, RumaCommonReexport, expand_fields_as_list},
};
impl Request {
pub fn expand_incoming(&self, ruma_common: &RumaCommon) -> TokenStream {
let http = ruma_common.reexported(RumaCommonReexport::Http);
let path_parse = self.path.expand_parse(ruma_common);
let path_fields = self.path.expand_fields();
let query_parse = self.query.expand_parse(ruma_common);
let query_fields = self.query.expand_fields();
let headers_parse = self.headers.expand_parse(KIND, ruma_common);
let headers_fields = self.headers.expand_fields();
let body_parse = self.body.expand_parse(KIND, ruma_common);
let body_fields = self.body.expand_fields();
let request = KIND.as_variable_ident();
let error_ty = &self.error_ty;
let ident = &self.ident;
quote! {
#[automatically_derived]
#[cfg(feature = "server")]
impl #ruma_common::api::IncomingRequest for #ident {
type EndpointError = #error_ty;
type OutgoingResponse = Response;
fn try_from_http_request<B, S>(
#request: #http::Request<B>,
path_args: &[S],
) -> ::std::result::Result<Self, #ruma_common::api::error::FromHttpRequestError>
where
B: ::std::convert::AsRef<[::std::primitive::u8]>,
S: ::std::convert::AsRef<::std::primitive::str>,
{
<Self as #ruma_common::api::IncomingRequest>::check_request_method(#request.method())?;
#path_parse
#query_parse
#headers_parse
#body_parse
::std::result::Result::Ok(Self {
#path_fields
#query_fields
#headers_fields
#body_fields
})
}
}
}
}
}
impl RequestPath {
fn expand_parse(&self, ruma_common: &RumaCommon) -> Option<TokenStream> {
if self.0.is_empty() {
return None;
}
let serde = ruma_common.reexported(RumaCommonReexport::Serde);
let fields = self.expand_fields();
Some(quote! {
let (#fields) = #serde::Deserialize::deserialize(
#serde::de::value::SeqDeserializer::<_, #serde::de::value::Error>::new(
path_args.iter().map(::std::convert::AsRef::as_ref)
)
)?;
})
}
}
impl RequestQuery {
fn expand_parse(&self, ruma_common: &RumaCommon) -> Option<TokenStream> {
let fields = match self {
Self::None => return None,
Self::Fields(fields) => fields.as_slice(),
Self::All(field) => std::slice::from_ref(field),
};
let serde_html_form = ruma_common.reexported(RumaCommonReexport::SerdeHtmlForm);
let request = KIND.as_variable_ident();
let query_ident = KIND.as_struct_ident(StructSuffix::Query);
let query_fields = expand_fields_as_list(fields);
Some(quote! {
let query: #query_ident =
#serde_html_form::from_str(#request.uri().query().unwrap_or(""))?;
let #query_ident {
#query_fields
} = query;
})
}
}