ruma_macros/api/request/
outgoing.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3
4use super::{KIND, Request, RequestQuery};
5use crate::{
6    api::StructSuffix,
7    util::{RumaCommon, RumaCommonReexport, StructFieldExt},
8};
9
10impl Request {
11    /// Generate the `ruma_common::api::OutgoingRequest` implementation for this request struct.
12    pub fn expand_outgoing(&self, ruma_common: &RumaCommon) -> TokenStream {
13        let bytes = ruma_common.reexported(RumaCommonReexport::Bytes);
14        let http = ruma_common.reexported(RumaCommonReexport::Http);
15
16        let path_fields = self.path.expand_fields();
17        let path_idents = self.path.0.iter().map(|field| field.ident());
18
19        let query_serialize = self.query.expand_serialize(ruma_common);
20        let query_fields = self.query.expand_fields();
21
22        let headers_serialize = self.headers.expand_serialize(KIND, &self.body, ruma_common, &http);
23        let headers_fields = self.headers.expand_fields();
24
25        let body_serialize = self.body.expand_serialize(KIND, ruma_common);
26        let body_fields = self.body.expand_fields();
27
28        let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
29        let ident = &self.ident;
30        let error_ty = &self.error_ty;
31        let request = KIND.as_variable_ident();
32
33        quote! {
34            #[automatically_derived]
35            #[cfg(feature = "client")]
36            impl #impl_generics #ruma_common::api::OutgoingRequest for #ident #ty_generics #where_clause {
37                type EndpointError = #error_ty;
38                type IncomingResponse = Response;
39
40                fn try_into_http_request<T: ::std::default::Default + #bytes::BufMut + ::std::convert::AsRef<[::std::primitive::u8]>>(
41                    self,
42                    base_url: &::std::primitive::str,
43                    authentication_input: <<Self as #ruma_common::api::Metadata>::Authentication as #ruma_common::api::auth_scheme::AuthScheme>::Input<'_>,
44                    path_builder_input: <<Self as #ruma_common::api::Metadata>::PathBuilder as #ruma_common::api::path_builder::PathBuilder>::Input<'_>,
45                ) -> ::std::result::Result<#http::Request<T>, #ruma_common::api::error::IntoHttpError> {
46                    let Self {
47                        #path_fields
48                        #query_fields
49                        #headers_fields
50                        #body_fields
51                    } = self;
52
53                    let request_query_string = #query_serialize;
54
55                    let mut #request = #http::Request::builder()
56                        .method(<Self as #ruma_common::api::Metadata>::METHOD)
57                        .uri(<Self as #ruma_common::api::Metadata>::make_endpoint_url(
58                            path_builder_input,
59                            base_url,
60                            &[ #( &#path_idents ),* ],
61                            &request_query_string,
62                        )?)
63                        .body(#body_serialize)?;
64
65                    #headers_serialize
66
67                    <<Self as #ruma_common::api::Metadata>::Authentication as #ruma_common::api::auth_scheme::AuthScheme>::add_authentication(
68                        &mut #request,
69                        authentication_input
70                    )
71                        .map_err(|error| #ruma_common::api::error::IntoHttpError::Authentication(error.into()))?;
72
73                    Ok(#request)
74                }
75            }
76        }
77    }
78}
79
80impl RequestQuery {
81    /// Generate code to serialize the query string.
82    fn expand_serialize(&self, ruma_common: &RumaCommon) -> TokenStream {
83        if matches!(self, Self::None) {
84            return quote! { "" };
85        }
86
87        let serde_html_form = ruma_common.reexported(RumaCommonReexport::SerdeHtmlForm);
88        let fields = self.expand_fields();
89        let serde_struct = KIND.as_struct_ident(StructSuffix::Query);
90
91        quote! {{
92            let request_query = #serde_struct {
93                #fields
94            };
95
96            &#serde_html_form::to_string(request_query)?
97        }}
98    }
99}