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

View File

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

View File

@ -267,6 +267,26 @@ pub struct Metadata {
pub requires_authentication: bool, 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)] #[cfg(test)]
mod tests { mod tests {
/// PUT /_matrix/client/r0/directory/room/:room_alias /// PUT /_matrix/client/r0/directory/room/:room_alias