Simplify ruma-api-macros codegen
This commit is contained in:
parent
3696516679
commit
81207890b6
@ -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: <RequestBody as ruma_api::Outgoing>::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!(: <ResponseBody as ruma_api::Outgoing>::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: <RequestBody as ruma_api::Outgoing>::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: <ResponseBody as ruma_api::Outgoing>::Incoming =
|
||||
ruma_api::exports::serde_json::from_slice(
|
||||
http_response.into_body().as_slice(),
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
#response_init_fields
|
||||
|
@ -168,9 +168,7 @@ impl Request {
|
||||
})
|
||||
});
|
||||
|
||||
quote! {
|
||||
#(#fields,)*
|
||||
}
|
||||
quote! { #(#fields,)* }
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,46 +291,24 @@ impl TryFrom<RawRequest> 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
|
||||
};
|
||||
|
@ -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<RawResponse> 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user