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