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! {
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user