diff --git a/ruma-events/src/lib.rs b/ruma-events/src/lib.rs index 904b6a37..3f450f06 100644 --- a/ruma-events/src/lib.rs +++ b/ruma-events/src/lib.rs @@ -69,6 +69,72 @@ //! respective event traits whose `content` field is simply a `serde_json::Value` value, which //! represents arbitrary JSON. //! +//! ## Extending Ruma with custom events +//! +//! For our example we will create a reaction message event. This can be used with ruma-events +//! structs, for this event we will use a `SyncMessageEvent` struct but any `MessageEvent` struct +//! would work. +//! +//! ```rust +//! use ruma_events::{macros::MessageEventContent, SyncMessageEvent}; +//! use ruma_identifiers::EventId; +//! 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: EventId, +//! /// 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")] +//! Whatever, +//! } +//! +//! /// The payload for our reaction event. +//! #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] +//! #[ruma_event(type = "m.reaction")] +//! 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": "@someone:example.org", +//! "type": "m.reaction", +//! "unsigned": { +//! "age": 85 +//! } +//! }); +//! +//! // The downside of this event is we cannot use it with the `AnyRoomEvent` or `AnyEvent` enums, +//! // but could be deserialized from a `Raw` that has failed. +//! matches::assert_matches!( +//! serde_json::from_value::>(json), +//! Ok(SyncMessageEvent { +//! content: ReactionEventContent { +//! relates_to: RelatesTo::Annotation { key, .. }, +//! }, +//! .. +//! }) if key == "👍" +//! ); +//! ``` +//! //! # Serialization and deserialization //! //! All concrete event types in ruma-events can be serialized via the `Serialize` trait from @@ -82,7 +148,7 @@ //! collection failing to deserialize due to a single invalid event. The "content" type for each //! event also implements `Serialize` and either `TryFromRaw` (enabling usage as //! `Raw` for dedicated content types) or `Deserialize` (when the content is a -//! type alias), allowing content to be converted to and from JSON indepedently of the surrounding +//! type alias), allowing content to be converted to and from JSON independently of the surrounding //! event structure, if needed. //! //! # Collections diff --git a/ruma-serde/src/raw.rs b/ruma-serde/src/raw.rs index ea5a374d..e4a8d9bb 100644 --- a/ruma-serde/src/raw.rs +++ b/ruma-serde/src/raw.rs @@ -13,6 +13,21 @@ use serde_json::value::RawValue; /// A wrapper around `Box`, to be used in place of any type in the Matrix endpoint /// definition to allow request and response types to contain that said type represented by /// the generic argument `Ev`. +/// +/// Ruma offers the `Raw` wrapper to enable passing around JSON text that is only partially +/// validated. This is useful when a client receives events that do not follow the spec perfectly +/// or a server needs to generate reference hashes with the original canonical JSON string. +/// All event structs and enums implement `Serialize` / `Deserialize`, `Raw` should be used +/// to pass around events in a lossless way. +/// +/// ```ignore +/// let json = r#"{ "type": "imagine a full event", "content": {...} }"#; +/// +/// let deser = serde_json::from_str::>(json) +/// .unwrap() // the first Result from serde_json::from_str, will not fail +/// .deserialize() // deserialize to the inner type +/// .unwrap(); // finally get to the AnyRoomEvent +/// ``` pub struct Raw { json: Box, _ev: PhantomData,