1use ruma::{
2 assign,
3 events::{
4 room::{
5 avatar::{RoomAvatarEventContent, StrippedRoomAvatarEvent},
6 canonical_alias::{RoomCanonicalAliasEventContent, StrippedRoomCanonicalAliasEvent},
7 create::{StrippedRoomCreateEvent, SyncRoomCreateEvent},
8 guest_access::{
9 RedactedRoomGuestAccessEventContent, RoomGuestAccessEventContent,
10 StrippedRoomGuestAccessEvent,
11 },
12 history_visibility::{
13 RoomHistoryVisibilityEventContent, StrippedRoomHistoryVisibilityEvent,
14 },
15 join_rules::{RoomJoinRulesEventContent, StrippedRoomJoinRulesEvent},
16 member::{MembershipState, RoomMemberEventContent},
17 name::{RedactedRoomNameEventContent, RoomNameEventContent, StrippedRoomNameEvent},
18 tombstone::{
19 RedactedRoomTombstoneEventContent, RoomTombstoneEventContent,
20 StrippedRoomTombstoneEvent,
21 },
22 topic::{RedactedRoomTopicEventContent, RoomTopicEventContent, StrippedRoomTopicEvent},
23 },
24 RedactContent, RedactedStateEventContent, StateEventContent, StaticStateEventContent,
25 SyncStateEvent,
26 },
27 EventId, OwnedEventId, RoomVersionId,
28};
29use serde::{de::DeserializeOwned, Deserialize, Serialize};
30
31use crate::rooms::RoomCreateWithCreatorEventContent;
32
33#[derive(Clone, Debug, Deserialize, Serialize)]
46#[serde(bound(
47 serialize = "C: Serialize, C::Redacted: Serialize",
48 deserialize = "C: DeserializeOwned, C::Redacted: DeserializeOwned"
49))]
50pub enum MinimalStateEvent<C: StateEventContent + RedactContent>
51where
52 C::Redacted: RedactedStateEventContent,
53{
54 Original(OriginalMinimalStateEvent<C>),
56 Redacted(RedactedMinimalStateEvent<C::Redacted>),
58}
59
60#[derive(Clone, Debug, Deserialize, Serialize)]
64pub struct OriginalMinimalStateEvent<C>
65where
66 C: StateEventContent,
67{
68 pub content: C,
70 pub event_id: Option<OwnedEventId>,
72}
73
74#[derive(Clone, Debug, Deserialize, Serialize)]
78pub struct RedactedMinimalStateEvent<C>
79where
80 C: RedactedStateEventContent,
81{
82 pub content: C,
84 pub event_id: Option<OwnedEventId>,
86}
87
88impl<C> MinimalStateEvent<C>
89where
90 C: StateEventContent + RedactContent,
91 C::Redacted: RedactedStateEventContent,
92{
93 pub fn event_id(&self) -> Option<&EventId> {
95 match self {
96 MinimalStateEvent::Original(ev) => ev.event_id.as_deref(),
97 MinimalStateEvent::Redacted(ev) => ev.event_id.as_deref(),
98 }
99 }
100
101 pub fn as_original(&self) -> Option<&OriginalMinimalStateEvent<C>> {
103 match self {
104 MinimalStateEvent::Original(ev) => Some(ev),
105 MinimalStateEvent::Redacted(_) => None,
106 }
107 }
108
109 pub fn into_original(self) -> Option<OriginalMinimalStateEvent<C>> {
112 match self {
113 MinimalStateEvent::Original(ev) => Some(ev),
114 MinimalStateEvent::Redacted(_) => None,
115 }
116 }
117
118 pub fn redact(&mut self, room_version: &RoomVersionId)
122 where
123 C: Clone,
124 {
125 if let MinimalStateEvent::Original(ev) = self {
126 *self = MinimalStateEvent::Redacted(RedactedMinimalStateEvent {
127 content: ev.content.clone().redact(room_version),
128 event_id: ev.event_id.clone(),
129 });
130 }
131 }
132}
133
134pub type MinimalRoomMemberEvent = MinimalStateEvent<RoomMemberEventContent>;
136
137impl MinimalRoomMemberEvent {
138 pub fn membership(&self) -> &MembershipState {
141 match self {
142 MinimalStateEvent::Original(ev) => &ev.content.membership,
143 MinimalStateEvent::Redacted(ev) => &ev.content.membership,
144 }
145 }
146}
147
148impl<C> From<SyncStateEvent<C>> for MinimalStateEvent<C>
149where
150 C: StaticStateEventContent + RedactContent,
151 C::Redacted: RedactedStateEventContent,
152{
153 fn from(ev: SyncStateEvent<C>) -> Self {
154 match ev {
155 SyncStateEvent::Original(ev) => Self::Original(OriginalMinimalStateEvent {
156 content: ev.content,
157 event_id: Some(ev.event_id),
158 }),
159 SyncStateEvent::Redacted(ev) => Self::Redacted(RedactedMinimalStateEvent {
160 content: ev.content,
161 event_id: Some(ev.event_id),
162 }),
163 }
164 }
165}
166
167impl<C> From<&SyncStateEvent<C>> for MinimalStateEvent<C>
168where
169 C: Clone + StaticStateEventContent + RedactContent,
170 C::Redacted: Clone + RedactedStateEventContent,
171{
172 fn from(ev: &SyncStateEvent<C>) -> Self {
173 match ev {
174 SyncStateEvent::Original(ev) => Self::Original(OriginalMinimalStateEvent {
175 content: ev.content.clone(),
176 event_id: Some(ev.event_id.clone()),
177 }),
178 SyncStateEvent::Redacted(ev) => Self::Redacted(RedactedMinimalStateEvent {
179 content: ev.content.clone(),
180 event_id: Some(ev.event_id.clone()),
181 }),
182 }
183 }
184}
185
186impl From<&SyncRoomCreateEvent> for MinimalStateEvent<RoomCreateWithCreatorEventContent> {
187 fn from(ev: &SyncRoomCreateEvent) -> Self {
188 match ev {
189 SyncStateEvent::Original(ev) => Self::Original(OriginalMinimalStateEvent {
190 content: RoomCreateWithCreatorEventContent::from_event_content(
191 ev.content.clone(),
192 ev.sender.clone(),
193 ),
194 event_id: Some(ev.event_id.clone()),
195 }),
196 SyncStateEvent::Redacted(ev) => Self::Redacted(RedactedMinimalStateEvent {
197 content: RoomCreateWithCreatorEventContent::from_event_content(
198 ev.content.clone(),
199 ev.sender.clone(),
200 ),
201 event_id: Some(ev.event_id.clone()),
202 }),
203 }
204 }
205}
206
207impl From<&StrippedRoomAvatarEvent> for MinimalStateEvent<RoomAvatarEventContent> {
208 fn from(event: &StrippedRoomAvatarEvent) -> Self {
209 let content = assign!(RoomAvatarEventContent::new(), {
210 info: event.content.info.clone(),
211 url: event.content.url.clone(),
212 });
213 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
216 }
217}
218
219impl From<&StrippedRoomNameEvent> for MinimalStateEvent<RoomNameEventContent> {
220 fn from(event: &StrippedRoomNameEvent) -> Self {
221 match event.content.name.clone() {
222 Some(name) => {
223 let content = RoomNameEventContent::new(name);
224 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
225 }
226 None => {
227 let content = RedactedRoomNameEventContent::new();
228 Self::Redacted(RedactedMinimalStateEvent { content, event_id: None })
229 }
230 }
231 }
232}
233
234impl From<&StrippedRoomCreateEvent> for MinimalStateEvent<RoomCreateWithCreatorEventContent> {
235 fn from(event: &StrippedRoomCreateEvent) -> Self {
236 let content = RoomCreateWithCreatorEventContent {
237 creator: event.sender.clone(),
238 federate: event.content.federate,
239 room_version: event.content.room_version.clone(),
240 predecessor: event.content.predecessor.clone(),
241 room_type: event.content.room_type.clone(),
242 };
243 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
244 }
245}
246
247impl From<&StrippedRoomHistoryVisibilityEvent>
248 for MinimalStateEvent<RoomHistoryVisibilityEventContent>
249{
250 fn from(event: &StrippedRoomHistoryVisibilityEvent) -> Self {
251 let content =
252 RoomHistoryVisibilityEventContent::new(event.content.history_visibility.clone());
253 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
254 }
255}
256
257impl From<&StrippedRoomGuestAccessEvent> for MinimalStateEvent<RoomGuestAccessEventContent> {
258 fn from(event: &StrippedRoomGuestAccessEvent) -> Self {
259 match &event.content.guest_access {
260 Some(guest_access) => {
261 let content = RoomGuestAccessEventContent::new(guest_access.clone());
262 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
263 }
264 None => {
265 let content = RedactedRoomGuestAccessEventContent::new();
266 Self::Redacted(RedactedMinimalStateEvent { content, event_id: None })
267 }
268 }
269 }
270}
271
272impl From<&StrippedRoomJoinRulesEvent> for MinimalStateEvent<RoomJoinRulesEventContent> {
273 fn from(event: &StrippedRoomJoinRulesEvent) -> Self {
274 let content = RoomJoinRulesEventContent::new(event.content.join_rule.clone());
275 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
276 }
277}
278
279impl From<&StrippedRoomCanonicalAliasEvent> for MinimalStateEvent<RoomCanonicalAliasEventContent> {
280 fn from(event: &StrippedRoomCanonicalAliasEvent) -> Self {
281 let content = assign!(RoomCanonicalAliasEventContent::new(), {
282 alias: event.content.alias.clone(),
283 alt_aliases: event.content.alt_aliases.clone(),
284 });
285 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
286 }
287}
288
289impl From<&StrippedRoomTopicEvent> for MinimalStateEvent<RoomTopicEventContent> {
290 fn from(event: &StrippedRoomTopicEvent) -> Self {
291 match &event.content.topic {
292 Some(topic) => {
293 let content = RoomTopicEventContent::new(topic.clone());
294 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
295 }
296 None => {
297 let content = RedactedRoomTopicEventContent::new();
298 Self::Redacted(RedactedMinimalStateEvent { content, event_id: None })
299 }
300 }
301 }
302}
303
304impl From<&StrippedRoomTombstoneEvent> for MinimalStateEvent<RoomTombstoneEventContent> {
305 fn from(event: &StrippedRoomTombstoneEvent) -> Self {
306 match (&event.content.body, &event.content.replacement_room) {
307 (Some(body), Some(replacement_room)) => {
308 let content =
309 RoomTombstoneEventContent::new(body.clone(), replacement_room.clone());
310 Self::Original(OriginalMinimalStateEvent { content, event_id: None })
311 }
312 _ => {
313 let content = RedactedRoomTombstoneEventContent::new();
314 Self::Redacted(RedactedMinimalStateEvent { content, event_id: None })
315 }
316 }
317 }
318}