Add new macros for implementing event traits. Fix Serialize impl for

NameEventContent. Convert m.room.power_levels to the new API.
This commit is contained in:
Jimmy Cuadra 2019-06-21 15:33:15 -07:00
parent 03099b9a8b
commit 090a91f78b
3 changed files with 326 additions and 69 deletions

View File

@ -23,3 +23,77 @@ macro_rules! impl_enum {
}
}
}
macro_rules! impl_event {
($name:ident, $content_name:ident, $event_type:path) => {
impl Event for $name {
/// The type of this event's `content` field.
type Content = $content_name;
/// The event's content.
fn content(&self) -> &Self::Content {
&self.content
}
/// The type of the event.
fn event_type(&self) -> EventType {
$event_type
}
}
};
}
macro_rules! impl_room_event {
($name:ident, $content_name:ident, $event_type:path) => {
impl_event!($name, $content_name, $event_type);
impl RoomEvent for $name {
/// The unique identifier for the event.
fn event_id(&self) -> &EventId {
&self.event_id
}
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this event was
/// sent.
fn origin_server_ts(&self) -> UInt {
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) -> Option<&Value> {
self.unsigned.as_ref()
}
}
};
}
macro_rules! impl_state_event {
($name:ident, $content_name:ident, $event_type:path) => {
impl_room_event!($name, $content_name, $event_type);
impl StateEvent for $name {
/// 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
}
}
};
}

View File

