WIP
This commit is contained in:
parent
c309eed2ae
commit
91d564dcf8
@ -14,7 +14,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ruma-identifiers = "0.14.0"
|
ruma-identifiers = "0.14.0"
|
||||||
ruma-events-macros = "0.1.0"
|
ruma-events-macros = { version = "0.1.0", path = "../ruma-events-macros" }
|
||||||
serde_json = "1.0.40"
|
serde_json = "1.0.40"
|
||||||
|
|
||||||
[dependencies.js_int]
|
[dependencies.js_int]
|
||||||
|
185
src/lib.rs
185
src/lib.rs
@ -115,9 +115,10 @@
|
|||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Error as FmtError, Formatter, Result as FmtResult},
|
fmt::{Debug, Display, Error as FmtError, Formatter, Result as FmtResult},
|
||||||
str::FromStr,
|
hash::Hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
use js_int::UInt;
|
use js_int::UInt;
|
||||||
@ -129,19 +130,19 @@ use serde::{
|
|||||||
};
|
};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
pub use custom::CustomEvent;
|
// pub use custom::CustomEvent;
|
||||||
pub use custom_room::CustomRoomEvent;
|
// pub use custom_room::CustomRoomEvent;
|
||||||
pub use custom_state::CustomStateEvent;
|
// pub use custom_state::CustomStateEvent;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
/// Enums for heterogeneous collections of events.
|
// /// Enums for heterogeneous collections of events.
|
||||||
pub mod collections {
|
// pub mod collections {
|
||||||
pub mod all;
|
// pub mod all;
|
||||||
pub mod only;
|
// pub mod only;
|
||||||
}
|
// }
|
||||||
pub mod direct;
|
pub mod direct;
|
||||||
pub mod dummy;
|
pub mod dummy;
|
||||||
pub mod forwarded_room_key;
|
pub mod forwarded_room_key;
|
||||||
@ -261,6 +262,43 @@ impl<T> EventResult<T> {
|
|||||||
EventResult::Err(invalid_event) => Err(invalid_event),
|
EventResult::Err(invalid_event) => Err(invalid_event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for creating a validation error with an error message and the JSON that failed
|
||||||
|
/// validation.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn validation_error(message: String, json: serde_json::Value) -> Self {
|
||||||
|
EventResult::Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
json,
|
||||||
|
message,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, K, V> Deserialize<'de> for EventResult<HashMap<K, V>>
|
||||||
|
where
|
||||||
|
K: for<'inner> Deserialize<'inner> + Eq + Hash,
|
||||||
|
V: for<'inner> Deserialize<'inner>,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let json = serde_json::Value::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
let hash_map: HashMap<K, V> = match serde_json::from_value(json.clone()) {
|
||||||
|
Ok(hash_map) => hash_map,
|
||||||
|
Err(error) => {
|
||||||
|
return Ok(EventResult::Err(InvalidEvent(
|
||||||
|
InnerInvalidEvent::Validation {
|
||||||
|
json,
|
||||||
|
message: error.to_string(),
|
||||||
|
},
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(EventResult::Ok(hash_map))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error when attempting to create a value from a string via the `FromStr` trait.
|
/// An error when attempting to create a value from a string via the `FromStr` trait.
|
||||||
@ -320,6 +358,29 @@ impl<'de> Deserialize<'de> for Empty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for EventResult<Empty> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let json = serde_json::Value::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
let empty: Empty = match serde_json::from_value(json.clone()) {
|
||||||
|
Ok(empty) => empty,
|
||||||
|
Err(error) => {
|
||||||
|
return Ok(EventResult::Err(InvalidEvent(
|
||||||
|
InnerInvalidEvent::Validation {
|
||||||
|
json,
|
||||||
|
message: error.to_string(),
|
||||||
|
},
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(EventResult::Ok(empty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The type of an event.
|
/// The type of an event.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum EventType {
|
pub enum EventType {
|
||||||
@ -464,7 +525,9 @@ pub enum EventType {
|
|||||||
/// A basic event.
|
/// A basic event.
|
||||||
pub trait Event
|
pub trait Event
|
||||||
where
|
where
|
||||||
Self: Debug + FromStr + Serialize,
|
Self: Debug + Serialize + Sized,
|
||||||
|
for<'de> EventResult<Self>: Deserialize<'de>,
|
||||||
|
for<'de> EventResult<Self::Content>: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
/// The type of this event's `content` field.
|
/// The type of this event's `content` field.
|
||||||
type Content: Debug + Serialize;
|
type Content: Debug + Serialize;
|
||||||
@ -477,7 +540,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An event within the context of a room.
|
/// An event within the context of a room.
|
||||||
pub trait RoomEvent: Event {
|
pub trait RoomEvent: Event
|
||||||
|
where
|
||||||
|
for<'de> EventResult<Self>: Deserialize<'de>,
|
||||||
|
for<'de> EventResult<<Self as Event>::Content>: Deserialize<'de>,
|
||||||
|
{
|
||||||
/// The unique identifier for the event.
|
/// The unique identifier for the event.
|
||||||
fn event_id(&self) -> &EventId;
|
fn event_id(&self) -> &EventId;
|
||||||
|
|
||||||
@ -499,7 +566,11 @@ pub trait RoomEvent: Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An event that describes persistent state about a room.
|
/// An event that describes persistent state about a room.
|
||||||
pub trait StateEvent: RoomEvent {
|
pub trait StateEvent: RoomEvent
|
||||||
|
where
|
||||||
|
for<'de> EventResult<Self>: Deserialize<'de>,
|
||||||
|
for<'de> EventResult<<Self as Event>::Content>: Deserialize<'de>,
|
||||||
|
{
|
||||||
/// The previous content for this state key, if any.
|
/// The previous content for this state key, if any.
|
||||||
fn prev_content(&self) -> Option<&Self::Content>;
|
fn prev_content(&self) -> Option<&Self::Content>;
|
||||||
|
|
||||||
@ -507,56 +578,56 @@ pub trait StateEvent: RoomEvent {
|
|||||||
fn state_key(&self) -> &str;
|
fn state_key(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod custom {
|
// mod custom {
|
||||||
use ruma_events_macros::ruma_event;
|
// use ruma_events_macros::ruma_event;
|
||||||
use serde_json::Value;
|
// use serde_json::Value;
|
||||||
|
|
||||||
ruma_event! {
|
// ruma_event! {
|
||||||
/// A custom basic event not covered by the Matrix specification.
|
// /// A custom basic event not covered by the Matrix specification.
|
||||||
CustomEvent {
|
// CustomEvent {
|
||||||
kind: Event,
|
// kind: Event,
|
||||||
event_type: Custom,
|
// event_type: Custom,
|
||||||
content_type_alias: {
|
// content_type_alias: {
|
||||||
/// The payload for `CustomEvent`.
|
// /// The payload for `CustomEvent`.
|
||||||
Value
|
// Value
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod custom_room {
|
// mod custom_room {
|
||||||
use ruma_events_macros::ruma_event;
|
// use ruma_events_macros::ruma_event;
|
||||||
use serde_json::Value;
|
// use serde_json::Value;
|
||||||
|
|
||||||
ruma_event! {
|
// ruma_event! {
|
||||||
/// A custom room event not covered by the Matrix specification.
|
// /// A custom room event not covered by the Matrix specification.
|
||||||
CustomRoomEvent {
|
// CustomRoomEvent {
|
||||||
kind: RoomEvent,
|
// kind: RoomEvent,
|
||||||
event_type: Custom,
|
// event_type: Custom,
|
||||||
content_type_alias: {
|
// content_type_alias: {
|
||||||
/// The payload for `CustomRoomEvent`.
|
// /// The payload for `CustomRoomEvent`.
|
||||||
Value
|
// Value
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod custom_state {
|
// mod custom_state {
|
||||||
use ruma_events_macros::ruma_event;
|
// use ruma_events_macros::ruma_event;
|
||||||
use serde_json::Value;
|
// use serde_json::Value;
|
||||||
|
|
||||||
ruma_event! {
|
// ruma_event! {
|
||||||
/// A custom state event not covered by the Matrix specification.
|
// /// A custom state event not covered by the Matrix specification.
|
||||||
CustomStateEvent {
|
// CustomStateEvent {
|
||||||
kind: StateEvent,
|
// kind: StateEvent,
|
||||||
event_type: Custom,
|
// event_type: Custom,
|
||||||
content_type_alias: {
|
// content_type_alias: {
|
||||||
/// The payload for `CustomStateEvent`.
|
// /// The payload for `CustomStateEvent`.
|
||||||
Value
|
// Value
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Display for EventType {
|
impl Display for EventType {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||||
|
755
src/stripped.rs
755
src/stripped.rs
@ -5,11 +5,11 @@
|
|||||||
//! state event to be created, when the other fields can be inferred from a larger context, or where
|
//! state event to be created, when the other fields can be inferred from a larger context, or where
|
||||||
//! the other fields are otherwise inapplicable.
|
//! the other fields are otherwise inapplicable.
|
||||||
|
|
||||||
use std::{convert::TryFrom, str::FromStr};
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use ruma_identifiers::UserId;
|
use ruma_identifiers::UserId;
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use serde_json::{from_value, to_string, Value};
|
use serde_json::from_value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
room::{
|
room::{
|
||||||
@ -20,7 +20,7 @@ use crate::{
|
|||||||
power_levels::PowerLevelsEventContent, third_party_invite::ThirdPartyInviteEventContent,
|
power_levels::PowerLevelsEventContent, third_party_invite::ThirdPartyInviteEventContent,
|
||||||
topic::TopicEventContent,
|
topic::TopicEventContent,
|
||||||
},
|
},
|
||||||
EventType, InnerInvalidEvent, InvalidEvent,
|
EventResult, EventType, InnerInvalidEvent, InvalidEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A stripped-down version of a state event that is included along with some other events.
|
/// A stripped-down version of a state event that is included along with some other events.
|
||||||
@ -81,207 +81,6 @@ pub struct StrippedStateContent<C> {
|
|||||||
pub sender: UserId,
|
pub sender: UserId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for StrippedState {
|
|
||||||
type Err = InvalidEvent;
|
|
||||||
|
|
||||||
/// Attempt to create `Self` from parsing a string of JSON data.
|
|
||||||
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
|
||||||
let value = match serde_json::from_str::<Value>(json) {
|
|
||||||
Ok(value) => value,
|
|
||||||
Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
|
||||||
Ok(value) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: error.to_string(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Err(error) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Deserialization { error }));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let event_type_value = match value.get("type") {
|
|
||||||
Some(value) => value.clone(),
|
|
||||||
None => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "missing field `type`".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
|
||||||
Ok(event_type) => event_type,
|
|
||||||
Err(error) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: error.to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match event_type {
|
|
||||||
EventType::RoomAliases => Ok(StrippedState::RoomAliases(json.parse()?)),
|
|
||||||
EventType::RoomAvatar => Ok(StrippedState::RoomAvatar(json.parse()?)),
|
|
||||||
EventType::RoomCanonicalAlias => Ok(StrippedState::RoomCanonicalAlias(json.parse()?)),
|
|
||||||
EventType::RoomCreate => Ok(StrippedState::RoomCreate(json.parse()?)),
|
|
||||||
EventType::RoomGuestAccess => Ok(StrippedState::RoomGuestAccess(json.parse()?)),
|
|
||||||
EventType::RoomHistoryVisibility => {
|
|
||||||
Ok(StrippedState::RoomHistoryVisibility(json.parse()?))
|
|
||||||
}
|
|
||||||
EventType::RoomJoinRules => Ok(StrippedState::RoomJoinRules(json.parse()?)),
|
|
||||||
EventType::RoomMember => Ok(StrippedState::RoomMember(json.parse()?)),
|
|
||||||
EventType::RoomName => Ok(StrippedState::RoomName(json.parse()?)),
|
|
||||||
EventType::RoomPowerLevels => Ok(StrippedState::RoomPowerLevels(json.parse()?)),
|
|
||||||
EventType::RoomThirdPartyInvite => {
|
|
||||||
Ok(StrippedState::RoomThirdPartyInvite(json.parse()?))
|
|
||||||
}
|
|
||||||
EventType::RoomTopic => Ok(StrippedState::RoomTopic(json.parse()?)),
|
|
||||||
_ => Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "not a state event".to_string(),
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<&'a str> for StrippedState {
|
|
||||||
type Error = InvalidEvent;
|
|
||||||
|
|
||||||
/// Attempt to create `Self` from parsing a string of JSON data.
|
|
||||||
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
|
||||||
FromStr::from_str(json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for StrippedState {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
match *self {
|
|
||||||
StrippedState::RoomAliases(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomAvatar(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomCanonicalAlias(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomCreate(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomGuestAccess(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomHistoryVisibility(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomJoinRules(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomMember(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomName(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomPowerLevels(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomThirdPartyInvite(ref event) => event.serialize(serializer),
|
|
||||||
StrippedState::RoomTopic(ref event) => event.serialize(serializer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> FromStr for StrippedStateContent<C>
|
|
||||||
where
|
|
||||||
C: FromStr,
|
|
||||||
<C as FromStr>::Err: ToString,
|
|
||||||
{
|
|
||||||
type Err = InvalidEvent;
|
|
||||||
|
|
||||||
/// Attempt to create `Self` from parsing a string of JSON data.
|
|
||||||
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
|
||||||
let value = match serde_json::from_str::<Value>(json) {
|
|
||||||
Ok(value) => value,
|
|
||||||
Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
|
||||||
Ok(value) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: error.to_string(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Err(error) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Deserialization { error }));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let event_type_value = match value.get("type") {
|
|
||||||
Some(value) => value.clone(),
|
|
||||||
None => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "missing field `type`".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
|
||||||
Ok(event_type) => event_type,
|
|
||||||
Err(error) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: error.to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = match value.get("content") {
|
|
||||||
Some(content_value) => match content_value.as_object() {
|
|
||||||
Some(content) => content,
|
|
||||||
None => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "field `content` must be an object".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "missing field `content`".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unwrap is safe because we already know this can deserialize to a `Value`.
|
|
||||||
let json_string = to_string(content).unwrap();
|
|
||||||
|
|
||||||
match event_type {
|
|
||||||
EventType::RoomAliases => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomAvatar => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomCanonicalAlias => {
|
|
||||||
stripped_state_content(&json_string, event_type, value)
|
|
||||||
}
|
|
||||||
EventType::RoomCreate => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomGuestAccess => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomHistoryVisibility => {
|
|
||||||
stripped_state_content(&json_string, event_type, value)
|
|
||||||
}
|
|
||||||
EventType::RoomJoinRules => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomMember => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomName => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomPowerLevels => stripped_state_content(&json_string, event_type, value),
|
|
||||||
EventType::RoomThirdPartyInvite => {
|
|
||||||
stripped_state_content(&json_string, event_type, value)
|
|
||||||
}
|
|
||||||
EventType::RoomTopic => stripped_state_content(&json_string, event_type, value),
|
|
||||||
_ => Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "not a state event".to_string(),
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, C> TryFrom<&'a str> for StrippedStateContent<C>
|
|
||||||
where
|
|
||||||
C: FromStr,
|
|
||||||
<C as FromStr>::Err: ToString,
|
|
||||||
{
|
|
||||||
type Error = InvalidEvent;
|
|
||||||
|
|
||||||
/// Attempt to create `Self` from parsing a string of JSON data.
|
|
||||||
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
|
||||||
FromStr::from_str(json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A stripped-down version of the *m.room.aliases* event.
|
/// A stripped-down version of the *m.room.aliases* event.
|
||||||
pub type StrippedRoomAliases = StrippedStateContent<AliasesEventContent>;
|
pub type StrippedRoomAliases = StrippedStateContent<AliasesEventContent>;
|
||||||
|
|
||||||
@ -318,75 +117,499 @@ pub type StrippedRoomThirdPartyInvite = StrippedStateContent<ThirdPartyInviteEve
|
|||||||
/// A stripped-down version of the *m.room.topic* event.
|
/// A stripped-down version of the *m.room.topic* event.
|
||||||
pub type StrippedRoomTopic = StrippedStateContent<TopicEventContent>;
|
pub type StrippedRoomTopic = StrippedStateContent<TopicEventContent>;
|
||||||
|
|
||||||
/// Reduces the boilerplate in the match arms of `impl FromStr for StrippedState`.
|
impl<'de> Deserialize<'de> for EventResult<StrippedState> {
|
||||||
#[inline]
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
fn stripped_state_content<C>(
|
where
|
||||||
json: &str,
|
D: Deserializer<'de>,
|
||||||
event_type: EventType,
|
{
|
||||||
value: Value,
|
let value = serde_json::Value::deserialize(deserializer)?;
|
||||||
) -> Result<StrippedStateContent<C>, InvalidEvent>
|
|
||||||
where
|
|
||||||
C: FromStr,
|
|
||||||
<C as FromStr>::Err: ToString,
|
|
||||||
{
|
|
||||||
let content = match json.parse::<C>() {
|
|
||||||
Ok(content) => content,
|
|
||||||
Err(error) => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: error.to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(StrippedStateContent {
|
let event_type_value = match value.get("type") {
|
||||||
content,
|
Some(value) => value.clone(),
|
||||||
event_type,
|
|
||||||
state_key: match value.get("state_key") {
|
|
||||||
Some(state_key_value) => match state_key_value.as_str() {
|
|
||||||
Some(state_key) => state_key.to_string(),
|
|
||||||
None => {
|
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
|
||||||
json: value,
|
|
||||||
message: "field `state_key` must be a string".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
None => {
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
return Ok(EventResult::Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
json: value,
|
json: value,
|
||||||
message: "missing field `state_key`".to_string(),
|
message: "missing field `type`".to_string(),
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
sender: match value.get("sender") {
|
|
||||||
Some(sender_value) => match sender_value.as_str() {
|
let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
||||||
Some(sender_str) => match UserId::try_from(sender_str) {
|
Ok(event_type) => event_type,
|
||||||
Ok(sender) => sender,
|
Err(error) => {
|
||||||
Err(error) => {
|
return Ok(EventResult::Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
json: value,
|
||||||
json: value,
|
message: error.to_string(),
|
||||||
message: error.to_string(),
|
})))
|
||||||
}))
|
}
|
||||||
}
|
};
|
||||||
},
|
|
||||||
None => {
|
let content = match value.get("content") {
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
Some(content_value) => content_value,
|
||||||
json: value,
|
|
||||||
message: "field `sender` must be a string".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
None => {
|
||||||
return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
return Ok(EventResult::validation_error("missing field `content`".to_string(), value))
|
||||||
json: value,
|
|
||||||
message: "missing field `sender`".to_string(),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
})
|
|
||||||
|
let stripped_state = match event_type {
|
||||||
|
// TODO: On the next stream, start with doing the other variants in this match.
|
||||||
|
EventType::RoomAliases => {
|
||||||
|
let content_result = match from_value::<EventResult<AliasesEventContent>>(content.clone()) {
|
||||||
|
Ok(content_result) => content_result,
|
||||||
|
Err(error) => return Err(D::Error::custom(error)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = match content_result {
|
||||||
|
EventResult::Ok(content) => content,
|
||||||
|
EventResult::Err(error) => return Ok(EventResult::Err(error)),
|
||||||
|
};
|
||||||
|
|
||||||
|
StrippedState::RoomAliases(StrippedStateContent {
|
||||||
|
content,
|
||||||
|
event_type,
|
||||||
|
state_key: match value.get("state_key") {
|
||||||
|
Some(state_key_value) => match state_key_value.as_str() {
|
||||||
|
Some(state_key) => state_key.to_string(),
|
||||||
|
None => {
|
||||||
|
return Ok(EventResult::validation_error("field `state_key` must be a string".to_string(), value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Ok(EventResult::validation_error("missing field `state_key`".to_string(), value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sender: match value.get("sender") {
|
||||||
|
Some(sender_value) => match sender_value.as_str() {
|
||||||
|
Some(sender_str) => match UserId::try_from(sender_str) {
|
||||||
|
Ok(sender) => sender,
|
||||||
|
Err(error) => {
|
||||||
|
return Ok(EventResult::validation_error(error.to_string(), value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Ok(EventResult::validation_error("field `sender` must be a string".to_string(), value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Ok(EventResult::validation_error("missing field `sender`".to_string(), value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// EventType::RoomAvatar => match from_value::<StrippedRoomAvatar>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomAvatar(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomCanonicalAlias => match from_value::<StrippedRoomCanonicalAlias>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomCanonicalAlias(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomCreate => match from_value::<StrippedRoomCreate>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomCreate(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomGuestAccess => match from_value::<StrippedRoomGuestAccess>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomGuestAccess(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomHistoryVisibility => match from_value::<StrippedRoomHistoryVisibility>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomHistoryVisibility(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomJoinRules => match from_value::<StrippedRoomJoinRules>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomJoinRules(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomMember => match from_value::<StrippedRoomMember>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomMember(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomName => match from_value::<StrippedRoomName>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomName(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomPowerLevels => match from_value::<StrippedRoomPowerLevels>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomPowerLevels(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomThirdPartyInvite => match from_value::<StrippedRoomThirdPartyInvite>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomThirdPartyInvite(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// EventType::RoomTopic => match from_value::<StrippedRoomTopic>(value) {
|
||||||
|
// Ok(stripped_state) => StrippedState::RoomTopic(stripped_state),
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::Ok(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
_ => return Ok(EventResult::Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
json: value,
|
||||||
|
message: "not a state event".to_string(),
|
||||||
|
}))),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(EventResult::Ok(stripped_state))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl FromStr for StrippedState {
|
||||||
|
// type Err = InvalidEvent;
|
||||||
|
|
||||||
|
// /// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
// fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||||
|
// let value = match serde_json::from_str::<Value>(json) {
|
||||||
|
// Ok(value) => value,
|
||||||
|
// Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
||||||
|
// Ok(value) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
// Err(error) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Deserialization { error }));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let event_type_value = match value.get("type") {
|
||||||
|
// Some(value) => value.clone(),
|
||||||
|
// None => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "missing field `type`".to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
||||||
|
// Ok(event_type) => event_type,
|
||||||
|
// Err(error) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// match event_type {
|
||||||
|
// EventType::RoomAliases => Ok(StrippedState::RoomAliases(json.parse()?)),
|
||||||
|
// EventType::RoomAvatar => Ok(StrippedState::RoomAvatar(json.parse()?)),
|
||||||
|
// EventType::RoomCanonicalAlias => Ok(StrippedState::RoomCanonicalAlias(json.parse()?)),
|
||||||
|
// EventType::RoomCreate => Ok(StrippedState::RoomCreate(json.parse()?)),
|
||||||
|
// EventType::RoomGuestAccess => Ok(StrippedState::RoomGuestAccess(json.parse()?)),
|
||||||
|
// EventType::RoomHistoryVisibility => {
|
||||||
|
// Ok(StrippedState::RoomHistoryVisibility(json.parse()?))
|
||||||
|
// }
|
||||||
|
// EventType::RoomJoinRules => Ok(StrippedState::RoomJoinRules(json.parse()?)),
|
||||||
|
// EventType::RoomMember => Ok(StrippedState::RoomMember(json.parse()?)),
|
||||||
|
// EventType::RoomName => Ok(StrippedState::RoomName(json.parse()?)),
|
||||||
|
// EventType::RoomPowerLevels => Ok(StrippedState::RoomPowerLevels(json.parse()?)),
|
||||||
|
// EventType::RoomThirdPartyInvite => {
|
||||||
|
// Ok(StrippedState::RoomThirdPartyInvite(json.parse()?))
|
||||||
|
// }
|
||||||
|
// EventType::RoomTopic => Ok(StrippedState::RoomTopic(json.parse()?)),
|
||||||
|
// _ => Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "not a state event".to_string(),
|
||||||
|
// })),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a> TryFrom<&'a str> for StrippedState {
|
||||||
|
// type Error = InvalidEvent;
|
||||||
|
|
||||||
|
// /// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
// fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
||||||
|
// FromStr::from_str(json)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl Serialize for StrippedState {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match *self {
|
||||||
|
StrippedState::RoomAliases(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomAvatar(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomCanonicalAlias(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomCreate(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomGuestAccess(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomHistoryVisibility(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomJoinRules(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomMember(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomName(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomPowerLevels(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomThirdPartyInvite(ref event) => event.serialize(serializer),
|
||||||
|
StrippedState::RoomTopic(ref event) => event.serialize(serializer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl<'de, C> Deserialize<'de> for EventResult<StrippedStateContent<C>>
|
||||||
|
// where
|
||||||
|
// EventResult<C>: Deserialize<'de>,
|
||||||
|
// {
|
||||||
|
// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
// where
|
||||||
|
// D: Deserializer<'de>,
|
||||||
|
// {
|
||||||
|
// let value = serde_json::Value::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
// let event_type_value = match value.get("type") {
|
||||||
|
// Some(value) => value.clone(),
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("missing field `type`".to_string(), value))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
||||||
|
// Ok(event_type) => event_type,
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::validation_error(error.to_string(), value))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let content = match value.get("content") {
|
||||||
|
// Some(content_value) => match content_value.as_object() {
|
||||||
|
// Some(content) => content,
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("field `content` must be an object".to_string(), value))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("missing field `content`".to_string(), value))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// match event_type {
|
||||||
|
// EventType::RoomAliases => stripped_state_content::<AliasesEventContent>(event_type, value),
|
||||||
|
// EventType::RoomAvatar => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomCanonicalAlias => {
|
||||||
|
// stripped_state_content(event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomCreate => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomGuestAccess => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomHistoryVisibility => {
|
||||||
|
// stripped_state_content(event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomJoinRules => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomMember => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomName => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomPowerLevels => stripped_state_content(event_type, value),
|
||||||
|
// EventType::RoomThirdPartyInvite => {
|
||||||
|
// stripped_state_content(event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomTopic => stripped_state_content(event_type, value),
|
||||||
|
// _ => Ok(EventResult::validation_error("not a state event".to_string(), value)),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<C> FromStr for StrippedStateContent<C>
|
||||||
|
// where
|
||||||
|
// C: FromStr,
|
||||||
|
// <C as FromStr>::Err: ToString,
|
||||||
|
// {
|
||||||
|
// type Err = InvalidEvent;
|
||||||
|
|
||||||
|
// /// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
// fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||||
|
// let value = match serde_json::from_str::<Value>(json) {
|
||||||
|
// Ok(value) => value,
|
||||||
|
// Err(error) => match serde_json::from_str::<serde_json::Value>(json) {
|
||||||
|
// Ok(value) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
// Err(error) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Deserialization { error }));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let event_type_value = match value.get("type") {
|
||||||
|
// Some(value) => value.clone(),
|
||||||
|
// None => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "missing field `type`".to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let event_type = match from_value::<EventType>(event_type_value.clone()) {
|
||||||
|
// Ok(event_type) => event_type,
|
||||||
|
// Err(error) => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: error.to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let content = match value.get("content") {
|
||||||
|
// Some(content_value) => match content_value.as_object() {
|
||||||
|
// Some(content) => content,
|
||||||
|
// None => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "field `content` must be an object".to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// None => {
|
||||||
|
// return Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "missing field `content`".to_string(),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Unwrap is safe because we already know this can deserialize to a `Value`.
|
||||||
|
// let json_string = to_string(content).unwrap();
|
||||||
|
|
||||||
|
// match event_type {
|
||||||
|
// EventType::RoomAliases => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomAvatar => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomCanonicalAlias => {
|
||||||
|
// stripped_state_content(&json_string, event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomCreate => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomGuestAccess => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomHistoryVisibility => {
|
||||||
|
// stripped_state_content(&json_string, event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomJoinRules => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomMember => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomName => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomPowerLevels => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// EventType::RoomThirdPartyInvite => {
|
||||||
|
// stripped_state_content(&json_string, event_type, value)
|
||||||
|
// }
|
||||||
|
// EventType::RoomTopic => stripped_state_content(&json_string, event_type, value),
|
||||||
|
// _ => Err(InvalidEvent(InnerInvalidEvent::Validation {
|
||||||
|
// json: value,
|
||||||
|
// message: "not a state event".to_string(),
|
||||||
|
// })),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a, C> TryFrom<&'a str> for StrippedStateContent<C>
|
||||||
|
// where
|
||||||
|
// C: FromStr,
|
||||||
|
// <C as FromStr>::Err: ToString,
|
||||||
|
// {
|
||||||
|
// type Error = InvalidEvent;
|
||||||
|
|
||||||
|
// /// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
// fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
||||||
|
// FromStr::from_str(json)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// Reduces the boilerplate in the match arms of `impl Deserialize for StrippedState`.
|
||||||
|
// #[inline]
|
||||||
|
// fn create_stripped_state(
|
||||||
|
// event_type: EventType,
|
||||||
|
// value: Value,
|
||||||
|
// ) -> Result<EventResult<StrippedState>, serde_json::Error>
|
||||||
|
// where
|
||||||
|
// for<'de> EventResult<C>: Deserialize<'de>,
|
||||||
|
// {
|
||||||
|
// let event_result = from_value::<EventResult<C>>(value)?;
|
||||||
|
|
||||||
|
// Ok(EventResult::Ok(StrippedStateContent {
|
||||||
|
// content: event_result.into_result().unwrap(),
|
||||||
|
// event_type,
|
||||||
|
// state_key: match value.get("state_key") {
|
||||||
|
// Some(state_key_value) => match state_key_value.as_str() {
|
||||||
|
// Some(state_key) => state_key.to_string(),
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("field `state_key` must be a string".to_string(), value));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("missing field `state_key`".to_string(), value));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// sender: match value.get("sender") {
|
||||||
|
// Some(sender_value) => match sender_value.as_str() {
|
||||||
|
// Some(sender_str) => match UserId::try_from(sender_str) {
|
||||||
|
// Ok(sender) => sender,
|
||||||
|
// Err(error) => {
|
||||||
|
// return Ok(EventResult::validation_error(error.to_string(), value));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("field `sender` must be a string".to_string(), value));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// None => {
|
||||||
|
// return Ok(EventResult::validation_error("missing field `sender`".to_string(), value));
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
|
||||||
#[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