diff --git a/ruma-api-macros/src/api.rs b/ruma-api-macros/src/api.rs index 627ea442..49196e73 100644 --- a/ruma-api-macros/src/api.rs +++ b/ruma-api-macros/src/api.rs @@ -108,7 +108,7 @@ impl ToTokens for Api { TokenStream::new() }; - let (set_request_path, parse_request_path) = if self.request.has_path_fields() { + let (url_set_path, parse_request_path) = if self.request.has_path_fields() { let path_str = path.value(); assert!(path_str.starts_with('/'), "path needs to start with '/'"); @@ -182,7 +182,7 @@ impl ToTokens for Api { (set_tokens, parse_tokens) }; - let set_request_query = if let Some(field) = self.request.query_map_field() { + let url_set_querystring = if let Some(field) = self.request.query_map_field() { let field_name = field.ident.as_ref().expect("expected field to have identifier"); let field_type = &field.ty; @@ -252,10 +252,8 @@ impl ToTokens for Api { quote! { #field_name: request_query } - } else if self.request.has_query_fields() { - self.request.request_init_query_fields() } else { - TokenStream::new() + self.request.request_init_query_fields() }; let add_headers_to_request = if self.request.has_header_fields() { @@ -282,76 +280,22 @@ impl ToTokens for Api { TokenStream::new() }; - let create_http_request = if let Some(field) = self.request.newtype_body_field() { + let request_body_initializers = if let Some(field) = self.request.newtype_body_field() { let field_name = field.ident.as_ref().expect("expected field to have an identifier"); - - quote! { - let request_body = RequestBody(request.#field_name); - - let mut http_request = ruma_api::exports::http::Request::new( - ruma_api::exports::serde_json::to_vec(&request_body)?, - ); - } - } else if self.request.has_body_fields() { - let request_body_init_fields = self.request.request_body_init_fields(); - - quote! { - let request_body = RequestBody { - #request_body_init_fields - }; - - let mut http_request = ruma_api::exports::http::Request::new( - ruma_api::exports::serde_json::to_vec(&request_body)?, - ); - } + quote! { (request.#field_name) } } else { - quote! { - let mut http_request = ruma_api::exports::http::Request::new(Vec::new()); - } - }; - - let extract_request_body = if self.request.newtype_body_field().is_some() { - quote! { - let request_body = - ruma_api::exports::serde_json::from_slice(request.body().as_slice())?; - } - } else if self.request.has_body_fields() { - quote! { - let request_body: ::Incoming = - ruma_api::exports::serde_json::from_slice(request.body().as_slice())?; - } - } else { - TokenStream::new() + let initializers = self.request.request_body_init_fields(); + quote! { { #initializers } } }; let parse_request_body = if let Some(field) = self.request.newtype_body_field() { let field_name = field.ident.as_ref().expect("expected field to have an identifier"); quote! { - #field_name: request_body, + #field_name: request_body.0, } - } else if self.request.has_body_fields() { + } else { self.request.request_init_body_fields() - } else { - TokenStream::new() - }; - - let response_body_type_annotation = if self.response.has_body_fields() { - quote!(: ::Incoming) - } else { - TokenStream::new() - }; - - let try_deserialize_response_body = if self.response.has_body() { - quote! { - ruma_api::exports::serde_json::from_slice( - http_response.into_body().as_slice(), - )? - } - } else { - quote! { - () - } }; let extract_response_headers = if self.response.has_header_fields() { @@ -362,24 +306,11 @@ impl ToTokens for Api { TokenStream::new() }; - let response_init_fields = if self.response.has_fields() { - self.response.init_fields() - } else { - TokenStream::new() - }; + let response_init_fields = self.response.init_fields(); let serialize_response_headers = self.response.apply_header_fields(); - let try_serialize_response_body = if self.response.has_body() { - let body = self.response.to_body(); - quote! { - ruma_api::exports::serde_json::to_vec(&#body)? - } - } else { - quote! { - "{}".as_bytes().to_vec() - } - }; + let body = self.response.to_body(); let request_doc = format!( "Data for a request to the `{}` API endpoint.\n\n{}", @@ -406,7 +337,9 @@ impl ToTokens for Api { #extract_request_path #extract_request_query #extract_request_headers - #extract_request_body + + let request_body: ::Incoming = + ruma_api::exports::serde_json::from_slice(request.body().as_slice())?; Ok(Self { #parse_request_path @@ -431,10 +364,14 @@ impl ToTokens for Api { ruma_api::exports::url::Url::parse("http://invalid-host-please-change/") .unwrap(); - { #set_request_path } - { #set_request_query } + { #url_set_path } + { #url_set_querystring } - #create_http_request + let request_body = RequestBody #request_body_initializers; + + let mut http_request = ruma_api::exports::http::Request::new( + ruma_api::exports::serde_json::to_vec(&request_body)?, + ); *http_request.method_mut() = ruma_api::exports::http::Method::#method; *http_request.uri_mut() = url.into_string().parse().unwrap(); @@ -456,7 +393,7 @@ impl ToTokens for Api { let response = ruma_api::exports::http::Response::builder() .header(ruma_api::exports::http::header::CONTENT_TYPE, "application/json") #serialize_response_headers - .body(#try_serialize_response_body) + .body(ruma_api::exports::serde_json::to_vec(&#body)?) .unwrap(); Ok(response) } @@ -472,8 +409,10 @@ impl ToTokens for Api { if http_response.status().is_success() { #extract_response_headers - let response_body #response_body_type_annotation = - #try_deserialize_response_body; + let response_body: ::Incoming = + ruma_api::exports::serde_json::from_slice( + http_response.into_body().as_slice(), + )?; Ok(Self { #response_init_fields diff --git a/ruma-api-macros/src/api/request.rs b/ruma-api-macros/src/api/request.rs index 58e8363e..ad741f89 100644 --- a/ruma-api-macros/src/api/request.rs +++ b/ruma-api-macros/src/api/request.rs @@ -168,9 +168,7 @@ impl Request { }) }); - quote! { - #(#fields,)* - } + quote! { #(#fields,)* } } } @@ -293,46 +291,24 @@ impl TryFrom for Request { impl ToTokens for Request { fn to_tokens(&self, tokens: &mut TokenStream) { - let request_struct_header = quote! { - #[derive(Debug, Clone, ruma_api::Outgoing)] - #[incoming_no_deserialize] - pub struct Request - }; - - let request_struct_body = if self.fields.is_empty() { + let request_def = if self.fields.is_empty() { quote!(;) } else { let fields = self.fields.iter().map(|request_field| strip_serde_attrs(request_field.field())); - - quote! { - { - #(#fields),* - } - } + quote! { { #(#fields),* } } }; - let request_body_struct = + let (derive_deserialize, request_body_def) = if let Some(body_field) = self.fields.iter().find(|f| f.is_newtype_body()) { - let field = body_field.field(); - let ty = &field.ty; - let span = field.span(); + let field = Field { ident: None, colon_token: None, ..body_field.field().clone() }; let derive_deserialize = if body_field.has_wrap_incoming_attr() { TokenStream::new() } else { quote!(ruma_api::exports::serde::Deserialize) }; - quote_spanned! {span=> - /// Data in the request body. - #[derive( - Debug, - ruma_api::Outgoing, - ruma_api::exports::serde::Serialize, - #derive_deserialize - )] - struct RequestBody(#ty); - } + (derive_deserialize, quote! { (#field); }) } else if self.has_body_fields() { let fields = self.fields.iter().filter(|f| f.is_body()); let derive_deserialize = if fields.clone().any(|f| f.has_wrap_incoming_attr()) { @@ -342,20 +318,9 @@ impl ToTokens for Request { }; let fields = fields.map(RequestField::field); - quote! { - /// Data in the request body. - #[derive( - Debug, - ruma_api::Outgoing, - ruma_api::exports::serde::Serialize, - #derive_deserialize - )] - struct RequestBody { - #(#fields),* - } - } + (derive_deserialize, quote! { { #(#fields),* } }) } else { - TokenStream::new() + (quote!(ruma_api::exports::serde::Deserialize), quote!(;)) }; let request_path_struct = if self.has_path_fields() { @@ -376,18 +341,17 @@ impl ToTokens for Request { TokenStream::new() }; - let request_query_struct = if let Some(field) = self.query_map_field() { - let ty = &field.ty; - let span = field.span(); + let request_query_struct = if let Some(f) = self.query_map_field() { + let field = Field { ident: None, colon_token: None, ..f.clone() }; - quote_spanned! {span=> + quote! { /// Data in the request's query string. #[derive( Debug, ruma_api::exports::serde::Deserialize, ruma_api::exports::serde::Serialize, )] - struct RequestQuery(#ty); + struct RequestQuery(#field); } } else if self.has_query_fields() { let fields = self.fields.iter().filter_map(RequestField::as_query_field); @@ -408,9 +372,19 @@ impl ToTokens for Request { }; let request = quote! { - #request_struct_header - #request_struct_body - #request_body_struct + #[derive(Debug, Clone, ruma_api::Outgoing)] + #[incoming_no_deserialize] + pub struct Request #request_def + + /// Data in the request body. + #[derive( + Debug, + ruma_api::Outgoing, + ruma_api::exports::serde::Serialize, + #derive_deserialize + )] + struct RequestBody #request_body_def + #request_path_struct #request_query_struct }; diff --git a/ruma-api-macros/src/api/response.rs b/ruma-api-macros/src/api/response.rs index 29f2b4ae..5f5f4016 100644 --- a/ruma-api-macros/src/api/response.rs +++ b/ruma-api-macros/src/api/response.rs @@ -23,21 +23,11 @@ impl Response { self.fields.iter().any(|field| field.is_body()) } - /// Whether or not this response has any fields. - pub fn has_fields(&self) -> bool { - !self.fields.is_empty() - } - /// Whether or not this response has any data in HTTP headers. pub fn has_header_fields(&self) -> bool { self.fields.iter().any(|field| field.is_header()) } - /// Whether or not this response has any data in the HTTP body. - pub fn has_body(&self) -> bool { - self.fields.iter().any(|field| !field.is_header()) - } - /// Whether any field has a #[wrap_incoming] attribute. pub fn uses_wrap_incoming(&self) -> bool { self.fields.iter().any(|f| f.has_wrap_incoming_attr()) @@ -74,7 +64,7 @@ impl Response { let span = field.span(); quote_spanned! {span=> - #field_name: response_body + #field_name: response_body.0 } } }); @@ -100,9 +90,7 @@ impl Response { } }); - quote! { - #(#header_calls)* - } + quote! { #(#header_calls)* } } /// Produces code to initialize the struct that will be used to create the response body. @@ -127,9 +115,7 @@ impl Response { }); quote! { - ResponseBody { - #(#fields),* - } + ResponseBody { #(#fields),* } } } } @@ -231,46 +217,25 @@ impl TryFrom for Response { impl ToTokens for Response { fn to_tokens(&self, tokens: &mut TokenStream) { - let response_struct_header = quote! { - #[derive(Debug, Clone, ruma_api::Outgoing)] - #[incoming_no_deserialize] - pub struct Response - }; - - let response_struct_body = if self.fields.is_empty() { + let response_def = if self.fields.is_empty() { quote!(;) } else { let fields = self.fields.iter().map(|response_field| strip_serde_attrs(response_field.field())); - quote! { - { - #(#fields),* - } - } + quote! { { #(#fields),* } } }; - let response_body_struct = + let (derive_deserialize, response_body_def) = if let Some(body_field) = self.fields.iter().find(|f| f.is_newtype_body()) { - let field = body_field.field(); - let ty = &field.ty; - let span = field.span(); + let field = Field { ident: None, colon_token: None, ..body_field.field().clone() }; let derive_deserialize = if body_field.has_wrap_incoming_attr() { TokenStream::new() } else { quote!(ruma_api::exports::serde::Deserialize) }; - quote_spanned! {span=> - /// Data in the response body. - #[derive( - Debug, - ruma_api::Outgoing, - ruma_api::exports::serde::Serialize, - #derive_deserialize - )] - struct ResponseBody(#ty); - } + (derive_deserialize, quote! { (#field); }) } else if self.has_body_fields() { let fields = self.fields.iter().filter(|f| f.is_body()); let derive_deserialize = if fields.clone().any(|f| f.has_wrap_incoming_attr()) { @@ -280,26 +245,24 @@ impl ToTokens for Response { }; let fields = fields.map(ResponseField::field); - quote! { - /// Data in the response body. - #[derive( - Debug, - ruma_api::Outgoing, - ruma_api::exports::serde::Serialize, - #derive_deserialize - )] - struct ResponseBody { - #(#fields),* - } - } + (derive_deserialize, quote!({ #(#fields),* })) } else { - TokenStream::new() + (quote!(ruma_api::exports::serde::Deserialize), quote!(;)) }; let response = quote! { - #response_struct_header - #response_struct_body - #response_body_struct + #[derive(Debug, Clone, ruma_api::Outgoing)] + #[incoming_no_deserialize] + pub struct Response #response_def + + /// Data in the response body. + #[derive( + Debug, + ruma_api::Outgoing, + ruma_api::exports::serde::Serialize, + #derive_deserialize + )] + struct ResponseBody #response_body_def }; response.to_tokens(tokens);