events: Remove / replace previous error types
This commit is contained in:
parent
976f90a1a2
commit
d213ee4718
@ -1,5 +1,14 @@
|
|||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
Breaking changes:
|
||||||
|
|
||||||
|
* `room::name::NameEventContent` now uses a custom `RoomName` type for its
|
||||||
|
`name` field and makes it public, in response the constructor and `name`
|
||||||
|
accessor had their types updated too
|
||||||
|
* Replace `InvalidEvent` by a more specific `FromStringError` for room name
|
||||||
|
validation
|
||||||
|
* Remove unused `FromStrError`
|
||||||
|
|
||||||
# 0.23.3
|
# 0.23.3
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
@ -33,6 +33,7 @@ ruma-identifiers = { version = "0.19.4", path = "../ruma-identifiers", features
|
|||||||
ruma-serde = { version = "0.4.2", path = "../ruma-serde" }
|
ruma-serde = { version = "0.4.2", path = "../ruma-serde" }
|
||||||
serde = { version = "1.0.118", features = ["derive"] }
|
serde = { version = "1.0.118", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.60", features = ["raw_value"] }
|
serde_json = { version = "1.0.60", features = ["raw_value"] }
|
||||||
|
thiserror = "1.0.25"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assign = "1.1.1"
|
assign = "1.1.1"
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
use std::{error::Error, fmt};
|
|
||||||
|
|
||||||
/// An error returned when attempting to create an event with data that would make it invalid.
|
|
||||||
///
|
|
||||||
/// This type is similar to [`InvalidEvent`](struct.InvalidEvent.html), but used during the
|
|
||||||
/// construction of a new event, as opposed to deserialization of an existing event from JSON.
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct InvalidInput(pub(crate) String);
|
|
||||||
|
|
||||||
impl fmt::Display for InvalidInput {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for InvalidInput {}
|
|
||||||
|
|
||||||
/// An error when attempting to create a value from a string via the `FromStr` trait.
|
|
||||||
#[derive(Clone, Eq, Debug, Hash, PartialEq)]
|
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
|
||||||
pub struct FromStrError;
|
|
||||||
|
|
||||||
impl fmt::Display for FromStrError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "failed to parse type from string")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for FromStrError {}
|
|
@ -572,145 +572,4 @@ mod tests {
|
|||||||
&& secret == "It's a secret to everybody"
|
&& secret == "It's a secret to everybody"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deserialization_failure() {
|
|
||||||
// Ensure that invalid JSON Creates a new `serde_json::Error` and not `InvalidEvent`
|
|
||||||
assert!(serde_json::from_str::<Raw<StartToDeviceEventContent>>("{").is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this fails because the error is a Validation error not deserialization?
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_structure_mismatch() {
|
|
||||||
// Missing several required fields.
|
|
||||||
let error =
|
|
||||||
from_json_value::<Raw<StartEventContent>>(json!({ "from_device": "123" }))
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("missing field"));
|
|
||||||
assert!(error.is_deserialization());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO re implement validation done in TryFromRaw else where
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_validation_missing_required_key_agreement_protocols() {
|
|
||||||
let json_data = json!({
|
|
||||||
"from_device": "123",
|
|
||||||
"transaction_id": "456",
|
|
||||||
"method": "m.sas.v1",
|
|
||||||
"key_agreement_protocols": [],
|
|
||||||
"hashes": ["sha256"],
|
|
||||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
|
||||||
"short_authentication_string": ["decimal"]
|
|
||||||
});
|
|
||||||
|
|
||||||
let error = from_json_value::<Raw<StartEventContent>>(json_data)
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("key_agreement_protocols"));
|
|
||||||
assert!(error.is_validation());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO re implement validation done in TryFromRaw else where
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_validation_missing_required_hashes() {
|
|
||||||
let json_data = json!({
|
|
||||||
"from_device": "123",
|
|
||||||
"transaction_id": "456",
|
|
||||||
"method": "m.sas.v1",
|
|
||||||
"key_agreement_protocols": ["curve25519"],
|
|
||||||
"hashes": [],
|
|
||||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
|
||||||
"short_authentication_string": ["decimal"]
|
|
||||||
});
|
|
||||||
let error = from_json_value::<Raw<StartEventContent>>(json_data)
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("hashes"));
|
|
||||||
assert!(error.is_validation());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO re implement validation done in TryFromRaw else where
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_validation_missing_required_message_authentication_codes() {
|
|
||||||
let json_data = json!({
|
|
||||||
"from_device": "123",
|
|
||||||
"transaction_id": "456",
|
|
||||||
"method": "m.sas.v1",
|
|
||||||
"key_agreement_protocols": ["curve25519"],
|
|
||||||
"hashes": ["sha256"],
|
|
||||||
"message_authentication_codes": [],
|
|
||||||
"short_authentication_string": ["decimal"]
|
|
||||||
});
|
|
||||||
let error = from_json_value::<Raw<StartEventContent>>(json_data)
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("message_authentication_codes"));
|
|
||||||
assert!(error.is_validation());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_validation_missing_required_short_authentication_string() {
|
|
||||||
let json_data = json!({
|
|
||||||
"from_device": "123",
|
|
||||||
"transaction_id": "456",
|
|
||||||
"method": "m.sas.v1",
|
|
||||||
"key_agreement_protocols": ["curve25519"],
|
|
||||||
"hashes": ["sha256"],
|
|
||||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
|
||||||
"short_authentication_string": []
|
|
||||||
});
|
|
||||||
let error = from_json_value::<Raw<StartEventContent>>(json_data)
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("short_authentication_string"));
|
|
||||||
assert!(error.is_validation());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO re implement validation done in TryFromRaw else where
|
|
||||||
/*
|
|
||||||
#[test]
|
|
||||||
fn deserialization_of_event_validates_content() {
|
|
||||||
// This JSON is missing the required value of "curve25519" for "key_agreement_protocols".
|
|
||||||
let json_data = json!({
|
|
||||||
"content": {
|
|
||||||
"from_device": "123",
|
|
||||||
"transaction_id": "456",
|
|
||||||
"method": "m.sas.v1",
|
|
||||||
"key_agreement_protocols": [],
|
|
||||||
"hashes": ["sha256"],
|
|
||||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
|
||||||
"short_authentication_string": ["decimal"]
|
|
||||||
},
|
|
||||||
"type": "m.key.verification.start"
|
|
||||||
});
|
|
||||||
let error = from_json_value::<Raw<StartEvent>>(json_data)
|
|
||||||
.unwrap()
|
|
||||||
.deserialize()
|
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(error.message().contains("key_agreement_protocols"));
|
|
||||||
assert!(error.is_validation());
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,6 @@ use serde_json::value::RawValue as RawJsonValue;
|
|||||||
use self::room::redaction::SyncRedactionEvent;
|
use self::room::redaction::SyncRedactionEvent;
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
mod error;
|
|
||||||
mod event_kinds;
|
mod event_kinds;
|
||||||
|
|
||||||
// Hack to allow both ruma-events itself and external crates (or tests) to use procedural macros
|
// Hack to allow both ruma-events itself and external crates (or tests) to use procedural macros
|
||||||
@ -186,11 +185,7 @@ pub mod typing;
|
|||||||
#[cfg(feature = "unstable-pre-spec")]
|
#[cfg(feature = "unstable-pre-spec")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
|
||||||
pub use self::relation::Relations;
|
pub use self::relation::Relations;
|
||||||
pub use self::{
|
pub use self::{enums::*, event_kinds::*};
|
||||||
enums::*,
|
|
||||||
error::{FromStrError, InvalidInput},
|
|
||||||
event_kinds::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Extra information about an event that is not incorporated into the event's
|
/// Extra information about an event that is not incorporated into the event's
|
||||||
/// hash.
|
/// hash.
|
||||||
|
@ -4,8 +4,9 @@ use std::convert::TryFrom;
|
|||||||
|
|
||||||
use ruma_events_macros::EventContent;
|
use ruma_events_macros::EventContent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{InvalidInput, StateEvent};
|
use crate::StateEvent;
|
||||||
|
|
||||||
/// The room name is a human-friendly string designed to be displayed to the end-user.
|
/// The room name is a human-friendly string designed to be displayed to the end-user.
|
||||||
pub type NameEvent = StateEvent<NameEventContent>;
|
pub type NameEvent = StateEvent<NameEventContent>;
|
||||||
@ -27,6 +28,7 @@ impl NameEventContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the room, if any.
|
/// The name of the room, if any.
|
||||||
|
#[deprecated = "You can access the name field directly."]
|
||||||
pub fn name(&self) -> Option<&RoomName> {
|
pub fn name(&self) -> Option<&RoomName> {
|
||||||
self.name.as_ref()
|
self.name.as_ref()
|
||||||
}
|
}
|
||||||
@ -34,19 +36,19 @@ impl NameEventContent {
|
|||||||
|
|
||||||
/// The name of a room.
|
/// The name of a room.
|
||||||
///
|
///
|
||||||
/// It should not exceed 255 characters and should not be empty.
|
/// It can't exceed 255 characters or be empty.
|
||||||
#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct RoomName(String);
|
pub struct RoomName(String);
|
||||||
|
|
||||||
impl TryFrom<String> for RoomName {
|
impl TryFrom<String> for RoomName {
|
||||||
type Error = InvalidInput;
|
type Error = FromStringError;
|
||||||
|
|
||||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
match value.len() {
|
match value.len() {
|
||||||
0 => Err(InvalidInput("a room name cannot be empty.".into())),
|
0 => Err(FromStringError::Empty),
|
||||||
1..=255 => Ok(RoomName(value)),
|
1..=255 => Ok(RoomName(value)),
|
||||||
_ => Err(InvalidInput("a room name cannot be more than 255 bytes.".into())),
|
_ => Err(FromStringError::TooLong),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,11 +70,24 @@ impl<'de> Deserialize<'de> for RoomName {
|
|||||||
|
|
||||||
match RoomName::try_from(str_name) {
|
match RoomName::try_from(str_name) {
|
||||||
Ok(name) => Ok(name),
|
Ok(name) => Ok(name),
|
||||||
Err(e) => Err(D::Error::custom(e.to_string())),
|
Err(e) => Err(D::Error::custom(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when converting a string to `RoomName`.
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum FromStringError {
|
||||||
|
/// Room name string was empty.
|
||||||
|
#[error("room name may not be empty")]
|
||||||
|
Empty,
|
||||||
|
|
||||||
|
/// Room name string exceeded 255 byte limit.
|
||||||
|
#[error("room name length may not exceed 255 bytes")]
|
||||||
|
TooLong,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user