Convert Event, RoomEvent and StateEvent into traits.

This commit is contained in:
Jimmy Cuadra 2016-10-02 03:46:16 -07:00
parent f3acdfd141
commit 8392852741
24 changed files with 339 additions and 217 deletions

View File

@ -1,10 +1,11 @@
//! Types for the *m.call.answer* event.
use RoomEvent;
use super::SessionDescription;
/// This event is sent by the callee when they wish to answer the call.
pub type AnswerEvent = RoomEvent<AnswerEventContent, ()>;
room_event! {
/// This event is sent by the callee when they wish to answer the call.
pub struct AnswerEvent(AnswerEventContent) {}
}
/// The payload of an `AnswerEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,10 +1,11 @@
//! Types for the *m.call.candidates* event.
use RoomEvent;
/// This event is sent by callers after sending an invite and by the callee after answering.
/// Its purpose is to give the other party additional ICE candidates to try using to communicate.
pub type CandidatesEvent = RoomEvent<CandidatesEventContent, ()>;
room_event! {
/// This event is sent by callers after sending an invite and by the callee after answering.
/// Its purpose is to give the other party additional ICE candidates to try using to
/// communicate.
pub struct CandidatesEvent(CandidatesEventContent) {}
}
/// The payload of a `CandidatesEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,10 +1,10 @@
//! Types for the *m.call.hangup* event.
use RoomEvent;
/// Sent by either party to signal their termination of the call. This can be sent either once the
/// call has has been established or before to abort the call.
pub type HangupEvent = RoomEvent<HangupEventContent, ()>;
room_event! {
/// Sent by either party to signal their termination of the call. This can be sent either once
/// the call has has been established or before to abort the call.
pub struct HangupEvent(HangupEventContent) {}
}
/// The payload of a `HangupEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,10 +1,11 @@
//! Types for the *m.call.invite* event.
use RoomEvent;
use super::SessionDescription;
/// This event is sent by the caller when they wish to establish a call.
pub type InviteEvent = RoomEvent<InviteEventContent, ()>;
room_event! {
/// This event is sent by the caller when they wish to establish a call.
pub struct InviteEvent(InviteEventContent) {}
}
/// The payload of an `InviteEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -9,7 +9,7 @@ extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use std::fmt::{Display, Formatter, Error as FmtError};
use std::fmt::{Debug, Display, Formatter, Error as FmtError};
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
@ -81,93 +81,55 @@ pub enum EventType {
}
/// A basic event.
#[derive(Debug, Deserialize, Serialize)]
pub struct Event<C, E> where C: Deserialize + Serialize, E: Deserialize + Serialize {
/// Data specific to the event type.
pub content: C,
pub trait Event: Debug + Deserialize + Serialize {
/// The event-type-specific payload this event carries.
type Content;
/// The event's content.
fn content(&self) -> &Self::Content;
/// The type of the event.
#[serde(rename="type")]
pub event_type: EventType,
/// Extra top-level key-value pairs specific to this event type, but that are not under the
/// `content` field.
pub extra_content: E,
fn event_type(&self) -> &EventType;
}
/// An event within the context of a room.
#[derive(Debug, Deserialize, Serialize)]
pub struct RoomEvent<C, E> where C: Deserialize + Serialize, E: Deserialize + Serialize {
/// Data specific to the event type.
pub content: C,
pub trait RoomEvent: Debug + Deserialize + Event + Serialize {
/// The unique identifier for the event.
pub event_id: EventId,
/// Extra top-level key-value pairs specific to this event type, but that are not under the
/// `content` field.
pub extra_content: E,
/// The type of the event.
#[serde(rename="type")]
pub event_type: EventType,
fn event_id(&self) -> &EventId;
/// The unique identifier for the room associated with this event.
pub room_id: RoomId,
fn room_id(&self) -> &RoomId;
/// Additional key-value pairs not signed by the homeserver.
#[serde(skip_serializing_if="Option::is_none")]
pub unsigned: Option<Value>,
fn unsigned(&self) -> Option<&Value>;
/// The unique identifier for the user associated with this event.
#[serde(rename="sender")]
pub user_id: UserId,
fn user_id(&self) -> &UserId;
}
/// An event that describes persistent state about a room.
#[derive(Debug, Deserialize, Serialize)]
pub struct StateEvent<C, E> where C: Deserialize + Serialize, E: Deserialize + Serialize {
/// Data specific to the event type.
pub content: C,
/// The unique identifier for the event.
pub event_id: EventId,
/// The type of the event.
#[serde(rename="type")]
pub event_type: EventType,
/// Extra top-level key-value pairs specific to this event type, but that are not under the
/// `content` field.
pub extra_content: E,
pub trait StateEvent: Debug + Deserialize + RoomEvent + Serialize {
/// The previous content for this state key, if any.
#[serde(skip_serializing_if="Option::is_none")]
pub prev_content: Option<C>,
/// The unique identifier for the room associated with this event.
pub room_id: RoomId,
fn prev_content(&self) -> Option<&Self::Content>;
/// 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="Option::is_none")]
pub unsigned: Option<Value>,
/// The unique identifier for the user associated with this event.
#[serde(rename="sender")]
pub user_id: UserId,
fn state_key(&self) -> &str;
}
/// A custom basic event not covered by the Matrix specification.
pub type CustomEvent = Event<Value, ()>;
event! {
/// A custom basic event not covered by the Matrix specification.
pub struct CustomEvent(Value) {}
}
/// A custom room event not covered by the Matrix specification.
pub type CustomRoomEvent = RoomEvent<Value, ()>;
room_event! {
/// A custom room event not covered by the Matrix specification.
pub struct CustomRoomEvent(Value) {}
}
/// A custom state event not covered by the Matrix specification.
pub type CustomStateEvent = StateEvent<Value, ()>;
state_event! {
/// A custom state event not covered by the Matrix specification.
pub struct CustomStateEvent(Value) {}
}
impl Display for EventType {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {

View File

@ -22,3 +22,182 @@ macro_rules! impl_enum {
}
}
}
macro_rules! event {
( $(#[$attr:meta])*
pub struct $name:ident($content_type:ty) {
$(
$(#[$field_attr:meta])*
pub $field_name:ident: $field_type:ty
),*
}
) => {
$(#[$attr])*
#[derive(Debug, Deserialize, Serialize)]
pub struct $name {
/// The event's content.
pub content: $content_type,
/// The type of the event.
#[serde(rename="type")]
pub event_type: $crate::EventType,
$(
$(#[$field_attr])*
pub $field_name: $field_type
),*
}
impl_event!($name, $content_type);
}
}
macro_rules! impl_event {
($name:ident, $content_type:ty) => {
impl $crate::Event for $name {
type Content = $content_type;
fn content(&self) -> &<$name as $crate::Event>::Content {
&self.content
}
fn event_type(&self) -> &$crate::EventType {
&self.event_type
}
}
}
}
macro_rules! room_event {
( $(#[$attr:meta])*
pub struct $name:ident($content_type:ty) {
$(
$(#[$field_attr:meta])*
pub $field_name:ident: $field_type:ty
),*
}
) => {
$(#[$attr])*
#[derive(Debug, Deserialize, Serialize)]
pub struct $name {
/// The event's content.
pub content: $content_type,
/// The unique identifier for the event.
pub event_id: ::ruma_identifiers::EventId,
/// The type of the event.
#[serde(rename="type")]
pub event_type: $crate::EventType,
/// The unique identifier for the room associated with this event.
pub room_id: ::ruma_identifiers::RoomId,
/// Additional key-value pairs not signed by the homeserver.
#[serde(skip_serializing_if="Option::is_none")]
pub unsigned: Option<::serde_json::Value>,
/// The unique identifier for the user associated with this event.
#[serde(rename="sender")]
pub user_id: ::ruma_identifiers::UserId,
$(
$(#[$field_attr])*
pub $field_name: $field_type
),*
}
impl_room_event!($name, $content_type);
}
}
macro_rules! impl_room_event {
($name:ident, $content_type:ty) => {
impl_event!($name, $content_type);
impl $crate::RoomEvent for $name {
fn event_id(&self) -> &::ruma_identifiers::EventId {
&self.event_id
}
fn room_id(&self) -> &::ruma_identifiers::RoomId {
&self.room_id
}
fn unsigned(&self) -> Option<&::serde_json::Value> {
self.unsigned.as_ref()
}
fn user_id(&self) -> &::ruma_identifiers::UserId {
&self.user_id
}
}
}
}
macro_rules! state_event {
( $(#[$attr:meta])*
pub struct $name:ident($content_type:ty) {
$(
$(#[$field_attr:meta])*
pub $field_name:ident: $field_type:ty
),*
}
) => {
$(#[$attr])*
#[allow(missing_docs)]
#[derive(Debug, Deserialize, Serialize)]
pub struct $name {
/// The event's content.
pub content: $content_type,
/// The unique identifier for the event.
pub event_id: ::ruma_identifiers::EventId,
/// The type of the event.
#[serde(rename="type")]
pub event_type: $crate::EventType,
/// The previous content for this state key, if any.
#[serde(skip_serializing_if="Option::is_none")]
pub prev_content: Option<$content_type>,
/// The unique identifier for the room associated with this event.
pub room_id: ::ruma_identifiers::RoomId,
/// 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="Option::is_none")]
pub unsigned: Option<::serde_json::Value>,
/// The unique identifier for the user associated with this event.
#[serde(rename="sender")]
pub user_id: ::ruma_identifiers::UserId,
$(
$(#[$field_attr])*
pub $field_name: $field_type
),*
}
impl_state_event!($name, $content_type);
}
}
macro_rules! impl_state_event {
($name:ident, $content_type:ty) => {
impl_room_event!($name, $content_type);
impl $crate::StateEvent for $name {
fn prev_content(&self) -> Option<&Self::Content> {
self.prev_content.as_ref()
}
fn state_key(&self) -> &str {
&self.state_key
}
}
}
}

View File

@ -2,10 +2,13 @@
use ruma_identifiers::{EventId, UserId};
use Event;
/// Informs the client of a user's presence state change.
pub type PresenceEvent = Event<PresenceEventContent, PresenceEventExtraContent>;
event! {
/// Informs the client of a user's presence state change.
pub struct PresenceEvent(PresenceEventContent) {
/// The unique identifier for the event.
pub event_id: EventId
}
}
/// The payload of a `PresenceEvent`.
#[derive(Debug, Deserialize, Serialize)]
@ -47,18 +50,3 @@ pub enum PresenceState {
#[serde(rename="unavailable")]
Unavailable,
}
/// Extra content for a `PresenceEvent`.
#[derive(Debug, Deserialize, Serialize)]
pub struct PresenceEventExtraContent {
/// The unique identifier for the event.
pub event_id: EventId,
}
impl_enum! {
PresenceState {
Offline => "offline",
Online => "online",
Unavailable => "unavailable",
}
}

View File

@ -4,10 +4,13 @@ use std::collections::HashMap;
use ruma_identifiers::{EventId, RoomId, UserId};
use Event;
/// Informs the client of new receipts.
pub type ReceiptEvent = Event<ReceiptEventContent, ReceiptEventExtraContent>;
event! {
/// Informs the client of new receipts.
pub struct ReceiptEvent(ReceiptEventContent) {
/// The unique identifier for the room associated with this event.
pub room_id: RoomId
}
}
/// The payload of a `ReceiptEvent`.
///
@ -33,10 +36,3 @@ pub struct Receipt {
/// The timestamp the receipt was sent at.
pub ts: u64,
}
/// Extra content for a `PresenceEvent`.
#[derive(Debug, Deserialize, Serialize)]
pub struct ReceiptEventExtraContent {
/// The unique identifier for the room associated with this event.
pub room_id: RoomId,
}

View File

@ -2,10 +2,10 @@
use ruma_identifiers::RoomAliasId;
use StateEvent;
/// Informs the room about what room aliases it has been given.
pub type AliasesEvent = StateEvent<AliasesEventContent, ()>;
state_event! {
/// Informs the room about what room aliases it has been given.
pub struct AliasesEvent(AliasesEventContent) {}
}
/// The payload of an `AliasesEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,12 +1,13 @@
//! Types for the *m.room.avatar* event.
use StateEvent;
use super::ImageInfo;
/// A picture that is associated with the room.
///
/// This can be displayed alongside the room information.
pub type AvatarEvent = StateEvent<AvatarEventContent, ()>;
state_event! {
/// A picture that is associated with the room.
///
/// This can be displayed alongside the room information.
pub struct AvatarEvent(AvatarEventContent) {}
}
/// The payload of an `AvatarEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -2,10 +2,10 @@
use ruma_identifiers::RoomAliasId;
use StateEvent;
/// Informs the room as to which alias is the canonical one.
pub type CanonicalAliasEvent = StateEvent<CanonicalAliasEventContent, ()>;
state_event! {
/// Informs the room as to which alias is the canonical one.
pub struct CanonicalAliasEvent(CanonicalAliasEventContent) {}
}
/// The payload of a `CanonicalAliasEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -2,11 +2,11 @@
use ruma_identifiers::UserId;
use StateEvent;
/// This is the first event in a room and cannot be changed. It acts as the root of all other
/// events.
pub type CreateEvent = StateEvent<CreateEventContent, ()>;
state_event! {
/// This is the first event in a room and cannot be changed. It acts as the root of all other
/// events.
pub struct CreateEvent(CreateEventContent) {}
}
/// The payload of a `CreateEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,12 +1,12 @@
//! Types for the *m.room.guest_access* event.
use StateEvent;
/// Controls whether guest users are allowed to join rooms.
///
/// This event controls whether guest users are allowed to join rooms. If this event is absent,
/// servers should act as if it is present and has the value `GuestAccess::Forbidden`.
pub type GuestAccessEvent = StateEvent<GuestAccessEventContent, ()>;
state_event! {
/// Controls whether guest users are allowed to join rooms.
///
/// This event controls whether guest users are allowed to join rooms. If this event is absent,
/// servers should act as if it is present and has the value `GuestAccess::Forbidden`.
pub struct GuestAccessEvent(GuestAccessEventContent) {}
}
/// The payload of a `GuestAccessEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,10 +1,10 @@
//! Types for the *m.room.history_visibility* event.
use StateEvent;
/// This event controls whether a member of a room can see the events that happened in a room from
/// before they joined.
pub type HistoryVisibilityEvent = StateEvent<HistoryVisibilityEventContent, ()>;
state_event! {
/// This event controls whether a member of a room can see the events that happened in a room
/// from before they joined.
pub struct HistoryVisibilityEvent(HistoryVisibilityEventContent) {}
}
/// The payload of a `HistoryVisibilityEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,9 +1,9 @@
//! Types for the *m.room.join_rules* event.
use StateEvent;
/// Describes how users are allowed to join the room.
pub type JoinRulesEvent = StateEvent<JoinRulesEventContent, ()>;
state_event! {
/// Describes how users are allowed to join the room.
pub struct JoinRulesEvent(JoinRulesEventContent) {}
}
/// The payload of a `JoinRulesEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,22 +1,28 @@
//! Types for the *m.room.member* event.
use StateEvent;
use stripped::StrippedState;
/// The current membership state of a user in the room.
///
/// Adjusts the membership state for a user in a room. It is preferable to use the membership APIs
/// (``/rooms/<room id>/invite`` etc) when performing membership actions rather than adjusting the
/// state directly as there are a restricted set of valid transformations. For example, user A
/// cannot force user B to join a room, and trying to force this state change directly will fail.
///
/// The *third_party_invite* property will be set if this invite is an *invite* event and is the
/// successor of an *m.room.third_party_invite* event, and absent otherwise.
///
/// This event may also include an *invite_room_state* key outside the *content* key. If present,
/// this contains an array of `StrippedState` events. These events provide information on a few
/// select state events such as the room name.
pub type MemberEvent = StateEvent<MemberEventContent, MemberEventExtraContent>;
state_event! {
/// The current membership state of a user in the room.
///
/// Adjusts the membership state for a user in a room. It is preferable to use the membership
/// APIs (``/rooms/<room id>/invite`` etc) when performing membership actions rather than
/// adjusting the state directly as there are a restricted set of valid transformations. For
/// example, user A cannot force user B to join a room, and trying to force this state change
/// directly will fail.
///
/// The *third_party_invite* property will be set if this invite is an *invite* event and is the
/// successor of an *m.room.third_party_invite* event, and absent otherwise.
///
/// This event may also include an *invite_room_state* key outside the *content* key. If
/// present, this contains an array of `StrippedState` events. These events provide information
/// on a few select state events such as the room name.
pub struct MemberEvent(MemberEventContent) {
/// A subset of the state of the room at the time of the invite.
#[serde(skip_serializing_if="Option::is_none")]
pub invite_room_state: Option<Vec<StrippedState>>
}
}
/// The payload of a `MemberEvent`.
#[derive(Debug, Deserialize, Serialize)]
@ -60,14 +66,6 @@ pub enum MembershipState {
Leave,
}
/// Extra content for a `MemberEvent`.
#[derive(Debug, Deserialize, Serialize)]
pub struct MemberEventExtraContent {
/// A subset of the state of the room at the time of the invite.
#[serde(skip_serializing_if="Option::is_none")]
pub invite_room_state: Option<Vec<StrippedState>>,
}
impl_enum! {
MembershipState {
Ban => "ban",

View File

@ -3,11 +3,12 @@
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde_json::{Value, from_value};
use RoomEvent;
use super::ImageInfo;
/// A message sent to a room.
pub type MessageEvent = RoomEvent<MessageEventContent, ()>;
room_event! {
/// A message sent to a room.
pub struct MessageEvent(MessageEventContent) {}
}
/// The message type of message event, e.g. `m.image` or `m.text`.
#[derive(Debug, Deserialize, PartialEq, Serialize)]

View File

@ -1,9 +1,9 @@
//! Types for the *m.room.name* event.
use StateEvent;
/// A human-friendly room name designed to be displayed to the end-user.
pub type NameEvent = StateEvent<NameEventContent, ()>;
state_event! {
/// A human-friendly room name designed to be displayed to the end-user.
pub struct NameEvent(NameEventContent) {}
}
/// The payload of a `NameEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -4,10 +4,12 @@ use std::collections::HashMap;
use ruma_identifiers::UserId;
use {EventType, StateEvent};
use EventType;
/// Defines the power levels (privileges) of users in the room.
pub type PowerLevelsEvent = StateEvent<PowerLevelsEventContent, ()>;
state_event! {
/// Defines the power levels (privileges) of users in the room.
pub struct PowerLevelsEvent(PowerLevelsEventContent) {}
}
/// The payload of a `PowerLevelsEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -2,10 +2,13 @@
use ruma_identifiers::EventId;
use RoomEvent;
/// A redaction of an event.
pub type RedactionEvent = RoomEvent<RedactionEventContent, RedactionEventExtraContent>;
room_event! {
/// A redaction of an event.
pub struct RedactionEvent(RedactionEventContent) {
/// The ID of the event that was redacted.
pub redacts: EventId
}
}
/// The payload of a `RedactionEvent`.
#[derive(Debug, Deserialize, Serialize)]
@ -14,10 +17,3 @@ pub struct RedactionEventContent {
#[serde(skip_serializing_if="Option::is_none")]
pub reason: Option<String>,
}
/// Extra content for a `RedactionEvent`.
#[derive(Debug, Deserialize, Serialize)]
pub struct RedactionEventExtraContent {
/// The ID of the event that was redacted.
pub redacts: EventId,
}

View File

@ -1,13 +1,13 @@
//! Types for the *m.room.third_party_invite* event.
use StateEvent;
/// An invitation to a room issued to a third party identifier, rather than a matrix user ID.
///
/// Acts as an *m.room.member* invite event, where there isn't a target user_id to invite. This
/// event contains a token and a public key whose private key must be used to sign the token. Any
/// user who can present that signature may use this invitation to join the target room.
pub type ThirdPartyInviteEvent = StateEvent<ThirdPartyInviteEventContent, ()>;
state_event! {
/// An invitation to a room issued to a third party identifier, rather than a matrix user ID.
///
/// Acts as an *m.room.member* invite event, where there isn't a target user_id to invite. This
/// event contains a token and a public key whose private key must be used to sign the token. Any
/// user who can present that signature may use this invitation to join the target room.
pub struct ThirdPartyInviteEvent(ThirdPartyInviteEventContent) {}
}
/// The payload of a `ThirdPartyInviteEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -1,9 +1,9 @@
//! Types for the *m.room.topic* event.
use StateEvent;
/// A topic is a short message detailing what is currently being discussed in the room.
pub type TopicEvent = StateEvent<TopicEventContent, ()>;
state_event! {
/// A topic is a short message detailing what is currently being discussed in the room.
pub struct TopicEvent(TopicEventContent) {}
}
/// The payload of a `TopicEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -2,10 +2,10 @@
use std::collections::HashMap;
use Event;
/// Informs the client of tags on a room.
pub type TagEvent = Event<TagEventContent, ()>;
event! {
/// Informs the client of tags on a room.
pub struct TagEvent(TagEventContent) {}
}
/// The payload of a `TagEvent`.
#[derive(Debug, Deserialize, Serialize)]

View File

@ -2,10 +2,13 @@
use ruma_identifiers::{EventId, RoomId};
use Event;
/// Informs the client of the list of users currently typing.
pub type TypingEvent = Event<TypingEventContent, TypingEventExtraContent>;
event! {
/// Informs the client of the list of users currently typing.
pub struct TypingEvent(TypingEventContent) {
/// The unique identifier for the room associated with this event.
pub room_id: RoomId
}
}
/// The payload of a `TypingEvent`.
#[derive(Debug, Deserialize, Serialize)]
@ -13,10 +16,3 @@ pub struct TypingEventContent {
/// The list of user IDs typing in this room, if any.
pub user_ids: Vec<EventId>,
}
/// Extra content for a `TypingEvent`.
#[derive(Debug, Deserialize, Serialize)]
pub struct TypingEventExtraContent {
/// The unique identifier for the room associated with this event.
pub room_id: RoomId,
}