Refactor InvalidEvent

This commit is contained in:
Jonas Platte 2019-10-23 01:41:09 +02:00
parent 665fe4f4f4
commit 922a35eced
2 changed files with 64 additions and 47 deletions

View File

@ -484,7 +484,7 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("missing field")); assert!(error.message().contains("missing field"));
assert!(error.json().is_some()); assert!(error.is_deserialization());
} }
#[test] #[test]
@ -498,7 +498,7 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("key_agreement_protocols")); assert!(error.message().contains("key_agreement_protocols"));
assert!(error.raw_data().is_some()); assert!(error.is_validation());
} }
#[test] #[test]
@ -512,7 +512,7 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("hashes")); assert!(error.message().contains("hashes"));
assert!(error.raw_data().is_some()); assert!(error.is_validation());
} }
#[test] #[test]
@ -526,7 +526,7 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("message_authentication_codes")); assert!(error.message().contains("message_authentication_codes"));
assert!(error.raw_data().is_some()); assert!(error.is_validation());
} }
#[test] #[test]
@ -540,7 +540,7 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("short_authentication_string")); assert!(error.message().contains("short_authentication_string"));
assert!(error.raw_data().is_some()); assert!(error.is_validation());
} }
#[test] #[test]
@ -555,6 +555,6 @@ mod tests {
.unwrap_err(); .unwrap_err();
assert!(error.message().contains("key_agreement_protocols")); assert!(error.message().contains("key_agreement_protocols"));
assert!(error.raw_data().is_some()); assert!(error.is_validation());
} }
} }

View File

@ -174,62 +174,79 @@ pub mod typing;
/// the event is otherwise invalid, a similar message will be provided, as well as a /// the event is otherwise invalid, a similar message will be provided, as well as a
/// `serde_json::Value` containing the raw JSON data as it was deserialized. /// `serde_json::Value` containing the raw JSON data as it was deserialized.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct InvalidEvent<T>(InnerInvalidEvent<T>); pub enum InvalidEvent {
/// An error that occured during deserialization.
Deserialization(DeserializationError),
impl<T> InvalidEvent<T> { /// An error that occured during raw event validation.
Validation(ValidationError),
/// Additional variants may be added in the future and will not be considered breaking changes
/// to ruma-events.
#[doc(hidden)]
__Nonexhaustive,
}
impl InvalidEvent {
/// A message describing why the event is invalid. /// A message describing why the event is invalid.
pub fn message(&self) -> String { pub fn message(&self) -> String {
match self.0 { match self {
InnerInvalidEvent::Deserialization { ref error, .. } => error.to_string(), InvalidEvent::Deserialization(err) => err.message.clone(),
InnerInvalidEvent::Validation { ref message, .. } => message.to_string(), InvalidEvent::Validation(err) => err.message.clone(),
InvalidEvent::__Nonexhaustive => {
panic!("__Nonexhaustive enum variant is not intended for use.")
}
}
}
/// The `serde_json::Value` representation of the invalid event.
pub fn json(&self) -> &Value {
match self {
InvalidEvent::Deserialization(err) => &err.json,
InvalidEvent::Validation(err) => &err.json,
InvalidEvent::__Nonexhaustive => {
panic!("__Nonexhaustive enum variant is not intended for use.")
}
} }
} }
/// The raw event data, if deserialization succeeded but validation failed. /// Returns whether this is a deserialization error.
pub fn raw_data(&self) -> Option<&T> { pub fn is_deserialization(&self) -> bool {
match self.0 { match self {
InnerInvalidEvent::Validation { ref raw_data, .. } => Some(raw_data), InvalidEvent::Deserialization(_) => true,
_ => None, _ => false,
} }
} }
/// The `serde_json::Value` representation of the invalid event, if deserialization failed. /// Returns whether this is a validation error.
pub fn json(&self) -> Option<&Value> { pub fn is_validation(&self) -> bool {
match self.0 { match self {
InnerInvalidEvent::Deserialization { ref json, .. } => Some(json), InvalidEvent::Validation(_) => true,
_ => None, _ => false,
} }
} }
} }
impl<T> Display for InvalidEvent<T> { impl Display for InvalidEvent {
fn fmt(&self, f: &mut Formatter) -> FmtResult { fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(f, "{}", self.message()) write!(f, "{}", self.message())
} }
} }
impl<T: Debug> Error for InvalidEvent<T> {} impl Error for InvalidEvent {}
/// An event that is malformed or otherwise invalid. /// An error that occured during deserialization.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum InnerInvalidEvent<T> { pub struct DeserializationError {
/// An event that failed to deserialize from JSON. message: String,
Deserialization {
/// The raw `serde_json::Value` representation of the invalid event.
json: Value, json: Value,
}
/// The deserialization error returned by serde. /// An error that occured during raw event validation.
error: String, #[derive(Clone, Debug)]
}, pub struct ValidationError {
/// An event that deserialized but failed validation.
Validation {
/// The event data that failed validation.
raw_data: T,
/// A message describing why the event was invalid.
message: String, message: String,
}, json: Value,
} }
/// An error returned when attempting to create an event with data that would make it invalid. /// An error returned when attempting to create an event with data that would make it invalid.
@ -294,12 +311,12 @@ pub enum EventResult<T: TryFromRaw> {
/// `T` failed either deserialization or validation. /// `T` failed either deserialization or validation.
/// ///
/// `InvalidEvent` contains the error message and the raw data. /// `InvalidEvent` contains the error message and the raw data.
Err(InvalidEvent<T::Raw>), Err(InvalidEvent),
} }
impl<T: TryFromRaw> EventResult<T> { impl<T: TryFromRaw> EventResult<T> {
/// Convert `EventResult<T>` into the equivalent `std::result::Result<T, InvalidEvent>`. /// Convert `EventResult<T>` into the equivalent `std::result::Result<T, InvalidEvent>`.
pub fn into_result(self) -> Result<T, InvalidEvent<T::Raw>> { pub fn into_result(self) -> Result<T, InvalidEvent> {
match self { match self {
EventResult::Ok(t) => Ok(t), EventResult::Ok(t) => Ok(t),
EventResult::Err(invalid_event) => Err(invalid_event), EventResult::Err(invalid_event) => Err(invalid_event),
@ -320,10 +337,10 @@ where
let raw_data: T::Raw = match serde_json::from_value(json.clone()) { let raw_data: T::Raw = match serde_json::from_value(json.clone()) {
Ok(raw) => raw, Ok(raw) => raw,
Err(error) => { Err(error) => {
return Ok(EventResult::Err(InvalidEvent( return Ok(EventResult::Err(InvalidEvent::Deserialization(
InnerInvalidEvent::Deserialization { DeserializationError {
json, json,
error: error.to_string(), message: error.to_string(),
}, },
))); )));
} }
@ -331,10 +348,10 @@ where
match T::try_from_raw(raw_data) { match T::try_from_raw(raw_data) {
Ok(value) => Ok(EventResult::Ok(value)), Ok(value) => Ok(EventResult::Ok(value)),
Err((err, raw_data)) => Ok(EventResult::Err(InvalidEvent( Err((err, _)) => Ok(EventResult::Err(InvalidEvent::Validation(
InnerInvalidEvent::Validation { ValidationError {
message: err.to_string(), message: err.to_string(),
raw_data, json,
}, },
))), ))),
} }