@ -40,7 +40,7 @@ pub struct NameEvent {
pub state_key: String,
}
/// The payload of a `NameEvent`.
/// The payload for `NameEvent`.
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct NameEventContent {
/// The name of the room. This MUST NOT exceed 255 bytes.
@ -91,72 +91,47 @@ impl Serialize for NameEvent {
where
S: Serializer,
{
let mut state = serializer.serialize_struct("NameEvent", 2)?;
let mut len = 6;
if self.prev_content.is_some() {
len += 1;
}
if self.room_id.is_some() {
len += 1;
}
if self.unsigned.is_some() {
len += 1;
}
let mut state = serializer.serialize_struct("NameEvent", len)?;
state.serialize_field("content", &self.content)?;
state.serialize_field("event_id", &self.event_id)?;
state.serialize_field("origin_server_ts", &self.origin_server_ts)?;
if self.prev_content.is_some() {
state.serialize_field("prev_content", &self.prev_content)?;
}
if self.room_id.is_some() {
state.serialize_field("room_id", &self.room_id)?;
}
if self.unsigned.is_some() {
state.serialize_field("unsigned", &self.unsigned)?;
}
state.serialize_field("sender", &self.sender)?;
state.serialize_field("state_key", &self.state_key)?;
state.serialize_field("type", &self.event_type())?;
state.end()
}
}
impl Event for NameEvent {
/// The type of this event's `content` field.
type Content = NameEventContent;
/// The event's content.
fn content(&self) -> &Self::Content {
&self.content
}
/// The type of the event.
fn event_type(&self) -> EventType {
EventType::RoomName
}
}
impl RoomEvent for NameEvent {
/// The unique identifier for the event.
fn event_id(&self) -> &EventId {
&self.event_id
}
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this event was
/// sent.
fn origin_server_ts(&self) -> UInt {
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) -> Option<&Value> {
self.unsigned.as_ref()
}
}
impl StateEvent for NameEvent {
/// 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
}
}
impl_state_event!(NameEvent, NameEventContent, EventType::RoomName);
impl NameEventContent {
/// Create a new `NameEventContent` with the given name.

View File

@ -1,20 +1,48 @@
//! Types for the *m.room.power_levels* event.
use std::collections::HashMap;
use std::{collections::HashMap, convert::TryFrom, str::FromStr};
use js_int::{Int, UInt};
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};
use js_int::UInt;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
use serde_json::Value;
use crate::EventType;
use crate::{
Event, EventType, InvalidEvent, InvalidInput, RoomEvent, StateEvent,
};
state_event! {
/// Defines the power levels (privileges) of users in the room.
pub struct PowerLevelsEvent(PowerLevelsEventContent) {}
/// Defines the power levels (privileges) of users in the room.
#[derive(Clone, Debug, PartialEq)]
pub struct PowerLevelsEvent {
/// The event's content.
pub content: PowerLevelsEventContent,
/// The unique identifier for the event.
pub event_id: EventId,
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this
/// event was sent.
pub origin_server_ts: UInt,
/// The previous content for this state key, if any.
pub prev_content: Option<NameEventContent>,
/// The unique identifier for the room associated with this event.
pub room_id: Option<RoomId>,
/// Additional key-value pairs not signed by the homeserver.
pub unsigned: Option<Value>,
/// 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,
}
/// The payload of a `PowerLevelsEvent`.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
/// The payload for `PowerLevelsEvent`.
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct PowerLevelsEventContent {
/// The level required to ban a user.
#[serde(default = "default_power_level")]
@ -60,6 +88,186 @@ pub struct PowerLevelsEventContent {
pub notifications: NotificationPowerLevels,
}
impl FromStr for PowerLevelsEvent {
type Err = crate::InvalidEvent;
/// Attempt to create `Self` from parsing a string of JSON data.
fn from_str(json: &str) -> Result<Self, Self::Err> {
let raw = serde_json::from_str::<raw::PowerLevelsEvent>(json)?;
Ok(Self {
content: PowerLevelsEventContent {
ban: raw.content.ban,
events: raw.content.events,
events_default: raw.content.events_default,
invite: raw.content.invite,
kick: raw.content.kick,
redact: raw.content.redact,
state_default: raw.content.state_default,
users: raw.content.users,
users_default: raw.content.users_default,
notifications: raw.content.notifications,
},
event_id: raw.event_id,
origin_server_ts: raw.origin_server_ts,
prev_content: raw
.prev_content
.map(|prev| PowerLevelsEventContent {
ban: prev.ban,
events: prev.events,
events_default: prev.events_default,
invite: prev.invite,
kick: prev.kick,
redact: prev.redact,
state_default: prev.state_default,
users: prev.users,
users_default: prev.users_default,
notifications: prev.notifications,
}),
room_id: raw.room_id,
unsigned: raw.unsigned,
sender: raw.sender,
state_key: raw.state_key,
})
}
}
impl<'a> TryFrom<&'a str> for PowerLevelsEvent {
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 NameEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut len = 6;
if self.prev_content.is_some() {
len += 1;
}
if self.room_id.is_some() {
len += 1;
}
if self.unsigned.is_some() {
len += 1;
}
let mut state = serializer.serialize_struct("PowerLevelsEvent", len)?;
state.serialize_field("content", &self.content)?;
state.serialize_field("event_id", &self.event_id)?;
state.serialize_field("origin_server_ts", &self.origin_server_ts)?;
if self.prev_content.is_some() {
state.serialize_field("prev_content", &self.prev_content)?;
}
if self.room_id.is_some() {
state.serialize_field("room_id", &self.room_id)?;
}
if self.unsigned.is_some() {
state.serialize_field("unsigned", &self.unsigned)?;
}
state.serialize_field("sender", &self.sender)?;
state.serialize_field("state_key", &self.state_key)?;
state.serialize_field("type", &self.event_type())?;
state.end()
}
}
impl_state_event!(PowerLevelsEvent, PowerLevelsEventContent, EventType::RoomPowerLevels);
mod raw {
use super::*;
/// Defines the power levels (privileges) of users in the room.
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct PowerLevelsEvent {
/// The event's content.
pub content: PowerLevelsEventContent,
/// The unique identifier for the event.
pub event_id: EventId,
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this
/// event was sent.
pub origin_server_ts: UInt,
/// The previous content for this state key, if any.
pub prev_content: Option<NameEventContent>,
/// The unique identifier for the room associated with this event.
pub room_id: Option<RoomId>,
/// Additional key-value pairs not signed by the homeserver.
pub unsigned: Option<Value>,
/// 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,
}
/// The payload for `PowerLevelsEvent`.
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct PowerLevelsEventContent {
/// The level required to ban a user.
#[serde(default = "default_power_level")]
pub ban: Int,
/// The level required to send specific event types.
///
/// This is a mapping from event type to power level required.
pub events: HashMap<EventType, Int>,
/// The default level required to send message events.
#[serde(default)]
pub events_default: Int,
/// The level required to invite a user.
#[serde(default = "default_power_level")]
pub invite: Int,
/// The level required to kick a user.
#[serde(default = "default_power_level")]
pub kick: Int,
/// The level required to redact an event.
#[serde(default = "default_power_level")]
pub redact: Int,
/// The default level required to send state events.
#[serde(default = "default_power_level")]
pub state_default: Int,
/// The power levels for specific users.
///
/// This is a mapping from `user_id` to power level for that user.
pub users: HashMap<UserId, Int>,
/// The default power level for every user in the room.
#[serde(default)]
pub users_default: Int,
/// The power level requirements for specific notification types.
///
/// This is a mapping from `key` to power level for that notifications key.
pub notifications: NotificationPowerLevels,
}
}
/// The power level requirements for specific notification types.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct NotificationPowerLevels {