diff --git a/src/collections/raw/all.rs b/src/collections/raw/all.rs index 2b4b7757..fbe78ef5 100644 --- a/src/collections/raw/all.rs +++ b/src/collections/raw/all.rs @@ -10,9 +10,7 @@ use crate::{ answer::raw::AnswerEvent, candidates::raw::CandidatesEvent, hangup::raw::HangupEvent, invite::raw::InviteEvent, }, - custom::raw::CustomEvent, - custom_room::raw::CustomRoomEvent, - custom_state::raw::CustomStateEvent, + custom::raw::{CustomEvent, CustomRoomEvent, CustomStateEvent}, direct::raw::DirectEvent, dummy::raw::DummyEvent, forwarded_room_key::raw::ForwardedRoomKeyEvent, diff --git a/src/collections/raw/only.rs b/src/collections/raw/only.rs index 80de2f33..c720949f 100644 --- a/src/collections/raw/only.rs +++ b/src/collections/raw/only.rs @@ -10,8 +10,7 @@ use crate::{ answer::raw::AnswerEvent, candidates::raw::CandidatesEvent, hangup::raw::HangupEvent, invite::raw::InviteEvent, }, - custom::raw::CustomEvent, - custom_room::raw::CustomRoomEvent, + custom::raw::{CustomEvent, CustomRoomEvent}, direct::raw::DirectEvent, dummy::raw::DummyEvent, forwarded_room_key::raw::ForwardedRoomKeyEvent, diff --git a/src/custom.rs b/src/custom.rs new file mode 100644 index 00000000..cc911c94 --- /dev/null +++ b/src/custom.rs @@ -0,0 +1,262 @@ +//! Types for custom events outside of the Matrix specification. + +use std::{collections::BTreeMap, time::SystemTime}; + +use crate::{Event, EventType, RoomEvent, StateEvent}; + +use ruma_events_macros::FromRaw; +use ruma_identifiers::{EventId, RoomId, UserId}; +use serde::Serialize; +use serde_json::Value as JsonValue; + +/// A custom event not covered by the Matrix specification. +#[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] +pub struct CustomEvent { + /// The event's content. + pub content: CustomEventContent, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, +} + +/// The payload for `CustomEvent`. +pub type CustomEventContent = JsonValue; + +impl Event for CustomEvent { + /// The type of this event's `content` field. + type Content = CustomEventContent; + + /// The event's content. + fn content(&self) -> &Self::Content { + &self.content + } + + /// The type of the event. + fn event_type(&self) -> EventType { + EventType::Custom(self.event_type.clone()) + } +} + +/// A custom room event not covered by the Matrix specification. +#[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] +pub struct CustomRoomEvent { + /// The event's content. + pub content: CustomRoomEventContent, + /// The unique identifier for the event. + pub event_id: EventId, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, + /// Time on originating homeserver when this event was sent. + #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] + pub origin_server_ts: SystemTime, + /// The unique identifier for the room associated with this event. + pub room_id: Option, + /// The unique identifier for the user who sent this event. + pub sender: UserId, + /// Additional key-value pairs not signed by the homeserver. + #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] + pub unsigned: BTreeMap, +} + +/// The payload for `CustomRoomEvent`. +pub type CustomRoomEventContent = JsonValue; + +impl Event for CustomRoomEvent { + /// The type of this event's `content` field. + type Content = CustomRoomEventContent; + + /// The event's content. + fn content(&self) -> &Self::Content { + &self.content + } + + /// The type of the event. + fn event_type(&self) -> EventType { + EventType::Custom(self.event_type.clone()) + } +} + +impl RoomEvent for CustomRoomEvent { + /// The unique identifier for the event. + fn event_id(&self) -> &EventId { + &self.event_id + } + + /// Time on originating homeserver when this event was sent. + fn origin_server_ts(&self) -> SystemTime { + self.origin_server_ts + } + + /// The unique identifier for the room associated with this event. + /// + /// This can be `None` if the event came from a context where there is + /// no ambiguity which room it belongs to, like a `/sync` response for example. + fn room_id(&self) -> Option<&RoomId> { + self.room_id.as_ref() + } + + /// The unique identifier for the user who sent this event. + fn sender(&self) -> &UserId { + &self.sender + } + + /// Additional key-value pairs not signed by the homeserver. + fn unsigned(&self) -> &BTreeMap { + &self.unsigned + } +} + +/// A custom state event not covered by the Matrix specification. +#[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] +pub struct CustomStateEvent { + /// The event's content. + pub content: CustomStateEventContent, + /// The unique identifier for the event. + pub event_id: EventId, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, + /// Time on originating homeserver when this event was sent. + #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] + pub origin_server_ts: SystemTime, + /// The previous content for this state key, if any. + pub prev_content: Option, + /// The unique identifier for the room associated with this event. + pub room_id: Option, + /// The unique identifier for the user who sent this event. + pub sender: UserId, + /// A key that determines which piece of room state the event represents. + pub state_key: String, + /// Additional key-value pairs not signed by the homeserver. + #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] + pub unsigned: BTreeMap, +} + +/// The payload for `CustomStateEvent`. +pub type CustomStateEventContent = JsonValue; + +impl Event for CustomStateEvent { + /// The type of this event's `content` field. + type Content = CustomStateEventContent; + + /// The event's content. + fn content(&self) -> &Self::Content { + &self.content + } + + /// The type of the event. + fn event_type(&self) -> EventType { + EventType::Custom(self.event_type.clone()) + } +} + +impl RoomEvent for CustomStateEvent { + /// The unique identifier for the event. + fn event_id(&self) -> &EventId { + &self.event_id + } + + /// Time on originating homeserver when this event was sent. + fn origin_server_ts(&self) -> SystemTime { + self.origin_server_ts + } + + /// The unique identifier for the room associated with this event. + /// + /// This can be `None` if the event came from a context where there is + /// no ambiguity which room it belongs to, like a `/sync` response for example. + fn room_id(&self) -> Option<&RoomId> { + self.room_id.as_ref() + } + + /// The unique identifier for the user who sent this event. + fn sender(&self) -> &UserId { + &self.sender + } + + /// Additional key-value pairs not signed by the homeserver. + fn unsigned(&self) -> &BTreeMap { + &self.unsigned + } +} + +impl StateEvent for CustomStateEvent { + /// The previous content for this state key, if any. + fn prev_content(&self) -> Option<&Self::Content> { + self.prev_content.as_ref() + } + + /// A key that determines which piece of room state the event represents. + fn state_key(&self) -> &str { + &self.state_key + } +} + +pub(crate) mod raw { + use std::{collections::BTreeMap, time::SystemTime}; + + use ruma_identifiers::{EventId, RoomId, UserId}; + use serde::Deserialize; + use serde_json::Value as JsonValue; + + use super::{CustomEventContent, CustomRoomEventContent, CustomStateEventContent}; + + /// A custom event not covered by the Matrix specification. + #[derive(Clone, Debug, PartialEq, Deserialize)] + pub struct CustomEvent { + /// The event's content. + pub content: CustomEventContent, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, + } + + /// A custom room event not covered by the Matrix specification. + #[derive(Clone, Debug, PartialEq, Deserialize)] + pub struct CustomRoomEvent { + /// The event's content. + pub content: CustomRoomEventContent, + /// The unique identifier for the event. + pub event_id: EventId, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, + /// Time on originating homeserver when this event was sent. + #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] + pub origin_server_ts: SystemTime, + /// The unique identifier for the room associated with this event. + pub room_id: Option, + /// The unique identifier for the user who sent this event. + pub sender: UserId, + /// Additional key-value pairs not signed by the homeserver. + #[serde(default)] + pub unsigned: BTreeMap, + } + + /// A custom state event not covered by the Matrix specification. + #[derive(Clone, Debug, PartialEq, Deserialize)] + pub struct CustomStateEvent { + /// The event's content. + pub content: CustomStateEventContent, + /// The unique identifier for the event. + pub event_id: EventId, + /// The custom type of the event. + #[serde(rename = "type")] + pub event_type: String, + /// Time on originating homeserver when this event was sent. + #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] + pub origin_server_ts: SystemTime, + /// The previous content for this state key, if any. + pub prev_content: Option, + /// The unique identifier for the room associated with this event. + pub room_id: Option, + /// The unique identifier for the user who sent this event. + pub sender: UserId, + /// A key that determines which piece of room state the event represents. + pub state_key: String, + /// Additional key-value pairs not signed by the homeserver. + #[serde(default)] + pub unsigned: BTreeMap, + } +} diff --git a/src/empty.rs b/src/empty.rs new file mode 100644 index 00000000..a288af01 --- /dev/null +++ b/src/empty.rs @@ -0,0 +1,58 @@ +use std::fmt::{self, Formatter}; + +use serde::{ + de::{Deserialize, Deserializer, MapAccess, Visitor}, + ser::{Serialize, SerializeMap, Serializer}, +}; + +use crate::FromRaw; + +/// A meaningless value that serializes to an empty JSON object. +/// +/// This type is used in a few places where the Matrix specification requires an empty JSON object, +/// but it's wasteful to represent it as a `BTreeMap` in Rust code. +#[derive(Clone, Debug, PartialEq)] +pub struct Empty; + +impl Serialize for Empty { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_map(Some(0))?.end() + } +} + +impl<'de> Deserialize<'de> for Empty { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct EmptyMapVisitor; + + impl<'de> Visitor<'de> for EmptyMapVisitor { + type Value = Empty; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "an object/map") + } + + fn visit_map(self, _map: A) -> Result + where + A: MapAccess<'de>, + { + Ok(Empty) + } + } + + deserializer.deserialize_map(EmptyMapVisitor) + } +} + +impl FromRaw for Empty { + type Raw = Self; + + fn from_raw(raw: Self) -> Self { + raw + } +} diff --git a/src/lib.rs b/src/lib.rs index a6c49aa3..9cfc2b57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,18 +122,19 @@ use std::{ }; use ruma_identifiers::{EventId, RoomId, UserId}; -use serde::{ - de::{MapAccess, Visitor}, - ser::SerializeMap, - Deserialize, Deserializer, Serialize, Serializer, -}; +use serde::Serialize; use serde_json::Value; -pub use self::{custom::CustomEvent, custom_room::CustomRoomEvent, custom_state::CustomStateEvent}; +pub use self::{ + custom::{CustomEvent, CustomRoomEvent, CustomStateEvent}, + empty::Empty, +}; #[macro_use] mod macros; + mod algorithm; +mod empty; mod event_type; mod from_raw; mod json; @@ -145,6 +146,7 @@ pub mod util; extern crate self as ruma_events; pub mod call; +pub mod custom; /// Enums for heterogeneous collections of events. pub mod collections { pub mod all; @@ -250,56 +252,6 @@ impl Display for FromStrError { impl Error for FromStrError {} -/// A meaningless value that serializes to an empty JSON object. -/// -/// This type is used in a few places where the Matrix specification requires an empty JSON object, -/// but it's wasteful to represent it as a `BTreeMap` in Rust code. -#[derive(Clone, Debug, PartialEq)] -pub struct Empty; - -impl Serialize for Empty { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_map(Some(0))?.end() - } -} - -impl<'de> Deserialize<'de> for Empty { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct EmptyMapVisitor; - - impl<'de> Visitor<'de> for EmptyMapVisitor { - type Value = Empty; - - fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "an object/map") - } - - fn visit_map(self, _map: A) -> Result - where - A: MapAccess<'de>, - { - Ok(Empty) - } - } - - deserializer.deserialize_map(EmptyMapVisitor) - } -} - -impl FromRaw for Empty { - type Raw = Self; - - fn from_raw(raw: Self) -> Self { - raw - } -} - /// A basic event. pub trait Event: Debug + Serialize + Sized + TryFromRaw { /// The type of this event's `content` field. @@ -341,287 +293,3 @@ pub trait StateEvent: RoomEvent { /// A key that determines which piece of room state the event represents. fn state_key(&self) -> &str; } - -/// A basic custom event outside of the Matrix specification. -mod custom { - use super::{Event, EventType}; - - use ruma_events_macros::FromRaw; - use serde::{Deserialize, Serialize}; - use serde_json::Value; - - /// A custom event not covered by the Matrix specification. - #[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] - pub struct CustomEvent { - /// The event's content. - pub content: CustomEventContent, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - } - - /// The payload for `CustomEvent`. - pub type CustomEventContent = Value; - - impl Event for CustomEvent { - /// The type of this event's `content` field. - type Content = CustomEventContent; - - /// The event's content. - fn content(&self) -> &Self::Content { - &self.content - } - - /// The type of the event. - fn event_type(&self) -> EventType { - EventType::Custom(self.event_type.clone()) - } - } - - /// "Raw" versions of the event and its content which implement `serde::Deserialize`. - pub mod raw { - use super::*; - - /// A custom event not covered by the Matrix specification. - #[derive(Clone, Debug, PartialEq, Deserialize)] - pub struct CustomEvent { - /// The event's content. - pub content: CustomEventContent, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - } - } -} - -mod custom_room { - use std::{collections::BTreeMap, time::SystemTime}; - - use super::{Event, EventType, RoomEvent}; - - use ruma_events_macros::FromRaw; - use serde::{Deserialize, Serialize}; - use serde_json::Value; - - /// A custom room event not covered by the Matrix specification. - #[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] - pub struct CustomRoomEvent { - /// The event's content. - pub content: CustomRoomEventContent, - /// The unique identifier for the event. - pub event_id: ruma_identifiers::EventId, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - /// Time on originating homeserver when this event was sent. - #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] - pub origin_server_ts: SystemTime, - /// The unique identifier for the room associated with this event. - pub room_id: Option, - /// The unique identifier for the user who sent this event. - pub sender: ruma_identifiers::UserId, - /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] - pub unsigned: BTreeMap, - } - - /// The payload for `CustomRoomEvent`. - pub type CustomRoomEventContent = Value; - - impl Event for CustomRoomEvent { - /// The type of this event's `content` field. - type Content = CustomRoomEventContent; - - /// The event's content. - fn content(&self) -> &Self::Content { - &self.content - } - - /// The type of the event. - fn event_type(&self) -> EventType { - EventType::Custom(self.event_type.clone()) - } - } - - impl RoomEvent for CustomRoomEvent { - /// The unique identifier for the event. - fn event_id(&self) -> &ruma_identifiers::EventId { - &self.event_id - } - - /// Time on originating homeserver when this event was sent. - fn origin_server_ts(&self) -> SystemTime { - self.origin_server_ts - } - - /// The unique identifier for the room associated with this event. - /// - /// This can be `None` if the event came from a context where there is - /// no ambiguity which room it belongs to, like a `/sync` response for example. - fn room_id(&self) -> Option<&ruma_identifiers::RoomId> { - self.room_id.as_ref() - } - - /// The unique identifier for the user who sent this event. - fn sender(&self) -> &ruma_identifiers::UserId { - &self.sender - } - - /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &BTreeMap { - &self.unsigned - } - } - - pub mod raw { - use super::*; - - /// A custom room event not covered by the Matrix specification. - #[derive(Clone, Debug, PartialEq, Deserialize)] - pub struct CustomRoomEvent { - /// The event's content. - pub content: CustomRoomEventContent, - /// The unique identifier for the event. - pub event_id: ruma_identifiers::EventId, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - /// Time on originating homeserver when this event was sent. - #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] - pub origin_server_ts: SystemTime, - /// The unique identifier for the room associated with this event. - pub room_id: Option, - /// The unique identifier for the user who sent this event. - pub sender: ruma_identifiers::UserId, - /// Additional key-value pairs not signed by the homeserver. - #[serde(default)] - pub unsigned: BTreeMap, - } - } -} - -mod custom_state { - use std::{collections::BTreeMap, time::SystemTime}; - - use super::{Event, EventType, RoomEvent, StateEvent}; - - use ruma_events_macros::FromRaw; - use serde::{Deserialize, Serialize}; - use serde_json::Value; - - /// A custom state event not covered by the Matrix specification. - #[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] - pub struct CustomStateEvent { - /// The event's content. - pub content: CustomStateEventContent, - /// The unique identifier for the event. - pub event_id: ruma_identifiers::EventId, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - /// Time on originating homeserver when this event was sent. - #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] - pub origin_server_ts: SystemTime, - /// The previous content for this state key, if any. - pub prev_content: Option, - /// The unique identifier for the room associated with this event. - pub room_id: Option, - /// The unique identifier for the user who sent this event. - pub sender: ruma_identifiers::UserId, - /// A key that determines which piece of room state the event represents. - pub state_key: String, - /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] - pub unsigned: BTreeMap, - } - - /// The payload for `CustomStateEvent`. - pub type CustomStateEventContent = Value; - - impl Event for CustomStateEvent { - /// The type of this event's `content` field. - type Content = CustomStateEventContent; - - /// The event's content. - fn content(&self) -> &Self::Content { - &self.content - } - - /// The type of the event. - fn event_type(&self) -> EventType { - EventType::Custom(self.event_type.clone()) - } - } - - impl RoomEvent for CustomStateEvent { - /// The unique identifier for the event. - fn event_id(&self) -> &ruma_identifiers::EventId { - &self.event_id - } - - /// Time on originating homeserver when this event was sent. - fn origin_server_ts(&self) -> SystemTime { - self.origin_server_ts - } - - /// The unique identifier for the room associated with this event. - /// - /// This can be `None` if the event came from a context where there is - /// no ambiguity which room it belongs to, like a `/sync` response for example. - fn room_id(&self) -> Option<&ruma_identifiers::RoomId> { - self.room_id.as_ref() - } - - /// The unique identifier for the user who sent this event. - fn sender(&self) -> &ruma_identifiers::UserId { - &self.sender - } - - /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &BTreeMap { - &self.unsigned - } - } - - impl StateEvent for CustomStateEvent { - /// The previous content for this state key, if any. - fn prev_content(&self) -> Option<&Self::Content> { - self.prev_content.as_ref() - } - - /// A key that determines which piece of room state the event represents. - fn state_key(&self) -> &str { - &self.state_key - } - } - - pub mod raw { - use super::*; - - /// A custom state event not covered by the Matrix specification. - #[derive(Clone, Debug, PartialEq, Deserialize)] - pub struct CustomStateEvent { - /// The event's content. - pub content: CustomStateEventContent, - /// The unique identifier for the event. - pub event_id: ruma_identifiers::EventId, - /// The custom type of the event. - #[serde(rename = "type")] - pub event_type: String, - /// Time on originating homeserver when this event was sent. - #[serde(with = "ruma_serde::time::ms_since_unix_epoch")] - pub origin_server_ts: SystemTime, - /// The previous content for this state key, if any. - pub prev_content: Option, - /// The unique identifier for the room associated with this event. - pub room_id: Option, - /// The unique identifier for the user who sent this event. - pub sender: ruma_identifiers::UserId, - /// A key that determines which piece of room state the event represents. - pub state_key: String, - /// Additional key-value pairs not signed by the homeserver. - #[serde(default)] - pub unsigned: BTreeMap, - } - } -}