diff --git a/ruma-api-macros/src/api.rs b/ruma-api-macros/src/api.rs index a7a42c88..b2024c98 100644 --- a/ruma-api-macros/src/api.rs +++ b/ruma-api-macros/src/api.rs @@ -160,7 +160,7 @@ impl ToTokens for Api { let decoded = ruma_api::exports::percent_encoding::percent_decode(segment) .decode_utf8_lossy(); - match ruma_api::exports::serde_json::from_str(decoded.deref()) { + match std::convert::TryFrom::try_from(decoded.deref()) { Ok(val) => val, Err(err) => { return Err( diff --git a/src/error.rs b/src/error.rs index 364f36a0..f90f37f8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -193,6 +193,7 @@ enum SerializationError { pub enum DeserializationError { Json(serde_json::Error), Query(serde_urlencoded::de::Error), + Ident(ruma_identifiers::Error), } impl Display for DeserializationError { @@ -200,6 +201,7 @@ impl Display for DeserializationError { match self { DeserializationError::Json(err) => Display::fmt(err, f), DeserializationError::Query(err) => Display::fmt(err, f), + DeserializationError::Ident(err) => Display::fmt(err, f), } } } @@ -217,3 +219,17 @@ impl From for DeserializationError { Self::Query(err) } } + +#[doc(hidden)] +impl From for DeserializationError { + fn from(err: ruma_identifiers::Error) -> Self { + Self::Ident(err) + } +} + +#[doc(hidden)] +impl From for DeserializationError { + fn from(err: std::convert::Infallible) -> Self { + match err {} + } +} diff --git a/tests/conversions.rs b/tests/conversions.rs new file mode 100644 index 00000000..55bdc578 --- /dev/null +++ b/tests/conversions.rs @@ -0,0 +1,61 @@ +use ruma_api::ruma_api; +use ruma_identifiers::UserId; + +ruma_api! { + metadata { + description: "Does something.", + method: POST, + name: "my_endpoint", + path: "/_matrix/foo/:bar/:baz", + rate_limited: false, + requires_authentication: false, + } + + request { + pub hello: String, + #[ruma_api(header = CONTENT_TYPE)] + pub world: String, + #[ruma_api(query)] + pub q1: String, + #[ruma_api(query)] + pub q2: u32, + #[ruma_api(path)] + pub bar: String, + #[ruma_api(path)] + pub baz: UserId, + } + + response { + pub hello: String, + #[ruma_api(header = CONTENT_TYPE)] + pub world: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub optional_flag: Option, + } +} + +#[test] +fn request_serde() -> Result<(), Box> { + use std::convert::TryFrom; + + let req = Request { + hello: "hi".to_owned(), + world: "test".to_owned(), + q1: "query_param_special_chars %/&@!".to_owned(), + q2: 55, + bar: "bar".to_owned(), + baz: UserId::try_from("@bazme:ruma.io")?, + }; + + let http_req = http::Request::>::try_from(req.clone())?; + let req2 = Request::try_from(http_req)?; + + assert_eq!(req.hello, req2.hello); + assert_eq!(req.world, req2.world); + assert_eq!(req.q1, req2.q1); + assert_eq!(req.q2, req2.q2); + assert_eq!(req.bar, req2.bar); + assert_eq!(req.baz, req2.baz); + + Ok(()) +}