Replace FromStr/TryFrom impls with Deserialize using EventResult.

This commit is contained in:
Jimmy Cuadra 2019-08-22 17:31:13 -07:00
parent e11ac61bef
commit f1927b2e5b
2 changed files with 58 additions and 58 deletions

View File

@ -360,40 +360,31 @@ impl ToTokens for RumaEvent {
} }
quote! { quote! {
impl std::str::FromStr for #content_name { impl<'de> serde::Deserialize<'de> for crate::EventResult<#content_name> {
type Err = crate::InvalidEvent; fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let json = serde_json::Value::deserialize(deserializer)?;
/// Attempt to create `Self` from parsing a string of JSON data. let raw: raw::#content_name = match serde_json::from_value(json.clone()) {
fn from_str(json: &str) -> Result<Self, Self::Err> {
let raw = match serde_json::from_str::<raw::#content_name>(json) {
Ok(raw) => raw, Ok(raw) => raw,
Err(error) => match serde_json::from_str::<serde_json::Value>(json) { Err(error) => {
Ok(value) => { return Ok(crate::EventResult::Err(crate::InvalidEvent(
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Validation { crate::InnerInvalidEvent::Validation {
json: value, json,
message: error.to_string(), message: error.to_string(),
})); },
} )));
Err(error) => { }
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Deserialization { error }));
}
},
}; };
Ok(Self { Ok(crate::EventResult::Ok(#content_name {
#(#content_field_values)* #(#content_field_values)*
}) }))
} }
} }
impl<'a> std::convert::TryFrom<&'a str> for #content_name {
type Error = crate::InvalidEvent;
/// Attempt to create `Self` from parsing a string of JSON data.
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
std::str::FromStr::from_str(json)
}
}
} }
} else { } else {
TokenStream::new() TokenStream::new()
@ -408,38 +399,28 @@ impl ToTokens for RumaEvent {
#content #content
impl std::str::FromStr for #name { impl<'de> serde::Deserialize<'de> for crate::EventResult<#name> {
type Err = crate::InvalidEvent; fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let json = serde_json::Value::deserialize(deserializer)?;
/// Attempt to create `Self` from parsing a string of JSON data. let raw: raw::#name = match serde_json::from_value(json.clone()) {
fn from_str(json: &str) -> Result<Self, Self::Err> {
let raw = match serde_json::from_str::<raw::#name>(json) {
Ok(raw) => raw, Ok(raw) => raw,
Err(error) => match serde_json::from_str::<serde_json::Value>(json) { Err(error) => {
Ok(value) => { return Ok(crate::EventResult::Err(crate::InvalidEvent(
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Validation { crate::InnerInvalidEvent::Validation {
json: value, json,
message: error.to_string(), message: error.to_string(),
})); },
} )));
Err(error) => { }
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Deserialization { error }));
}
},
}; };
Ok(Self { Ok(crate::EventResult::Ok(#name {
#(#try_from_field_values)* #(#try_from_field_values)*
}) }))
}
}
impl<'a> std::convert::TryFrom<&'a str> for #name {
type Error = crate::InvalidEvent;
/// Attempt to create `Self` from parsing a string of JSON data.
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
std::str::FromStr::from_str(json)
} }
} }

View File

@ -80,6 +80,28 @@ impl<'de> Deserialize<'de> for EventType {
} }
} }
/// The result of deserializing an event, which may or may not be valid.
#[derive(Debug)]
pub enum EventResult<T> {
/// `T` deserialized and validated successfully.
Ok(T),
/// `T` deserialized but was invalid.
///
/// `InvalidEvent` contains the original input.
Err(InvalidEvent),
}
impl<T> EventResult<T> {
/// Convert `EventResult<T>` into the equivalent `std::result::Result<T, InvalidEvent>`.
pub fn into_result(self) -> Result<T, InvalidEvent> {
match self {
EventResult::Ok(t) => Ok(t),
EventResult::Err(invalid_event) => Err(invalid_event),
}
}
}
/// A basic event. /// A basic event.
pub trait Event pub trait Event
where where
@ -140,12 +162,6 @@ pub struct InvalidEvent(InnerInvalidEvent);
/// An event that is malformed or otherwise invalid. /// An event that is malformed or otherwise invalid.
#[derive(Debug)] #[derive(Debug)]
enum InnerInvalidEvent { enum InnerInvalidEvent {
/// An event that failed to deserialize from JSON.
Deserialization {
/// The deserialization error returned by serde.
error: serde_json::Error,
},
/// An event that deserialized but failed validation. /// An event that deserialized but failed validation.
Validation { Validation {
/// The raw `serde_json::Value` representation of the invalid event. /// The raw `serde_json::Value` representation of the invalid event.
@ -165,6 +181,8 @@ pub mod common_case {
use ruma_identifiers::{EventId, RoomAliasId, RoomId, UserId}; use ruma_identifiers::{EventId, RoomAliasId, RoomId, UserId};
use serde_json::Value; use serde_json::Value;
use super::EventResult;
ruma_event! { ruma_event! {
/// Informs the room about what room aliases it has been given. /// Informs the room about what room aliases it has been given.
AliasesEvent { AliasesEvent {
@ -248,7 +266,8 @@ pub mod common_case {
fn deserialization() { fn deserialization() {
let json = r##"{"content":{"aliases":["#room:example.org"]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"prev_content":{"aliases":[]},"room_id":"!n8f893n9:example.com","sender":"@carl:example.com","state_key":"example.com","unsigned":{"foo":"bar"},"type":"m.room.aliases"}"##; let json = r##"{"content":{"aliases":["#room:example.org"]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"prev_content":{"aliases":[]},"room_id":"!n8f893n9:example.com","sender":"@carl:example.com","state_key":"example.com","unsigned":{"foo":"bar"},"type":"m.room.aliases"}"##;
let actual: AliasesEvent = json.parse().unwrap(); let event_result: EventResult<AliasesEvent> = serde_json::from_str(json).unwrap();
let actual: AliasesEvent = event_result.into_result().unwrap();
let expected = AliasesEvent { let expected = AliasesEvent {
content: AliasesEventContent { content: AliasesEventContent {