Crate ruma_events

source ·
Expand description

(De)serializable types for the events in the Matrix specification. These types are used by other Ruma crates.

All data exchanged over Matrix is expressed as an event. Different event types represent different actions, such as joining a room or sending a message. Events are stored and transmitted as simple JSON structures. While anyone can create a new event type for their own purposes, the Matrix specification defines a number of event types which are considered core to the protocol. This module contains Rust types for all of the event types defined by the specification and facilities for extending the event system for custom event types.

Core event types

This module includes Rust types for all event types in the Matrix specification. To better organize the crate, these types live in separate modules with a hierarchy that matches the reverse domain name notation of the event type. For example, the event lives at ruma::events::room::message::RoomMessageEvent. Each type’s module also contains a Rust type for that event type’s content field, and any other supporting types required by the event’s other fields.

Extending Ruma with custom events

For our examples we will start with a simple custom state event. ruma_event specifies the state event’s type and its kind.

use ruma_events::macros::EventContent;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "org.example.event", kind = State, state_key_type = String)]
pub struct ExampleContent {
    field: String,

This can be used with events structs, such as passing it into ruma::api::client::state::send_state_event’s Request.

As a more advanced example we create a reaction message event. For this event we will use a OriginalSyncMessageLikeEvent struct but any OriginalMessageLikeEvent struct would work.

use ruma_common::OwnedEventId;
use ruma_events::{macros::EventContent, OriginalSyncMessageLikeEvent};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "rel_type")]
pub enum RelatesTo {
    #[serde(rename = "m.annotation")]
    Annotation {
        /// The event this reaction relates to.
        event_id: OwnedEventId,
        /// The displayable content of the reaction.
        key: String,

    /// Since this event is not fully specified in the Matrix spec
    /// it may change or types may be added, we are ready!
    #[serde(rename = "m.whatever")]

/// The payload for our reaction event.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.reaction", kind = MessageLike)]
pub struct ReactionEventContent {
    #[serde(rename = "m.relates_to")]
    pub relates_to: RelatesTo,

let json = serde_json::json!({
    "content": {
        "m.relates_to": {
            "event_id": "$xxxx-xxxx",
            "key": "👍",
            "rel_type": "m.annotation"
    "event_id": "$xxxx-xxxx",
    "origin_server_ts": 1,
    "sender": "",
    "type": "m.reaction",
    "unsigned": {
        "age": 85

// The downside of this event is we cannot use it with event enums,
// but could be deserialized from a `Raw<_>` that has failed to deserialize.
    Ok(OriginalSyncMessageLikeEvent {
        content: ReactionEventContent {
            relates_to: RelatesTo::Annotation { key, .. },
    }) if key == "👍"