ruma_events/
kinds.rs

1#![allow(clippy::exhaustive_structs)]
2
3use as_variant::as_variant;
4use ruma_common::{
5    serde::{from_raw_json_value, Raw},
6    EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId,
7    RoomVersionId, UserId,
8};
9use ruma_macros::Event;
10use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize};
11use serde_json::value::RawValue as RawJsonValue;
12
13use super::{
14    AnyInitialStateEvent, EmptyStateKey, EphemeralRoomEventContent, EventContent,
15    EventContentFromType, GlobalAccountDataEventContent, MessageLikeEventContent,
16    MessageLikeEventType, MessageLikeUnsigned, PossiblyRedactedStateEventContent, RedactContent,
17    RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned,
18    RedactionDeHelper, RoomAccountDataEventContent, StateEventType, StaticStateEventContent,
19    ToDeviceEventContent,
20};
21
22/// A global account data event.
23#[derive(Clone, Debug, Event)]
24pub struct GlobalAccountDataEvent<C: GlobalAccountDataEventContent> {
25    /// Data specific to the event type.
26    pub content: C,
27}
28
29impl<C: GlobalAccountDataEventContent> Serialize for GlobalAccountDataEvent<C> {
30    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31    where
32        S: serde::Serializer,
33    {
34        let mut state = serializer.serialize_struct("GlobalAccountDataEvent", 2)?;
35        state.serialize_field("type", &self.content.event_type())?;
36        state.serialize_field("content", &self.content)?;
37        state.end()
38    }
39}
40
41/// A room account data event.
42#[derive(Clone, Debug, Event)]
43pub struct RoomAccountDataEvent<C: RoomAccountDataEventContent> {
44    /// Data specific to the event type.
45    pub content: C,
46}
47
48impl<C: RoomAccountDataEventContent> Serialize for RoomAccountDataEvent<C> {
49    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50    where
51        S: serde::Serializer,
52    {
53        let mut state = serializer.serialize_struct("RoomAccountDataEvent", 2)?;
54        state.serialize_field("type", &self.content.event_type())?;
55        state.serialize_field("content", &self.content)?;
56        state.end()
57    }
58}
59
60/// An ephemeral room event.
61#[derive(Clone, Debug, Event)]
62pub struct EphemeralRoomEvent<C: EphemeralRoomEventContent> {
63    /// Data specific to the event type.
64    pub content: C,
65
66    /// The ID of the room associated with this event.
67    pub room_id: OwnedRoomId,
68}
69
70impl<C: EphemeralRoomEventContent> Serialize for EphemeralRoomEvent<C> {
71    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72    where
73        S: serde::Serializer,
74    {
75        let mut state = serializer.serialize_struct("EphemeralRoomEvent", 2)?;
76        state.serialize_field("type", &self.content.event_type())?;
77        state.serialize_field("content", &self.content)?;
78        state.serialize_field("room_id", &self.room_id)?;
79        state.end()
80    }
81}
82
83/// An ephemeral room event without a `room_id`.
84#[derive(Clone, Debug, Event)]
85pub struct SyncEphemeralRoomEvent<C: EphemeralRoomEventContent> {
86    /// Data specific to the event type.
87    pub content: C,
88}
89
90impl<C: EphemeralRoomEventContent> Serialize for SyncEphemeralRoomEvent<C> {
91    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92    where
93        S: serde::Serializer,
94    {
95        let mut state = serializer.serialize_struct("SyncEphemeralRoomEvent", 2)?;
96        state.serialize_field("type", &self.content.event_type())?;
97        state.serialize_field("content", &self.content)?;
98        state.end()
99    }
100}
101
102/// An unredacted message-like event.
103///
104/// `OriginalMessageLikeEvent` implements the comparison traits using only the `event_id` field, a
105/// sorted list would be sorted lexicographically based on the event's `EventId`.
106#[derive(Clone, Debug, Event)]
107pub struct OriginalMessageLikeEvent<C: MessageLikeEventContent> {
108    /// Data specific to the event type.
109    pub content: C,
110
111    /// The globally unique event identifier for the user who sent the event.
112    pub event_id: OwnedEventId,
113
114    /// The fully-qualified ID of the user who sent this event.
115    pub sender: OwnedUserId,
116
117    /// Timestamp in milliseconds on originating homeserver when this event was sent.
118    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
119
120    /// The ID of the room associated with this event.
121    pub room_id: OwnedRoomId,
122
123    /// Additional key-value pairs not signed by the homeserver.
124    pub unsigned: MessageLikeUnsigned<C>,
125}
126
127/// An unredacted message-like event without a `room_id`.
128///
129/// `OriginalSyncMessageLikeEvent` implements the comparison traits using only the `event_id` field,
130/// a sorted list would be sorted lexicographically based on the event's `EventId`.
131#[derive(Clone, Debug, Event)]
132pub struct OriginalSyncMessageLikeEvent<C: MessageLikeEventContent> {
133    /// Data specific to the event type.
134    pub content: C,
135
136    /// The globally unique event identifier for the user who sent the event.
137    pub event_id: OwnedEventId,
138
139    /// The fully-qualified ID of the user who sent this event.
140    pub sender: OwnedUserId,
141
142    /// Timestamp in milliseconds on originating homeserver when this event was sent.
143    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
144
145    /// Additional key-value pairs not signed by the homeserver.
146    pub unsigned: MessageLikeUnsigned<C>,
147}
148
149impl<C: MessageLikeEventContent + RedactContent> OriginalSyncMessageLikeEvent<C>
150where
151    C::Redacted: RedactedMessageLikeEventContent,
152{
153    pub(crate) fn into_maybe_redacted(self) -> SyncMessageLikeEvent<C> {
154        SyncMessageLikeEvent::Original(self)
155    }
156}
157
158/// A redacted message-like event.
159///
160/// `RedactedMessageLikeEvent` implements the comparison traits using only the `event_id` field, a
161/// sorted list would be sorted lexicographically based on the event's `EventId`.
162#[derive(Clone, Debug, Event)]
163pub struct RedactedMessageLikeEvent<C: RedactedMessageLikeEventContent> {
164    /// Data specific to the event type.
165    pub content: C,
166
167    /// The globally unique event identifier for the user who sent the event.
168    pub event_id: OwnedEventId,
169
170    /// The fully-qualified ID of the user who sent this event.
171    pub sender: OwnedUserId,
172
173    /// Timestamp in milliseconds on originating homeserver when this event was sent.
174    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
175
176    /// The ID of the room associated with this event.
177    pub room_id: OwnedRoomId,
178
179    /// Additional key-value pairs not signed by the homeserver.
180    pub unsigned: RedactedUnsigned,
181}
182
183/// A redacted message-like event without a `room_id`.
184///
185/// `RedactedSyncMessageLikeEvent` implements the comparison traits using only the `event_id` field,
186/// a sorted list would be sorted lexicographically based on the event's `EventId`.
187#[derive(Clone, Debug, Event)]
188pub struct RedactedSyncMessageLikeEvent<C: RedactedMessageLikeEventContent> {
189    /// Data specific to the event type.
190    pub content: C,
191
192    /// The globally unique event identifier for the user who sent the event.
193    pub event_id: OwnedEventId,
194
195    /// The fully-qualified ID of the user who sent this event.
196    pub sender: OwnedUserId,
197
198    /// Timestamp in milliseconds on originating homeserver when this event was sent.
199    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
200
201    /// Additional key-value pairs not signed by the homeserver.
202    pub unsigned: RedactedUnsigned,
203}
204
205/// A possibly-redacted message-like event.
206///
207/// `MessageLikeEvent` implements the comparison traits using only the `event_id` field, a sorted
208/// list would be sorted lexicographically based on the event's `EventId`.
209#[allow(clippy::exhaustive_enums)]
210#[derive(Clone, Debug)]
211pub enum MessageLikeEvent<C: MessageLikeEventContent + RedactContent>
212where
213    C::Redacted: RedactedMessageLikeEventContent,
214{
215    /// Original, unredacted form of the event.
216    Original(OriginalMessageLikeEvent<C>),
217
218    /// Redacted form of the event with minimal fields.
219    Redacted(RedactedMessageLikeEvent<C::Redacted>),
220}
221
222/// A possibly-redacted message-like event without a `room_id`.
223///
224/// `SyncMessageLikeEvent` implements the comparison traits using only the `event_id` field, a
225/// sorted list would be sorted lexicographically based on the event's `EventId`.
226#[allow(clippy::exhaustive_enums)]
227#[derive(Clone, Debug)]
228pub enum SyncMessageLikeEvent<C: MessageLikeEventContent + RedactContent>
229where
230    C::Redacted: RedactedMessageLikeEventContent,
231{
232    /// Original, unredacted form of the event.
233    Original(OriginalSyncMessageLikeEvent<C>),
234
235    /// Redacted form of the event with minimal fields.
236    Redacted(RedactedSyncMessageLikeEvent<C::Redacted>),
237}
238
239/// An unredacted state event.
240///
241/// `OriginalStateEvent` implements the comparison traits using only the `event_id` field, a sorted
242/// list would be sorted lexicographically based on the event's `EventId`.
243#[derive(Clone, Debug, Event)]
244pub struct OriginalStateEvent<C: StaticStateEventContent> {
245    /// Data specific to the event type.
246    pub content: C,
247
248    /// The globally unique event identifier for the user who sent the event.
249    pub event_id: OwnedEventId,
250
251    /// The fully-qualified ID of the user who sent this event.
252    pub sender: OwnedUserId,
253
254    /// Timestamp in milliseconds on originating homeserver when this event was sent.
255    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
256
257    /// The ID of the room associated with this event.
258    pub room_id: OwnedRoomId,
259
260    /// A unique key which defines the overwriting semantics for this piece of room state.
261    ///
262    /// This is often an empty string, but some events send a `UserId` to show which user the event
263    /// affects.
264    pub state_key: C::StateKey,
265
266    /// Additional key-value pairs not signed by the homeserver.
267    pub unsigned: C::Unsigned,
268}
269
270/// An unredacted state event without a `room_id`.
271///
272/// `OriginalSyncStateEvent` implements the comparison traits using only the `event_id` field, a
273/// sorted list would be sorted lexicographically based on the event's `EventId`.
274#[derive(Clone, Debug, Event)]
275pub struct OriginalSyncStateEvent<C: StaticStateEventContent> {
276    /// Data specific to the event type.
277    pub content: C,
278
279    /// The globally unique event identifier for the user who sent the event.
280    pub event_id: OwnedEventId,
281
282    /// The fully-qualified ID of the user who sent this event.
283    pub sender: OwnedUserId,
284
285    /// Timestamp in milliseconds on originating homeserver when this event was sent.
286    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
287
288    /// A unique key which defines the overwriting semantics for this piece of room state.
289    ///
290    /// This is often an empty string, but some events send a `UserId` to show which user the event
291    /// affects.
292    pub state_key: C::StateKey,
293
294    /// Additional key-value pairs not signed by the homeserver.
295    pub unsigned: C::Unsigned,
296}
297
298/// A stripped-down state event, used for previews of rooms the user has been invited to.
299#[derive(Clone, Debug, Event)]
300pub struct StrippedStateEvent<C: PossiblyRedactedStateEventContent> {
301    /// Data specific to the event type.
302    pub content: C,
303
304    /// The fully-qualified ID of the user who sent this event.
305    pub sender: OwnedUserId,
306
307    /// A unique key which defines the overwriting semantics for this piece of room state.
308    ///
309    /// This is often an empty string, but some events send a `UserId` to show which user the event
310    /// affects.
311    pub state_key: C::StateKey,
312}
313
314/// A minimal state event, used for creating a new room.
315#[derive(Clone, Debug, Event)]
316pub struct InitialStateEvent<C: StaticStateEventContent> {
317    /// Data specific to the event type.
318    pub content: C,
319
320    /// A unique key which defines the overwriting semantics for this piece of room state.
321    ///
322    /// This is often an empty string, but some events send a `UserId` to show which user the event
323    /// affects.
324    ///
325    /// Defaults to the empty string.
326    pub state_key: C::StateKey,
327}
328
329impl<C: StaticStateEventContent> InitialStateEvent<C> {
330    /// Create a new `InitialStateEvent` for an event type with an empty state key.
331    ///
332    /// For cases where the state key is not empty, use a struct literal to create the event.
333    pub fn new(content: C) -> Self
334    where
335        C: StaticStateEventContent<StateKey = EmptyStateKey>,
336    {
337        Self { content, state_key: EmptyStateKey }
338    }
339
340    /// Shorthand for `Raw::new(self).unwrap()`.
341    ///
342    /// Since none of the content types in Ruma ever return an error in serialization, this will
343    /// never panic with `C` being a type from Ruma. However, if you use a custom content type
344    /// with a `Serialize` implementation that can error (for example because it contains an
345    /// `enum` with one or more variants that use the `#[serde(skip)]` attribute), this method
346    /// can panic.
347    pub fn to_raw(&self) -> Raw<Self> {
348        Raw::new(self).unwrap()
349    }
350
351    /// Shorthand for `self.to_raw().cast::<AnyInitialStateEvent>()`.
352    ///
353    /// Since none of the content types in Ruma ever return an error in serialization, this will
354    /// never panic with `C` being a type from Ruma. However, if you use a custom content type
355    /// with a `Serialize` implementation that can error (for example because it contains an
356    /// `enum` with one or more variants that use the `#[serde(skip)]` attribute), this method
357    /// can panic.
358    pub fn to_raw_any(&self) -> Raw<AnyInitialStateEvent> {
359        self.to_raw().cast()
360    }
361}
362
363impl<C> Default for InitialStateEvent<C>
364where
365    C: StaticStateEventContent<StateKey = EmptyStateKey> + Default,
366{
367    fn default() -> Self {
368        Self { content: Default::default(), state_key: EmptyStateKey }
369    }
370}
371
372impl<C: StaticStateEventContent> Serialize for InitialStateEvent<C> {
373    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
374    where
375        S: serde::Serializer,
376    {
377        let mut state = serializer.serialize_struct("InitialStateEvent", 3)?;
378        state.serialize_field("type", &self.content.event_type())?;
379        state.serialize_field("content", &self.content)?;
380        state.serialize_field("state_key", &self.state_key)?;
381        state.end()
382    }
383}
384
385/// A redacted state event.
386///
387/// `RedactedStateEvent` implements the comparison traits using only the `event_id` field, a sorted
388/// list would be sorted lexicographically based on the event's `EventId`.
389#[derive(Clone, Debug, Event)]
390pub struct RedactedStateEvent<C: RedactedStateEventContent> {
391    /// Data specific to the event type.
392    pub content: C,
393
394    /// The globally unique event identifier for the user who sent the event.
395    pub event_id: OwnedEventId,
396
397    /// The fully-qualified ID of the user who sent this event.
398    pub sender: OwnedUserId,
399
400    /// Timestamp in milliseconds on originating homeserver when this event was sent.
401    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
402
403    /// The ID of the room associated with this event.
404    pub room_id: OwnedRoomId,
405
406    /// A unique key which defines the overwriting semantics for this piece of room state.
407    ///
408    /// This is often an empty string, but some events send a `UserId` to show which user the event
409    /// affects.
410    pub state_key: C::StateKey,
411
412    /// Additional key-value pairs not signed by the homeserver.
413    pub unsigned: RedactedUnsigned,
414}
415
416/// A redacted state event without a `room_id`.
417///
418/// `RedactedSyncStateEvent` implements the comparison traits using only the `event_id` field, a
419/// sorted list would be sorted lexicographically based on the event's `EventId`.
420#[derive(Clone, Debug, Event)]
421pub struct RedactedSyncStateEvent<C: RedactedStateEventContent> {
422    /// Data specific to the event type.
423    pub content: C,
424
425    /// The globally unique event identifier for the user who sent the event.
426    pub event_id: OwnedEventId,
427
428    /// The fully-qualified ID of the user who sent this event.
429    pub sender: OwnedUserId,
430
431    /// Timestamp in milliseconds on originating homeserver when this event was sent.
432    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
433
434    /// A unique key which defines the overwriting semantics for this piece of room state.
435    ///
436    /// This is often an empty string, but some events send a `UserId` to show which user the event
437    /// affects.
438    pub state_key: C::StateKey,
439
440    /// Additional key-value pairs not signed by the homeserver.
441    pub unsigned: RedactedUnsigned,
442}
443
444/// A possibly-redacted state event.
445///
446/// `StateEvent` implements the comparison traits using only the `event_id` field, a sorted list
447/// would be sorted lexicographically based on the event's `EventId`.
448#[allow(clippy::exhaustive_enums)]
449#[derive(Clone, Debug)]
450pub enum StateEvent<C: StaticStateEventContent + RedactContent>
451where
452    C::Redacted: RedactedStateEventContent,
453{
454    /// Original, unredacted form of the event.
455    Original(OriginalStateEvent<C>),
456
457    /// Redacted form of the event with minimal fields.
458    Redacted(RedactedStateEvent<C::Redacted>),
459}
460
461/// A possibly-redacted state event without a `room_id`.
462///
463/// `SyncStateEvent` implements the comparison traits using only the `event_id` field, a sorted list
464/// would be sorted lexicographically based on the event's `EventId`.
465#[allow(clippy::exhaustive_enums)]
466#[derive(Clone, Debug)]
467pub enum SyncStateEvent<C: StaticStateEventContent + RedactContent>
468where
469    C::Redacted: RedactedStateEventContent,
470{
471    /// Original, unredacted form of the event.
472    Original(OriginalSyncStateEvent<C>),
473
474    /// Redacted form of the event with minimal fields.
475    Redacted(RedactedSyncStateEvent<C::Redacted>),
476}
477
478/// An event sent using send-to-device messaging.
479#[derive(Clone, Debug, Event)]
480pub struct ToDeviceEvent<C: ToDeviceEventContent> {
481    /// Data specific to the event type.
482    pub content: C,
483
484    /// The fully-qualified ID of the user who sent this event.
485    pub sender: OwnedUserId,
486}
487
488impl<C: ToDeviceEventContent> Serialize for ToDeviceEvent<C> {
489    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
490    where
491        S: serde::Serializer,
492    {
493        let mut state = serializer.serialize_struct("ToDeviceEvent", 3)?;
494        state.serialize_field("type", &self.content.event_type())?;
495        state.serialize_field("content", &self.content)?;
496        state.serialize_field("sender", &self.sender)?;
497        state.end()
498    }
499}
500
501/// The decrypted payload of an `m.olm.v1.curve25519-aes-sha2` event.
502#[derive(Clone, Debug, Event)]
503pub struct DecryptedOlmV1Event<C: MessageLikeEventContent> {
504    /// Data specific to the event type.
505    pub content: C,
506
507    /// The fully-qualified ID of the user who sent this event.
508    pub sender: OwnedUserId,
509
510    /// The fully-qualified ID of the intended recipient this event.
511    pub recipient: OwnedUserId,
512
513    /// The recipient's ed25519 key.
514    pub recipient_keys: OlmV1Keys,
515
516    /// The sender's ed25519 key.
517    pub keys: OlmV1Keys,
518}
519
520/// Public keys used for an `m.olm.v1.curve25519-aes-sha2` event.
521#[derive(Clone, Debug, Deserialize, Serialize)]
522pub struct OlmV1Keys {
523    /// An ed25519 key.
524    pub ed25519: String,
525}
526
527/// The decrypted payload of an `m.megolm.v1.aes-sha2` event.
528#[derive(Clone, Debug, Event)]
529pub struct DecryptedMegolmV1Event<C: MessageLikeEventContent> {
530    /// Data specific to the event type.
531    pub content: C,
532
533    /// The ID of the room associated with the event.
534    pub room_id: OwnedRoomId,
535}
536
537/// A possibly-redacted state event content.
538///
539/// A non-redacted content also contains the `prev_content` from the unsigned event data.
540#[allow(clippy::exhaustive_enums)]
541#[derive(Clone, Debug)]
542pub enum FullStateEventContent<C: StaticStateEventContent + RedactContent> {
543    /// Original, unredacted content of the event.
544    Original {
545        /// Current content of the room state.
546        content: C,
547
548        /// Previous content of the room state.
549        prev_content: Option<C::PossiblyRedacted>,
550    },
551
552    /// Redacted content of the event.
553    Redacted(C::Redacted),
554}
555
556impl<C: StaticStateEventContent + RedactContent> FullStateEventContent<C>
557where
558    C::Redacted: RedactedStateEventContent,
559{
560    /// Get the event’s type, like `m.room.create`.
561    pub fn event_type(&self) -> StateEventType {
562        match self {
563            Self::Original { content, .. } => content.event_type(),
564            Self::Redacted(content) => content.event_type(),
565        }
566    }
567
568    /// Transform `self` into a redacted form (removing most or all fields) according to the spec.
569    ///
570    /// If `self` is already [`Redacted`](Self::Redacted), return the inner data unmodified.
571    ///
572    /// A small number of events have room-version specific redaction behavior, so a version has to
573    /// be specified.
574    pub fn redact(self, version: &RoomVersionId) -> C::Redacted {
575        match self {
576            FullStateEventContent::Original { content, .. } => content.redact(version),
577            FullStateEventContent::Redacted(content) => content,
578        }
579    }
580}
581
582macro_rules! impl_possibly_redacted_event {
583    (
584        $ty:ident ( $content_trait:ident, $redacted_content_trait:ident, $event_type:ident )
585        $( where C::Redacted: $trait:ident<StateKey = C::StateKey>, )?
586        { $($extra:tt)* }
587    ) => {
588        impl<C> $ty<C>
589        where
590            C: $content_trait + RedactContent,
591            C::Redacted: $redacted_content_trait,
592            $( C::Redacted: $trait<StateKey = C::StateKey>, )?
593        {
594            /// Returns the `type` of this event.
595            pub fn event_type(&self) -> $event_type {
596                match self {
597                    Self::Original(ev) => ev.content.event_type(),
598                    Self::Redacted(ev) => ev.content.event_type(),
599                }
600            }
601
602            /// Returns this event's `event_id` field.
603            pub fn event_id(&self) -> &EventId {
604                match self {
605                    Self::Original(ev) => &ev.event_id,
606                    Self::Redacted(ev) => &ev.event_id,
607                }
608            }
609
610            /// Returns this event's `sender` field.
611            pub fn sender(&self) -> &UserId {
612                match self {
613                    Self::Original(ev) => &ev.sender,
614                    Self::Redacted(ev) => &ev.sender,
615                }
616            }
617
618            /// Returns this event's `origin_server_ts` field.
619            pub fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
620                match self {
621                    Self::Original(ev) => ev.origin_server_ts,
622                    Self::Redacted(ev) => ev.origin_server_ts,
623                }
624            }
625
626            // So the room_id method can be in the same impl block, in rustdoc
627            $($extra)*
628        }
629
630        impl<'de, C> Deserialize<'de> for $ty<C>
631        where
632            C: $content_trait + EventContentFromType + RedactContent,
633            C::Redacted: $redacted_content_trait + EventContentFromType,
634            $( C::Redacted: $trait<StateKey = C::StateKey>, )?
635        {
636            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
637            where
638                D: Deserializer<'de>,
639            {
640                let json = Box::<RawJsonValue>::deserialize(deserializer)?;
641                let RedactionDeHelper { unsigned } = from_raw_json_value(&json)?;
642
643                if unsigned.and_then(|u| u.redacted_because).is_some() {
644                    Ok(Self::Redacted(from_raw_json_value(&json)?))
645                } else {
646                    Ok(Self::Original(from_raw_json_value(&json)?))
647                }
648            }
649        }
650    }
651}
652
653impl_possibly_redacted_event!(
654    MessageLikeEvent(
655        MessageLikeEventContent, RedactedMessageLikeEventContent, MessageLikeEventType
656    ) {
657        /// Returns this event's `room_id` field.
658        pub fn room_id(&self) -> &RoomId {
659            match self {
660                Self::Original(ev) => &ev.room_id,
661                Self::Redacted(ev) => &ev.room_id,
662            }
663        }
664
665        /// Get the inner `OriginalMessageLikeEvent` if this is an unredacted event.
666        pub fn as_original(&self) -> Option<&OriginalMessageLikeEvent<C>> {
667            as_variant!(self, Self::Original)
668        }
669    }
670);
671
672impl_possibly_redacted_event!(
673    SyncMessageLikeEvent(
674        MessageLikeEventContent, RedactedMessageLikeEventContent, MessageLikeEventType
675    ) {
676        /// Get the inner `OriginalSyncMessageLikeEvent` if this is an unredacted event.
677        pub fn as_original(&self) -> Option<&OriginalSyncMessageLikeEvent<C>> {
678            as_variant!(self, Self::Original)
679        }
680
681        /// Convert this sync event into a full event (one with a `room_id` field).
682        pub fn into_full_event(self, room_id: OwnedRoomId) -> MessageLikeEvent<C> {
683            match self {
684                Self::Original(ev) => MessageLikeEvent::Original(ev.into_full_event(room_id)),
685                Self::Redacted(ev) => MessageLikeEvent::Redacted(ev.into_full_event(room_id)),
686            }
687        }
688    }
689);
690
691impl_possibly_redacted_event!(
692    StateEvent(StaticStateEventContent, RedactedStateEventContent, StateEventType)
693    where
694        C::Redacted: RedactedStateEventContent<StateKey = C::StateKey>,
695    {
696        /// Returns this event's `room_id` field.
697        pub fn room_id(&self) -> &RoomId {
698            match self {
699                Self::Original(ev) => &ev.room_id,
700                Self::Redacted(ev) => &ev.room_id,
701            }
702        }
703
704        /// Returns this event's `state_key` field.
705        pub fn state_key(&self) -> &C::StateKey {
706            match self {
707                Self::Original(ev) => &ev.state_key,
708                Self::Redacted(ev) => &ev.state_key,
709            }
710        }
711
712        /// Get the inner `OriginalStateEvent` if this is an unredacted event.
713        pub fn as_original(&self) -> Option<&OriginalStateEvent<C>> {
714            as_variant!(self, Self::Original)
715        }
716    }
717);
718
719impl_possibly_redacted_event!(
720    SyncStateEvent(StaticStateEventContent, RedactedStateEventContent, StateEventType)
721    where
722        C::Redacted: RedactedStateEventContent<StateKey = C::StateKey>,
723    {
724        /// Returns this event's `state_key` field.
725        pub fn state_key(&self) -> &C::StateKey {
726            match self {
727                Self::Original(ev) => &ev.state_key,
728                Self::Redacted(ev) => &ev.state_key,
729            }
730        }
731
732        /// Get the inner `OriginalSyncStateEvent` if this is an unredacted event.
733        pub fn as_original(&self) -> Option<&OriginalSyncStateEvent<C>> {
734            as_variant!(self, Self::Original)
735        }
736
737        /// Convert this sync event into a full event (one with a `room_id` field).
738        pub fn into_full_event(self, room_id: OwnedRoomId) -> StateEvent<C> {
739            match self {
740                Self::Original(ev) => StateEvent::Original(ev.into_full_event(room_id)),
741                Self::Redacted(ev) => StateEvent::Redacted(ev.into_full_event(room_id)),
742            }
743        }
744    }
745);
746
747macro_rules! impl_sync_from_full {
748    ($ty:ident, $full:ident, $content_trait:ident, $redacted_content_trait: ident) => {
749        impl<C> From<$full<C>> for $ty<C>
750        where
751            C: $content_trait + RedactContent,
752            C::Redacted: $redacted_content_trait,
753        {
754            fn from(full: $full<C>) -> Self {
755                match full {
756                    $full::Original(ev) => Self::Original(ev.into()),
757                    $full::Redacted(ev) => Self::Redacted(ev.into()),
758                }
759            }
760        }
761    };
762}
763
764impl_sync_from_full!(
765    SyncMessageLikeEvent,
766    MessageLikeEvent,
767    MessageLikeEventContent,
768    RedactedMessageLikeEventContent
769);
770impl_sync_from_full!(
771    SyncStateEvent,
772    StateEvent,
773    StaticStateEventContent,
774    RedactedStateEventContent
775);