Convert m.dummy, m.forwarded_room_key, m.presence, m.room_key_request,

and m.sticker to the new API.
This commit is contained in:
Jimmy Cuadra 2019-06-20 02:15:31 -07:00
parent ce2a3817cf
commit 1f3e33c77d
8 changed files with 304 additions and 170 deletions

View File

@ -14,6 +14,7 @@ edition = "2018"
[dependencies]
ruma-identifiers = "0.13.0"
ruma-events-macros = { path = "../ruma-events-macros" }
ruma-signatures = "0.4.2"
serde_json = "1.0.39"

View File

@ -1,10 +1,14 @@
//! Types for the *m.dummy* event.
use std::collections::HashMap;
use std::{
collections::HashMap,
fmt::{Formatter, Result as FmtResult},
};
use serde::{Deserialize, Serialize};
use serde::{de::{Error, MapAccess, Visitor}, ser::{SerializeMap, SerializeStruct}, Deserialize, Deserializer, Serialize, Serializer};
use crate::Event;
event! {
/// This event type is used to indicate new Olm sessions for end-to-end encryption.
///
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
@ -14,11 +18,133 @@ event! {
/// this *m.dummy* event as the most recent event and using the keyshare request to set up the
/// session. The keyshare request and *m.dummy* combination should result in the original
/// sending client receiving keys over the newly established session.
pub struct DummyEvent(DummyEventContent) {}
#[derive(Clone, Debug)]
pub struct DummyEvent {
/// The event's content.
pub content: DummyEventContent,
}
/// The payload of an *m.dummy* event.
/// The payload for `DummyEvent`.
#[derive(Clone, Debug)]
pub struct DummyEventContent;
impl DummyEvent {
/// Attempt to create `Self` from parsing a string of JSON data.
pub fn from_str(json: &str) -> Result<Self, crate::InvalidEvent> {
serde_json::from_str::<raw::DummyEvent>(json)?;
Ok(Self {
content: DummyEventContent,
})
}
}
impl Serialize for DummyEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer
{
let mut state = serializer.serialize_struct("DummyEvent", 2)?;
state.serialize_field("content", &self.content);
state.serialize_field("type", &self.event_type());
state.end()
}
}
impl crate::Event for DummyEvent {
/// The type of the event.
const EVENT_TYPE: crate::EventType = crate::EventType::Dummy;
/// The type of this event's `content` field.
type Content = DummyEventContent;
/// The event's content.
fn content(&self) -> &Self::Content {
&self.content
}
}
// This is necessary because the content is represented in JSON as an empty object.
impl Serialize for DummyEventContent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer
{
serializer.serialize_map(Some(0))?.end()
}
}
mod raw {
use super::*;
/// This event type is used to indicate new Olm sessions for end-to-end encryption.
///
/// The values in the hash map are not meaningful. They are used to generate an empty JSON
/// object to support the structure used by the Matrix specification.
pub type DummyEventContent = HashMap<(), ()>;
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
///
/// The event does not have any content associated with it. The sending client is expected to
/// send a key share request shortly after this message, causing the receiving client to process
/// this *m.dummy* event as the most recent event and using the keyshare request to set up the
/// session. The keyshare request and *m.dummy* combination should result in the original
/// sending client receiving keys over the newly established session.
#[derive(Clone, Debug, Deserialize)]
pub struct DummyEvent {
/// The event's content.
pub content: DummyEventContent,
}
/// The payload for `DummyEvent`.
#[derive(Clone, Debug)]
pub struct DummyEventContent;
impl<'de> Deserialize<'de> for DummyEventContent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>
{
struct EmptyMapVisitor;
impl <'de> Visitor<'de> for EmptyMapVisitor {
type Value = DummyEventContent;
fn expecting(&self, f: &mut Formatter) -> FmtResult {
write!(f, "an object/map")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>
{
Ok(DummyEventContent)
}
}
deserializer.deserialize_map(EmptyMapVisitor)
}
}
}
#[cfg(test)]
mod tests {
use super::{DummyEvent, DummyEventContent};
#[test]
fn serialization() {
let dummy_event = DummyEvent {
content: DummyEventContent,
};
let actual = serde_json::to_string(&dummy_event).unwrap();
let expected = r#"{"content":{},"type":"m.dummy"}"#;
assert_eq!(actual, expected);
}
#[test]
fn deserialization() {
let json = r#"{"content":{},"type":"m.dummy"}"#;
assert!(DummyEvent::from_str(json).is_ok());
}
}

View File

