diff --git a/ruma-events-macros/tests/ruma_events_macros.rs b/ruma-events-macros/tests/ruma_events_macros.rs index 40af5588..76bc70ba 100644 --- a/ruma-events-macros/tests/ruma_events_macros.rs +++ b/ruma-events-macros/tests/ruma_events_macros.rs @@ -1,12 +1,10 @@ -use std::{ - fmt::{Debug, Display, Formatter, Result as FmtResult}, - marker::PhantomData, -}; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use serde::{ - de::{Error as SerdeError, Visitor}, + de::{DeserializeOwned, Error as SerdeError, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; +use serde_json::Value; /// The type of an event. #[derive(Clone, Debug, PartialEq)] @@ -114,9 +112,9 @@ pub trait FromRaw: Sized { fn from_raw(_: Self::Raw) -> Self; } -pub trait TryFromRaw { +pub trait TryFromRaw: Sized { /// The raw form of this event that deserialization falls back to if deserializing `Self` fails. - type Raw; + type Raw: DeserializeOwned; type Err: Into; fn try_from_raw(_: Self::Raw) -> Result; @@ -131,7 +129,41 @@ impl TryFromRaw for T { } } -enum Void {} +impl<'de, T> Deserialize<'de> for EventResult +where + T: TryFromRaw, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let json = serde_json::Value::deserialize(deserializer)?; + + let raw_data: T::Raw = match serde_json::from_value(json.clone()) { + Ok(raw) => raw, + Err(error) => { + return Ok(EventResult::Err(InvalidEvent( + InnerInvalidEvent::Deserialization { + json, + error: error.to_string(), + }, + ))); + } + }; + + match T::try_from_raw(raw_data) { + Ok(value) => Ok(EventResult::Ok(value)), + Err((msg, raw_data)) => Ok(EventResult::Err(InvalidEvent( + InnerInvalidEvent::Validation { + message: msg.into(), + raw_data, + }, + ))), + } + } +} + +pub enum Void {} impl From for String { fn from(v: Void) -> Self { @@ -196,15 +228,22 @@ pub struct InvalidEvent(InnerInvalidEvent); /// An event that is malformed or otherwise invalid. #[derive(Debug)] enum InnerInvalidEvent { + /// An event that failed to deserialize from JSON. + Deserialization { + /// The raw `serde_json::Value` representation of the invalid event. + json: Value, + + /// The deserialization error returned by serde. + error: String, + }, + /// An event that deserialized but failed validation. Validation { - /// The raw `serde_json::Value` representation of the invalid event. - json: serde_json::Value, + /// The event data that failed validation. + raw_data: T, /// An message describing why the event was invalid. message: String, - - dummy: PhantomData, }, } diff --git a/src/ignored_user_list.rs b/src/ignored_user_list.rs index 341aa3ec..1661d768 100644 --- a/src/ignored_user_list.rs +++ b/src/ignored_user_list.rs @@ -40,6 +40,7 @@ impl Serialize for IgnoredUserListEvent { #[derive(Clone, Debug, PartialEq, Serialize)] pub struct IgnoredUserListEventContent { /// A list of users to ignore. + #[serde(with = "vec_as_map_of_empty")] pub ignored_users: Vec, } @@ -97,7 +98,10 @@ mod tests { let json = serde_json::to_string(&ignored_user_list_event).unwrap(); - assert_eq!(json, r#"{"content":{"ignored_users":{"@carl:example.com":{}}},"type":"m.ignored_user_list"}"#); + assert_eq!( + json, + r#"{"content":{"ignored_users":{"@carl:example.com":{}}},"type":"m.ignored_user_list"}"# + ); } #[test] diff --git a/src/lib.rs b/src/lib.rs index c6bfe314..797ea10d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -882,9 +882,9 @@ where } } -/// Serde serialization and deserialization functions that map a `Vec` to a +/// Serde serialization and deserialization functions that map a `Vec` to a `HashMap`. /// -/// To be used as `#[serde(with = "vec_as_map_of_empty")] +/// To be used as `#[serde(with = "vec_as_map_of_empty")]` mod vec_as_map_of_empty { use super::Empty; use serde::{Deserialize, Deserializer, Serialize, Serializer};