Replace FromStr/TryFrom impls with Deserialize using EventResult.
This commit is contained in:
parent
e11ac61bef
commit
f1927b2e5b
83
src/gen.rs
83
src/gen.rs
@ -360,40 +360,31 @@ impl ToTokens for RumaEvent {
|
||||
}
|
||||
|
||||
quote! {
|
||||
impl std::str::FromStr for #content_name {
|
||||
type Err = crate::InvalidEvent;
|
||||
impl<'de> serde::Deserialize<'de> for crate::EventResult<#content_name> {
|
||||
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.
|
||||
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||
let raw = match serde_json::from_str::<raw::#content_name>(json) {
|
||||
let raw: raw::#content_name = match serde_json::from_value(json.clone()) {
|
||||
Ok(raw) => raw,
|
||||
Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
||||
Ok(value) => {
|
||||
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Validation {
|
||||
json: value,
|
||||
Err(error) => {
|
||||
return Ok(crate::EventResult::Err(crate::InvalidEvent(
|
||||
crate::InnerInvalidEvent::Validation {
|
||||
json,
|
||||
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)*
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
TokenStream::new()
|
||||
@ -408,38 +399,28 @@ impl ToTokens for RumaEvent {
|
||||
|
||||
#content
|
||||
|
||||
impl std::str::FromStr for #name {
|
||||
type Err = crate::InvalidEvent;
|
||||
impl<'de> serde::Deserialize<'de> for crate::EventResult<#name> {
|
||||
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.
|
||||
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||
let raw = match serde_json::from_str::<raw::#name>(json) {
|
||||
let raw: raw::#name = match serde_json::from_value(json.clone()) {
|
||||
Ok(raw) => raw,
|
||||
Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
||||
Ok(value) => {
|
||||
return Err(crate::InvalidEvent(crate::InnerInvalidEvent::Validation {
|
||||
json: value,
|
||||
Err(error) => {
|
||||
return Ok(crate::EventResult::Err(crate::InvalidEvent(
|
||||
crate::InnerInvalidEvent::Validation {
|
||||
json,
|
||||
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)*
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
pub trait Event
|
||||
where
|
||||
@ -140,12 +162,6 @@ 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 deserialization error returned by serde.
|
||||
error: serde_json::Error,
|
||||
},
|
||||
|
||||
/// An event that deserialized but failed validation.
|
||||
Validation {
|
||||
/// 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 serde_json::Value;
|
||||
|
||||
use super::EventResult;
|
||||
|
||||
ruma_event! {
|
||||
/// Informs the room about what room aliases it has been given.
|
||||
AliasesEvent {
|
||||
@ -248,7 +266,8 @@ pub mod common_case {
|
||||
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 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 {
|
||||
content: AliasesEventContent {
|
||||
|
Loading…
x
Reference in New Issue
Block a user