Refactor Request/Response's TryFrom impl by generating match stmt

... by moving repetitive parts into a macro_rules macro
This commit is contained in:
Ragotzy.devin 2020-07-07 19:44:25 -04:00 committed by GitHub
parent 0d055e05d2
commit 4ff6c6ecbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 68 deletions

View File

@ -160,16 +160,10 @@ impl ToTokens for Api {
let extract_request_body =
if self.request.has_body_fields() || self.request.newtype_body_field().is_some() {
quote! {
let request_body: RequestBody =
match ruma_api::exports::serde_json::from_slice(request.body().as_slice()) {
Ok(body) => body,
Err(err) => {
return Err(
ruma_api::error::RequestDeserializationError::new(err, request)
.into()
);
}
};
let request_body: RequestBody = ::ruma_api::try_deserialize!(
request,
::ruma_api::exports::serde_json::from_slice(request.body().as_slice())
);
}
} else {
TokenStream::new()
@ -193,24 +187,17 @@ impl ToTokens for Api {
TokenStream::new()
};
let typed_response_body_decl = if self.response.has_body_fields()
|| self.response.newtype_body_field().is_some()
{
quote! {
let response_body: ResponseBody =
match ruma_api::exports::serde_json::from_slice(response.body().as_slice()) {
Ok(body) => body,
Err(err) => {
return Err(
ruma_api::error::ResponseDeserializationError::new(err, response)
.into()
);
}
};
}
} else {
TokenStream::new()
};
let typed_response_body_decl =
if self.response.has_body_fields() || self.response.newtype_body_field().is_some() {
quote! {
let response_body: ResponseBody = ::ruma_api::try_deserialize!(
response,
::ruma_api::exports::serde_json::from_slice(response.body().as_slice()),
);
}
} else {
TokenStream::new()
};
let response_init_fields = self.response.init_fields();

View File

@ -62,31 +62,19 @@ pub(crate) fn request_path_string_and_parse(
|(i, segment)| {
let path_var = &segment[1..];
let path_var_ident = Ident::new(path_var, Span::call_site());
quote! {
#path_var_ident: {
use std::ops::Deref as _;
use ruma_api::error::RequestDeserializationError;
let segment = path_segments.get(#i).unwrap().as_bytes();
let decoded = match ruma_api::exports::percent_encoding::percent_decode(
segment
).decode_utf8() {
Ok(x) => x,
Err(err) => {
return Err(
RequestDeserializationError::new(err, request).into()
);
}
};
match std::convert::TryFrom::try_from(decoded.deref()) {
Ok(val) => val,
Err(err) => {
return Err(
RequestDeserializationError::new(err, request).into()
);
}
}
let decoded = ::ruma_api::try_deserialize!(
request,
ruma_api::exports::percent_encoding::percent_decode(segment)
.decode_utf8(),
);
::ruma_api::try_deserialize!(request, std::convert::TryFrom::try_from(decoded.deref()))
}
}
},
@ -146,31 +134,21 @@ pub(crate) fn build_query_string(request: &Request) -> TokenStream {
pub(crate) fn extract_request_query(request: &Request) -> TokenStream {
if request.query_map_field().is_some() {
quote! {
let request_query = match ruma_api::exports::ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("")
) {
Ok(query) => query,
Err(err) => {
return Err(
ruma_api::error::RequestDeserializationError::new(err, request).into()
);
}
};
let request_query = ::ruma_api::try_deserialize!(
request,
::ruma_api::exports::ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("")
),
);
}
} else if request.has_query_fields() {
quote! {
let request_query: RequestQuery =
match ruma_api::exports::ruma_serde::urlencoded::from_str(
let request_query: RequestQuery = ::ruma_api::try_deserialize!(
request,
::ruma_api::exports::ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("")
) {
Ok(query) => query,
Err(err) => {
return Err(
ruma_api::error::RequestDeserializationError::new(err, request)
.into()
);
}
};
),
);
}
} else {
TokenStream::new()

View File

@ -267,6 +267,26 @@ pub struct Metadata {
pub requires_authentication: bool,
}
#[doc(hidden)]
#[macro_export]
macro_rules! try_deserialize {
($kind:ident, $call:expr $(,)?) => {
::ruma_api::try_deserialize!(@$kind, $kind, $call)
};
(@request, $kind:ident, $call:expr) => {
match $call {
Ok(val) => val,
Err(err) => return Err(::ruma_api::error::RequestDeserializationError::new(err, $kind).into()),
}
};
(@response, $kind:ident, $call:expr) => {
match $call {
Ok(val) => val,
Err(err) => return Err(::ruma_api::error::ResponseDeserializationError::new(err, $kind).into()),
}
};
}
#[cfg(test)]
mod tests {
/// PUT /_matrix/client/r0/directory/room/:room_alias