@ -1,20 +1,18 @@
//! Types for the *m.forwarded_room_key* event.
use ruma_events_macros::ruma_event;
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};
use super::Algorithm;
event! {
ruma_event! {
/// This event type is used to forward keys for end-to-end encryption.
///
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
pub struct ForwardedRoomKeyEvent(ForwardedRoomKeyEventContent) {}
}
/// The payload of an *m.forwarded_room_key* event.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ForwardedRoomKeyEventContent {
ForwardedRoomKeyEvent {
kind: Event,
event_type: ForwardedRoomKey,
content: {
/// The encryption algorithm the key in this event is to be used with.
pub algorithm: Algorithm,
@ -32,16 +30,18 @@ pub struct ForwardedRoomKeyEventContent {
/// The Ed25519 key of the device which initiated the session originally.
///
/// It is "claimed" because the receiving device has no way to tell that the original room_key
/// actually came from a device which owns the private part of this key unless they have done
/// device verification.
/// It is "claimed" because the receiving device has no way to tell that the original
/// room_key actually came from a device which owns the private part of this key unless
/// they have done device verification.
pub sender_claimed_ed25519_key: String,
/// Chain of Curve25519 keys.
///
/// It starts out empty, but each time the key is forwarded to another device, the previous
/// sender in the chain is added to the end of the list. For example, if the key is forwarded
/// from A to B to C, this field is empty between A and B, and contains A's Curve25519 key
/// between B and C.
/// It starts out empty, but each time the key is forwarded to another device, the
/// previous sender in the chain is added to the end of the list. For example, if the
/// key is forwarded from A to B to C, this field is empty between A and B, and contains
/// A's Curve25519 key between B and C.
pub forwarding_curve25519_key_chain: Vec<String>,
},
}
}

View File

@ -97,7 +97,7 @@
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(warnings)]
#![allow(warnings)]
use std::{
error::Error,
@ -115,28 +115,28 @@ use serde_json::Value;
#[macro_use]
mod macros;
pub mod call;
/// Enums for heterogeneous collections of events.
pub mod collections {
pub mod all;
pub mod only;
}
pub mod direct;
// pub mod call;
// /// Enums for heterogeneous collections of events.
// pub mod collections {
// pub mod all;
// pub mod only;
// }
// pub mod direct;
pub mod dummy;
pub mod forwarded_room_key;
pub mod fully_read;
pub mod ignored_user_list;
pub mod key;
// pub mod fully_read;
// pub mod ignored_user_list;
// pub mod key;
pub mod presence;
pub mod push_rules;
pub mod receipt;
// pub mod push_rules;
// pub mod receipt;
pub mod room;
pub mod room_key;
// pub mod room_key;
pub mod room_key_request;
pub mod sticker;
pub mod stripped;
pub mod tag;
pub mod typing;
// pub mod stripped;
// pub mod tag;
// pub mod typing;
/// An event that is malformed or otherwise invalid.
///
@ -356,16 +356,21 @@ pub enum EventType {
/// A basic event.
pub trait Event
where
Self: Debug + for<'a> Deserialize<'a> + Serialize,
Self: Debug + Serialize,
{
/// The event-type-specific payload this event carries.
type Content: Debug + for<'a> Deserialize<'a> + Serialize;
/// The type of the event.
const EVENT_TYPE: EventType;
/// The type of this event's `content` field.
type Content: Debug + Serialize;
/// The event's content.
fn content(&self) -> &Self::Content;
/// The type of the event.
fn event_type(&self) -> &EventType;
fn event_type(&self) -> EventType {
Self::EVENT_TYPE
}
}
/// An event within the context of a room.
@ -399,20 +404,20 @@ pub trait StateEvent: RoomEvent {
fn state_key(&self) -> &str;
}
event! {
/// A custom basic event not covered by the Matrix specification.
pub struct CustomEvent(Value) {}
}
// event! {
// /// A custom basic event not covered by the Matrix specification.
// pub struct CustomEvent(Value) {}
// }
room_event! {
/// A custom room event not covered by the Matrix specification.
pub struct CustomRoomEvent(Value) {}
}
// room_event! {
// /// A custom room event not covered by the Matrix specification.
// pub struct CustomRoomEvent(Value) {}
// }
state_event! {
/// A custom state event not covered by the Matrix specification.
pub struct CustomStateEvent(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

@ -1,20 +1,20 @@
//! Types for the *m.presence* event.
use js_int::UInt;
use ruma_events_macros::ruma_event;
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};
event! {
ruma_event! {
/// Informs the client of a user's presence state change.
pub struct PresenceEvent(PresenceEventContent) {
PresenceEvent {
kind: Event,
event_type: Presence,
fields: {
/// The unique identifier for the user associated with this event.
pub sender: UserId
}
}
/// The payload of a `PresenceEvent`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct PresenceEventContent {
pub sender: UserId,
},
content: {
/// The current avatar URL for this user.
#[serde(skip_serializing_if = "Option::is_none")]
pub avatar_url: Option<String>,
@ -37,6 +37,8 @@ pub struct PresenceEventContent {
/// An optional description to accompany the presence.
#[serde(skip_serializing_if = "Option::is_none")]
pub status_msg: Option<String>,
},
}
}
/// A description of a user's connectivity and availability for chat.
@ -93,14 +95,13 @@ mod tests {
presence: PresenceState::Online,
status_msg: Some("Making cupcakes".to_string()),
},
event_type: EventType::Presence,
sender: UserId::try_from("@example:localhost").unwrap(),
};
let serialized_event =
r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"type":"m.presence","sender":"@example:localhost"}"#;
r#"{"content":{"avatar_url":"mxc://localhost:wefuiwegh8742w","currently_active":false,"last_active_ago":2478593,"presence":"online","status_msg":"Making cupcakes"},"sender":"@example:localhost","type":"m.presence"}"#;
assert_eq!(to_string(&event).unwrap(), serialized_event);
let deserialized_event = from_str::<PresenceEvent>(serialized_event).unwrap();
let deserialized_event = PresenceEvent::from_str(serialized_event).unwrap();
assert_eq!(deserialized_event.content, event.content);
assert_eq!(deserialized_event.sender, event.sender);
}

View File

@ -7,25 +7,25 @@ use std::collections::HashMap;
use js_int::UInt;
use serde::{Deserialize, Serialize};
pub mod aliases;
pub mod avatar;
pub mod canonical_alias;
pub mod create;
pub mod encrypted;
pub mod encryption;
pub mod guest_access;
pub mod history_visibility;
pub mod join_rules;
pub mod member;
pub mod message;
pub mod name;
pub mod pinned_events;
pub mod power_levels;
pub mod redaction;
pub mod server_acl;
pub mod third_party_invite;
pub mod tombstone;
pub mod topic;
// pub mod aliases;
// pub mod avatar;
// pub mod canonical_alias;
// pub mod create;
// pub mod encrypted;
// pub mod encryption;
// pub mod guest_access;
// pub mod history_visibility;
// pub mod join_rules;
// pub mod member;
// pub mod message;
// pub mod name;
// pub mod pinned_events;
// pub mod power_levels;
// pub mod redaction;
// pub mod server_acl;
// pub mod third_party_invite;
// pub mod tombstone;
// pub mod topic;
/// Metadata about an image.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]

View File

@ -1,20 +1,19 @@
//! Types for the *m.room_key_request* event.
use ruma_events_macros::ruma_event;
use ruma_identifiers::{DeviceId, RoomId};
use serde::{Deserialize, Serialize};
use super::Algorithm;
event! {
ruma_event! {
/// This event type is used to request keys for end-to-end encryption.
///
/// It is sent as an unencrypted to-device event.
pub struct RoomKeyRequestEvent(RoomKeyRequestEventContent) {}
}
/// The payload of an *m.room_key_request* event.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RoomKeyRequestEventContent {
RoomKeyRequestEvent {
kind: Event,
event_type: RoomKeyRequest,
content: {
/// Whether this is a new key request or a cancellation of a previous request.
pub action: Action,
@ -28,9 +27,11 @@ pub struct RoomKeyRequestEventContent {
/// A random string uniquely identifying the request for a key.
///
/// If the key is requested multiple times, it should be reused. It should also reused in order
/// to cancel a request.
/// If the key is requested multiple times, it should be reused. It should also reused
/// in order to cancel a request.
pub request_id: String,
},
}
}
/// A new key request or a cancellation of a previous request.

View File

@ -1,20 +1,18 @@
//! Types for the *m.sticker* event.
use js_int::UInt;
use serde::{Deserialize, Serialize};
use ruma_events_macros::ruma_event;
use crate::room::ImageInfo;
room_event! {
ruma_event! {
/// A sticker message.
pub struct StickerEvent(StickerEventContent) {}
}
/// The payload of a `StickerEvent`.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct StickerEventContent {
/// A textual representation or associated description of the sticker image. This could be the
/// alt text of the original image, or a message to accompany and further describe the sticker.
StickerEvent {
kind: RoomEvent,
event_type: Sticker,
content: {
/// A textual representation or associated description of the sticker image. This could
/// be the alt text of the original image, or a message to accompany and further
/// describe the sticker.
pub body: String,
/// Metadata about the image referred to in `url` including a thumbnail representation.
@ -22,4 +20,6 @@ pub struct StickerEventContent {
/// The URL to the sticker image. This must be a valid `mxc://` URI.
pub url: String,
},
}
}