ruma_events/
content.rs

1use std::fmt;
2
3use ruma_common::serde::{CanBeEmpty, Raw};
4use serde::{de::DeserializeOwned, Serialize};
5use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
6
7use super::{
8    EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType,
9    RoomAccountDataEventType, StateEventType, ToDeviceEventType,
10};
11
12/// Extension trait for [`Raw<T>`].
13pub trait RawExt<T: EventContentFromType> {
14    /// Try to deserialize the JSON as an event's content with the given event type.
15    fn deserialize_with_type(&self, event_type: &str) -> serde_json::Result<T>;
16}
17
18impl<T> RawExt<T> for Raw<T>
19where
20    T: EventContentFromType,
21{
22    fn deserialize_with_type(&self, event_type: &str) -> serde_json::Result<T> {
23        T::from_parts(event_type, self.json())
24    }
25}
26
27/// An event content type with a statically-known event `type` value.
28///
29/// Note that the `TYPE` might not be the full event type. If `IsPrefix` is set to `True`, it only
30/// contains the statically-known prefix of the event type.
31///
32/// To only support full event types, the bound `StaticEventContent<IsPrefix = False>` can be used.
33pub trait StaticEventContent: Sized {
34    /// The statically-known part of the event type.
35    ///
36    /// If this is only the prefix of the event type, it should end with `.`, which is usually used
37    /// a separator in Matrix event types.
38    const TYPE: &'static str;
39    /// Whether the statically-known part of the event type is the prefix.
40    ///
41    /// Should be set to the [`True`] or [`False`] types.
42    ///
43    /// Ideally this should be a boolean associated constant, but [associated constant equality is
44    /// unstable], so this field could not be used as a bound. Instead we use an associated type so
45    /// we can rely on associated type equality.
46    ///
47    /// If this is set to [`False`], the `TYPE` is the full event type.
48    ///
49    /// [associated constant equality is unstable]: https://github.com/rust-lang/rust/issues/92827
50    type IsPrefix: BooleanType;
51}
52
53/// A trait for types representing a boolean value.
54pub trait BooleanType {
55    /// The boolean representation of this type.
56    fn as_bool() -> bool;
57}
58
59/// The equivalent of the `true` boolean.
60#[non_exhaustive]
61pub struct True;
62
63impl BooleanType for True {
64    fn as_bool() -> bool {
65        true
66    }
67}
68
69/// The equivalent of the `false` boolean.
70#[non_exhaustive]
71pub struct False;
72
73impl BooleanType for False {
74    fn as_bool() -> bool {
75        false
76    }
77}
78
79/// Content of a global account-data event.
80pub trait GlobalAccountDataEventContent: Sized + Serialize {
81    /// Get the event's type, like `m.push_rules`.
82    fn event_type(&self) -> GlobalAccountDataEventType;
83}
84
85/// Content of a room-specific account-data event.
86pub trait RoomAccountDataEventContent: Sized + Serialize {
87    /// Get the event's type, like `m.tag`.
88    fn event_type(&self) -> RoomAccountDataEventType;
89}
90
91/// Content of an ephemeral room event.
92pub trait EphemeralRoomEventContent: Sized + Serialize {
93    /// Get the event's type, like `m.receipt`.
94    fn event_type(&self) -> EphemeralRoomEventType;
95}
96
97/// Content of a non-redacted message-like event.
98pub trait MessageLikeEventContent: Sized + Serialize {
99    /// Get the event's type, like `m.room.message`.
100    fn event_type(&self) -> MessageLikeEventType;
101}
102
103/// Content of a redacted message-like event.
104pub trait RedactedMessageLikeEventContent: Sized + Serialize {
105    /// Get the event's type, like `m.room.message`.
106    fn event_type(&self) -> MessageLikeEventType;
107}
108
109/// Content of a non-redacted state event.
110pub trait StateEventContent: Sized + Serialize {
111    /// The type of the event's `state_key` field.
112    type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
113
114    /// Get the event's type, like `m.room.name`.
115    fn event_type(&self) -> StateEventType;
116}
117
118/// Content of a non-redacted state event with a corresponding possibly-redacted type.
119pub trait StaticStateEventContent: StateEventContent {
120    /// The possibly redacted form of the event's content.
121    type PossiblyRedacted: PossiblyRedactedStateEventContent;
122
123    /// The type of the event's `unsigned` field.
124    type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + DeserializeOwned;
125}
126
127/// Content of a redacted state event.
128pub trait RedactedStateEventContent: Sized + Serialize {
129    /// The type of the event's `state_key` field.
130    type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
131
132    /// Get the event's type, like `m.room.name`.
133    fn event_type(&self) -> StateEventType;
134}
135
136/// Content of a state event.
137pub trait PossiblyRedactedStateEventContent: Sized + Serialize {
138    /// The type of the event's `state_key` field.
139    type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
140
141    /// Get the event's type, like `m.room.name`.
142    fn event_type(&self) -> StateEventType;
143}
144
145/// Content of a to-device event.
146pub trait ToDeviceEventContent: Sized + Serialize {
147    /// Get the event's type, like `m.room_key`.
148    fn event_type(&self) -> ToDeviceEventType;
149}
150
151/// Event content that can be deserialized with its event type.
152pub trait EventContentFromType: Sized {
153    /// Constructs this event content from the given event type and JSON.
154    fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self>;
155}
156
157impl<T> EventContentFromType for T
158where
159    T: StaticEventContent + DeserializeOwned,
160{
161    fn from_parts(_event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self> {
162        from_json_str(content.get())
163    }
164}