diff --git a/crates/ruma-common/src/events/kinds.rs b/crates/ruma-common/src/events/kinds.rs index f8298461..1f7d9f50 100644 --- a/crates/ruma-common/src/events/kinds.rs +++ b/crates/ruma-common/src/events/kinds.rs @@ -145,6 +145,15 @@ pub struct OriginalSyncMessageLikeEvent { pub unsigned: MessageLikeUnsigned, } +impl OriginalSyncMessageLikeEvent +where + C::Redacted: RedactedMessageLikeEventContent, +{ + pub(crate) fn into_maybe_redacted(self) -> SyncMessageLikeEvent { + SyncMessageLikeEvent::Original(self) + } +} + /// A redacted message-like event. /// /// `RedactedMessageLikeEvent` implements the comparison traits using only the `event_id` field, a diff --git a/crates/ruma-common/src/events/relation.rs b/crates/ruma-common/src/events/relation.rs index c5e2b46c..88b487fc 100644 --- a/crates/ruma-common/src/events/relation.rs +++ b/crates/ruma-common/src/events/relation.rs @@ -240,6 +240,14 @@ impl BundledMessageLikeRelations { pub fn is_empty(&self) -> bool { self.replace.is_none() && self.thread.is_none() && self.reference.is_none() } + + /// Transform `BundledMessageLikeRelations` to `BundledMessageLikeRelations` using the + /// given closure to convert the `replace` field if it is `Some(_)`. + pub(crate) fn map_replace(self, f: impl FnOnce(E) -> T) -> BundledMessageLikeRelations { + let Self { replace, has_invalid_replacement, thread, reference } = self; + let replace = replace.map(|r| Box::new(f(*r))); + BundledMessageLikeRelations { replace, has_invalid_replacement, thread, reference } + } } impl Default for BundledMessageLikeRelations { diff --git a/crates/ruma-common/src/events/room/redaction.rs b/crates/ruma-common/src/events/room/redaction.rs index 7c1d230d..41b596dd 100644 --- a/crates/ruma-common/src/events/room/redaction.rs +++ b/crates/ruma-common/src/events/room/redaction.rs @@ -111,6 +111,12 @@ pub struct OriginalSyncRoomRedactionEvent { pub unsigned: RoomRedactionUnsigned, } +impl OriginalSyncRoomRedactionEvent { + pub(crate) fn into_maybe_redacted(self) -> SyncRoomRedactionEvent { + SyncRoomRedactionEvent::Original(self) + } +} + /// Redacted redaction event without a `room_id`. #[derive(Clone, Debug, Event)] #[allow(clippy::exhaustive_structs)] diff --git a/crates/ruma-macros/src/events/event_enum.rs b/crates/ruma-macros/src/events/event_enum.rs index 2b520240..5dc1768d 100644 --- a/crates/ruma-macros/src/events/event_enum.rs +++ b/crates/ruma-macros/src/events/event_enum.rs @@ -604,6 +604,34 @@ fn expand_accessor_methods( } }); + let relations_accessor = (kind == EventKind::MessageLike).then(|| { + let variants = variants.iter().map(|v| v.match_arm(quote! { Self })); + + quote! { + /// Returns this event's `relations` from inside `unsigned`. + pub fn relations( + &self, + ) -> #ruma_common::events::BundledMessageLikeRelations { + match self { + #( + #variants(event) => event.as_original().map_or_else( + ::std::default::Default::default, + |ev| ev.unsigned.relations.clone().map_replace(|r| { + ::std::convert::From::from(r.into_maybe_redacted()) + }), + ), + )* + Self::_Custom(event) => event.as_original().map_or_else( + ::std::default::Default::default, + |ev| ev.unsigned.relations.clone().map_replace(|r| { + AnySyncMessageLikeEvent::_Custom(r.into_maybe_redacted()) + }), + ), + } + } + } + }); + let maybe_redacted_accessors = maybe_redacted.then(|| { let variants = variants.iter().map(|v| v.match_arm(quote! { Self })); @@ -634,6 +662,7 @@ fn expand_accessor_methods( #content_accessor #( #methods )* + #relations_accessor #state_key_accessor #maybe_redacted_accessors }