diff --git a/crates/ruma-client-api/src/config/set_global_account_data.rs b/crates/ruma-client-api/src/config/set_global_account_data.rs index da81ee42..d6eb57e4 100644 --- a/crates/ruma-client-api/src/config/set_global_account_data.rs +++ b/crates/ruma-client-api/src/config/set_global_account_data.rs @@ -7,7 +7,7 @@ pub mod v3 { use ruma_common::{ api::ruma_api, - events::{AnyGlobalAccountDataEventContent, GlobalAccountDataEventContent}, + events::{AnyGlobalAccountDataEventContent, EventContent, GlobalAccountDataEventType}, serde::Raw, UserId, }; @@ -58,10 +58,10 @@ pub mod v3 { /// /// Since `Request` stores the request body in serialized form, this function can fail if /// `T`s [`Serialize`][serde::Serialize] implementation can fail. - pub fn new( - data: &'a T, - user_id: &'a UserId, - ) -> serde_json::Result { + pub fn new(data: &'a T, user_id: &'a UserId) -> serde_json::Result + where + T: EventContent, + { Ok(Self { user_id, event_type: data.event_type(), diff --git a/crates/ruma-client-api/src/config/set_room_account_data.rs b/crates/ruma-client-api/src/config/set_room_account_data.rs index 88331ece..4909e2b9 100644 --- a/crates/ruma-client-api/src/config/set_room_account_data.rs +++ b/crates/ruma-client-api/src/config/set_room_account_data.rs @@ -7,7 +7,7 @@ pub mod v3 { use ruma_common::{ api::ruma_api, - events::{AnyRoomAccountDataEventContent, RoomAccountDataEventContent}, + events::{AnyRoomAccountDataEventContent, EventContent, RoomAccountDataEventType}, serde::Raw, RoomId, UserId, }; @@ -62,11 +62,14 @@ pub mod v3 { /// /// Since `Request` stores the request body in serialized form, this function can fail if /// `T`s [`Serialize`][serde::Serialize] implementation can fail. - pub fn new( + pub fn new( data: &'a T, room_id: &'a RoomId, user_id: &'a UserId, - ) -> serde_json::Result { + ) -> serde_json::Result + where + T: EventContent, + { Ok(Self { data: Raw::from_json(to_raw_json_value(data)?), event_type: data.event_type(), diff --git a/crates/ruma-client-api/src/message/send_message_event.rs b/crates/ruma-client-api/src/message/send_message_event.rs index a94022c5..ed324889 100644 --- a/crates/ruma-client-api/src/message/send_message_event.rs +++ b/crates/ruma-client-api/src/message/send_message_event.rs @@ -7,7 +7,7 @@ pub mod v3 { use ruma_common::{ api::ruma_api, - events::{AnyMessageLikeEventContent, MessageLikeEventContent}, + events::{AnyMessageLikeEventContent, EventContent, MessageLikeEventType}, serde::Raw, EventId, RoomId, TransactionId, }; @@ -62,11 +62,14 @@ pub mod v3 { /// /// Since `Request` stores the request body in serialized form, this function can fail if /// `T`s [`Serialize`][serde::Serialize] implementation can fail. - pub fn new( + pub fn new( room_id: &'a RoomId, txn_id: &'a TransactionId, content: &'a T, - ) -> serde_json::Result { + ) -> serde_json::Result + where + T: EventContent, + { Ok(Self { room_id, txn_id, diff --git a/crates/ruma-client-api/src/state/send_state_event.rs b/crates/ruma-client-api/src/state/send_state_event.rs index 42a714a6..f4ab0721 100644 --- a/crates/ruma-client-api/src/state/send_state_event.rs +++ b/crates/ruma-client-api/src/state/send_state_event.rs @@ -7,7 +7,7 @@ pub mod v3 { use ruma_common::{ api::ruma_api, - events::{AnyStateEventContent, StateEventContent}, + events::{AnyStateEventContent, EventContent, StateEventType}, serde::{Outgoing, Raw}, EventId, RoomId, }; @@ -60,11 +60,14 @@ pub mod v3 { /// /// Since `Request` stores the request body in serialized form, this function can fail if /// `T`s [`Serialize`][serde::Serialize] implementation can fail. - pub fn new( + pub fn new( room_id: &'a RoomId, state_key: &'a str, content: &'a T, - ) -> serde_json::Result { + ) -> serde_json::Result + where + T: EventContent, + { Ok(Self { room_id, state_key, diff --git a/crates/ruma-common/src/events.rs b/crates/ruma-common/src/events.rs index 1c0b82c8..4bf8d71b 100644 --- a/crates/ruma-common/src/events.rs +++ b/crates/ruma-common/src/events.rs @@ -199,12 +199,16 @@ pub use self::{ /// The base trait that all event content types implement. /// -/// Implementing this trait allows content types to be serialized as well as deserialized. +/// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually. pub trait EventContent: Sized + Serialize { - /// A matrix event identifier, like `m.room.message`. + /// The Rust enum for the event kind's known types. + type EventType; + + /// Get the event's type, like `m.room.message`. fn event_type(&self) -> &str; /// Constructs the given event content. + #[doc(hidden)] fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result; } @@ -241,24 +245,6 @@ impl Raw { } } -/// Marker trait for the content of an ephemeral room event. -pub trait EphemeralRoomEventContent: EventContent {} - -/// Marker trait for the content of a global account data event. -pub trait GlobalAccountDataEventContent: EventContent {} - -/// Marker trait for the content of a room account data event. -pub trait RoomAccountDataEventContent: EventContent {} - -/// Marker trait for the content of a to device event. -pub trait ToDeviceEventContent: EventContent {} - -/// Marker trait for the content of a message-like event. -pub trait MessageLikeEventContent: EventContent {} - -/// Marker trait for the content of a state event. -pub trait StateEventContent: EventContent {} - /// The base trait that all redacted event content types implement. /// /// This trait's associated functions and methods should not be used to build @@ -284,12 +270,6 @@ pub trait RedactedEventContent: EventContent { fn has_deserialize_fields() -> HasDeserializeFields; } -/// Marker trait for the content of a redacted message-like event. -pub trait RedactedMessageLikeEventContent: RedactedEventContent {} - -/// Marker trait for the content of a redacted state event. -pub trait RedactedStateEventContent: RedactedEventContent {} - /// Trait for abstracting over event content structs. /// /// … but *not* enums which don't always have an event type and kind (e.g. message vs state) that's diff --git a/crates/ruma-common/src/events/_custom.rs b/crates/ruma-common/src/events/_custom.rs index aa10db46..75ca4798 100644 --- a/crates/ruma-common/src/events/_custom.rs +++ b/crates/ruma-common/src/events/_custom.rs @@ -2,59 +2,69 @@ use serde::Serialize; use serde_json::value::RawValue as RawJsonValue; use super::{ - EphemeralRoomEventContent, EventContent, GlobalAccountDataEventContent, HasDeserializeFields, - MessageLikeEventContent, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent, - RedactedStateEventContent, RoomAccountDataEventContent, StateEventContent, - ToDeviceEventContent, + EphemeralRoomEventType, EventContent, GlobalAccountDataEventType, HasDeserializeFields, + MessageLikeEventType, RedactContent, RedactedEventContent, RoomAccountDataEventType, + StateEventType, ToDeviceEventType, }; use crate::RoomVersionId; -/// A custom event's type. Used for event enum `_Custom` variants. -// FIXME: Serialize shouldn't be required here, but it's currently a supertrait of EventContent -#[derive(Clone, Debug, Serialize)] -#[allow(clippy::exhaustive_structs)] -pub struct CustomEventContent { - #[serde(skip)] - event_type: Box, +macro_rules! custom_event_content { + ($i:ident, $evt:ident) => { + /// A custom event's type. Used for event enum `_Custom` variants. + // FIXME: Serialize shouldn't be required here, but it's currently a supertrait of + // EventContent + #[derive(Clone, Debug, Serialize)] + #[allow(clippy::exhaustive_structs)] + pub struct $i { + #[serde(skip)] + event_type: Box, + } + + impl EventContent for $i { + type EventType = $evt; + + fn event_type(&self) -> &str { + &self.event_type + } + + fn from_parts(event_type: &str, _content: &RawJsonValue) -> serde_json::Result { + Ok(Self { event_type: event_type.into() }) + } + } + }; } -impl RedactContent for CustomEventContent { - type Redacted = Self; +macro_rules! custom_room_event_content { + ($i:ident, $evt:ident) => { + custom_event_content!($i, $evt); - fn redact(self, _: &RoomVersionId) -> Self { - self - } + impl RedactContent for $i { + type Redacted = Self; + + fn redact(self, _: &RoomVersionId) -> Self { + self + } + } + + impl RedactedEventContent for $i { + fn empty(event_type: &str) -> serde_json::Result { + Ok(Self { event_type: event_type.into() }) + } + + fn has_serialize_fields(&self) -> bool { + false + } + + fn has_deserialize_fields() -> HasDeserializeFields { + HasDeserializeFields::False + } + } + }; } -impl EventContent for CustomEventContent { - fn event_type(&self) -> &str { - &self.event_type - } - - fn from_parts(event_type: &str, _content: &RawJsonValue) -> serde_json::Result { - Ok(Self { event_type: event_type.into() }) - } -} - -impl RedactedEventContent for CustomEventContent { - fn empty(event_type: &str) -> serde_json::Result { - Ok(Self { event_type: event_type.into() }) - } - - fn has_serialize_fields(&self) -> bool { - false - } - - fn has_deserialize_fields() -> HasDeserializeFields { - HasDeserializeFields::False - } -} - -impl GlobalAccountDataEventContent for CustomEventContent {} -impl RoomAccountDataEventContent for CustomEventContent {} -impl ToDeviceEventContent for CustomEventContent {} -impl EphemeralRoomEventContent for CustomEventContent {} -impl MessageLikeEventContent for CustomEventContent {} -impl StateEventContent for CustomEventContent {} -impl RedactedMessageLikeEventContent for CustomEventContent {} -impl RedactedStateEventContent for CustomEventContent {} +custom_event_content!(CustomGlobalAccountDataEventContent, GlobalAccountDataEventType); +custom_event_content!(CustomRoomAccountDataEventContent, RoomAccountDataEventType); +custom_event_content!(CustomEphemeralRoomEventContent, EphemeralRoomEventType); +custom_room_event_content!(CustomMessageLikeEventContent, MessageLikeEventType); +custom_room_event_content!(CustomStateEventContent, StateEventType); +custom_event_content!(CustomToDeviceEventContent, ToDeviceEventType); diff --git a/crates/ruma-common/src/events/event_kinds.rs b/crates/ruma-common/src/events/event_kinds.rs index 6200d48d..61fe67ec 100644 --- a/crates/ruma-common/src/events/event_kinds.rs +++ b/crates/ruma-common/src/events/event_kinds.rs @@ -4,29 +4,29 @@ use ruma_macros::Event; use serde::{Deserialize, Serialize}; use super::{ - EphemeralRoomEventContent, GlobalAccountDataEventContent, MessageLikeEventContent, - RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned, - RoomAccountDataEventContent, StateEventContent, ToDeviceEventContent, Unsigned, + EphemeralRoomEventType, EventContent, GlobalAccountDataEventType, MessageLikeEventType, + RedactedEventContent, RedactedUnsigned, RoomAccountDataEventType, StateEventType, + ToDeviceEventType, Unsigned, }; use crate::{EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId}; /// A global account data event. #[derive(Clone, Debug, Event)] -pub struct GlobalAccountDataEvent { +pub struct GlobalAccountDataEvent> { /// Data specific to the event type. pub content: C, } /// A room account data event. #[derive(Clone, Debug, Event)] -pub struct RoomAccountDataEvent { +pub struct RoomAccountDataEvent> { /// Data specific to the event type. pub content: C, } /// An ephemeral room event. #[derive(Clone, Debug, Event)] -pub struct EphemeralRoomEvent { +pub struct EphemeralRoomEvent> { /// Data specific to the event type. pub content: C, @@ -36,7 +36,7 @@ pub struct EphemeralRoomEvent { /// An ephemeral room event without a `room_id`. #[derive(Clone, Debug, Event)] -pub struct SyncEphemeralRoomEvent { +pub struct SyncEphemeralRoomEvent> { /// Data specific to the event type. pub content: C, } @@ -46,7 +46,7 @@ pub struct SyncEphemeralRoomEvent { /// `MessageLikeEvent` implements the comparison traits using only the `event_id` field, a sorted /// list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct MessageLikeEvent { +pub struct MessageLikeEvent> { /// Data specific to the event type. pub content: C, @@ -71,7 +71,7 @@ pub struct MessageLikeEvent { /// `SyncMessageLikeEvent` implements the comparison traits using only the `event_id` field, a /// sorted list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct SyncMessageLikeEvent { +pub struct SyncMessageLikeEvent> { /// Data specific to the event type. pub content: C, @@ -93,7 +93,9 @@ pub struct SyncMessageLikeEvent { /// `RedactedMessageLikeEvent` implements the comparison traits using only the `event_id` field, a /// sorted list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct RedactedMessageLikeEvent { +pub struct RedactedMessageLikeEvent< + C: EventContent + RedactedEventContent, +> { /// Data specific to the event type. pub content: C, @@ -118,7 +120,9 @@ pub struct RedactedMessageLikeEvent { /// `RedactedSyncMessageLikeEvent` implements the comparison traits using only the `event_id` field, /// a sorted list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct RedactedSyncMessageLikeEvent { +pub struct RedactedSyncMessageLikeEvent< + C: EventContent + RedactedEventContent, +> { /// Data specific to the event type. pub content: C, @@ -140,7 +144,7 @@ pub struct RedactedSyncMessageLikeEvent { /// `StateEvent` implements the comparison traits using only the `event_id` field, a sorted list /// would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct StateEvent { +pub struct StateEvent> { /// Data specific to the event type. pub content: C, @@ -174,7 +178,7 @@ pub struct StateEvent { /// `SyncStateEvent` implements the comparison traits using only the `event_id` field, a sorted list /// would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct SyncStateEvent { +pub struct SyncStateEvent> { /// Data specific to the event type. pub content: C, @@ -202,7 +206,7 @@ pub struct SyncStateEvent { /// A stripped-down state event, used for previews of rooms the user has been invited to. #[derive(Clone, Debug, Event)] -pub struct StrippedStateEvent { +pub struct StrippedStateEvent> { /// Data specific to the event type. pub content: C, @@ -218,7 +222,7 @@ pub struct StrippedStateEvent { /// A minimal state event, used for creating a new room. #[derive(Clone, Debug, Event)] -pub struct InitialStateEvent { +pub struct InitialStateEvent> { /// Data specific to the event type. pub content: C, @@ -237,7 +241,7 @@ pub struct InitialStateEvent { /// `RedactedStateEvent` implements the comparison traits using only the `event_id` field, a sorted /// list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct RedactedStateEvent { +pub struct RedactedStateEvent + RedactedEventContent> { /// Data specific to the event type. pub content: C, @@ -268,7 +272,9 @@ pub struct RedactedStateEvent { /// `RedactedSyncStateEvent` implements the comparison traits using only the `event_id` field, a /// sorted list would be sorted lexicographically based on the event's `EventId`. #[derive(Clone, Debug, Event)] -pub struct RedactedSyncStateEvent { +pub struct RedactedSyncStateEvent< + C: EventContent + RedactedEventContent, +> { /// Data specific to the event type. pub content: C, @@ -293,7 +299,7 @@ pub struct RedactedSyncStateEvent { /// An event sent using send-to-device messaging. #[derive(Clone, Debug, Event)] -pub struct ToDeviceEvent { +pub struct ToDeviceEvent> { /// Data specific to the event type. pub content: C, @@ -303,7 +309,7 @@ pub struct ToDeviceEvent { /// The decrypted payload of an `m.olm.v1.curve25519-aes-sha2` event. #[derive(Clone, Debug, Event)] -pub struct DecryptedOlmV1Event { +pub struct DecryptedOlmV1Event> { /// Data specific to the event type. pub content: C, @@ -329,7 +335,7 @@ pub struct OlmV1Keys { /// The decrypted payload of an `m.megolm.v1.aes-sha2` event. #[derive(Clone, Debug, Event)] -pub struct DecryptedMegolmV1Event { +pub struct DecryptedMegolmV1Event> { /// Data specific to the event type. pub content: C, diff --git a/crates/ruma-common/src/events/room/aliases.rs b/crates/ruma-common/src/events/room/aliases.rs index dada94bc..eb365aaf 100644 --- a/crates/ruma-common/src/events/room/aliases.rs +++ b/crates/ruma-common/src/events/room/aliases.rs @@ -6,8 +6,7 @@ use serde_json::value::RawValue as RawJsonValue; use crate::{ events::{ - EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, - RedactedStateEventContent, + EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventType, }, RoomAliasId, RoomVersionId, }; @@ -77,6 +76,8 @@ impl RedactedRoomAliasesEventContent { } impl EventContent for RedactedRoomAliasesEventContent { + type EventType = StateEventType; + fn event_type(&self) -> &str { "m.room.aliases" } @@ -104,5 +105,3 @@ impl RedactedEventContent for RedactedRoomAliasesEventContent { HasDeserializeFields::Optional } } - -impl RedactedStateEventContent for RedactedRoomAliasesEventContent {} diff --git a/crates/ruma-common/src/events/room/member.rs b/crates/ruma-common/src/events/room/member.rs index 4bd4e11c..adb03e11 100644 --- a/crates/ruma-common/src/events/room/member.rs +++ b/crates/ruma-common/src/events/room/member.rs @@ -10,8 +10,8 @@ use serde_json::value::RawValue as RawJsonValue; use crate::{ events::{ - EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, - RedactedStateEventContent, StrippedStateEvent, SyncStateEvent, + EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventType, + StrippedStateEvent, SyncStateEvent, }, serde::StringEnum, MxcUri, PrivOwnedStr, RoomVersionId, ServerName, ServerSigningKeyId, UserId, @@ -159,6 +159,8 @@ impl RedactedRoomMemberEventContent { } impl EventContent for RedactedRoomMemberEventContent { + type EventType = StateEventType; + fn event_type(&self) -> &str { "m.room.member" } @@ -187,8 +189,6 @@ impl RedactedEventContent for RedactedRoomMemberEventContent { } } -impl RedactedStateEventContent for RedactedRoomMemberEventContent {} - /// The membership state of a user. /// /// This type can hold an arbitrary string. To check for formats that are not available as a diff --git a/crates/ruma-common/tests/events/ui/04-event-sanity-check.rs b/crates/ruma-common/tests/events/ui/04-event-sanity-check.rs index 5f29d690..a180f73e 100644 --- a/crates/ruma-common/tests/events/ui/04-event-sanity-check.rs +++ b/crates/ruma-common/tests/events/ui/04-event-sanity-check.rs @@ -4,14 +4,14 @@ extern crate serde; use ruma_common::{ - events::{StateEventContent, Unsigned}, + events::{EventContent, StateEventType, Unsigned}, EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId, }; use ruma_macros::Event; /// State event. #[derive(Clone, Debug, Event)] -pub struct StateEvent { +pub struct StateEvent> { pub content: C, pub event_id: Box, pub sender: Box, diff --git a/crates/ruma-common/tests/events/ui/05-named-fields.rs b/crates/ruma-common/tests/events/ui/05-named-fields.rs index 9fb1defb..444c917f 100644 --- a/crates/ruma-common/tests/events/ui/05-named-fields.rs +++ b/crates/ruma-common/tests/events/ui/05-named-fields.rs @@ -1,8 +1,8 @@ -use ruma_common::events::StateEventContent; +use ruma_common::events::{EventContent, StateEventType}; use ruma_macros::Event; /// State event. #[derive(Clone, Debug, Event)] -pub struct StateEvent(C); +pub struct StateEvent>(C); fn main() {} diff --git a/crates/ruma-common/tests/events/ui/05-named-fields.stderr b/crates/ruma-common/tests/events/ui/05-named-fields.stderr index a4245a68..3517fa62 100644 --- a/crates/ruma-common/tests/events/ui/05-named-fields.stderr +++ b/crates/ruma-common/tests/events/ui/05-named-fields.stderr @@ -1,5 +1,5 @@ error: the `Event` derive only supports structs with named fields - --> $DIR/05-named-fields.rs:6:12 + --> tests/events/ui/05-named-fields.rs:6:12 | -6 | pub struct StateEvent(C); +6 | pub struct StateEvent>(C); | ^^^^^^^^^^ diff --git a/crates/ruma-common/tests/events/ui/06-no-content-field.rs b/crates/ruma-common/tests/events/ui/06-no-content-field.rs index ecab017f..32a4d807 100644 --- a/crates/ruma-common/tests/events/ui/06-no-content-field.rs +++ b/crates/ruma-common/tests/events/ui/06-no-content-field.rs @@ -1,9 +1,9 @@ -use ruma_common::events::StateEventContent; +use ruma_common::events::{EventContent, StateEventType}; use ruma_macros::Event; /// State event. #[derive(Clone, Debug, Event)] -pub struct StateEvent { +pub struct StateEvent> { pub not_content: C, } diff --git a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr index 8cb531d0..d78901b6 100644 --- a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr +++ b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr @@ -1,11 +1,11 @@ error: well-known matrix events have to start with `m.` found `not.a.path` - --> $DIR/08-enum-invalid-path.rs:11:9 + --> tests/events/ui/08-enum-invalid-path.rs:11:9 | 11 | "not.a.path", | ^^^^^^^^^^^^ error[E0433]: failed to resolve: could not find `not` in `events` - --> $DIR/08-enum-invalid-path.rs:5:9 + --> tests/events/ui/08-enum-invalid-path.rs:5:9 | 5 | "m.not.a.path", | ^^^^^^^^^^^^^^ could not find `not` in `events` diff --git a/crates/ruma-macros/src/events/event.rs b/crates/ruma-macros/src/events/event.rs index 0e28ecd2..88b831f5 100644 --- a/crates/ruma-macros/src/events/event.rs +++ b/crates/ruma-macros/src/events/event.rs @@ -1,7 +1,7 @@ //! Implementation of the top level `*Event` derive macro. use proc_macro2::{Span, TokenStream}; -use quote::{format_ident, quote}; +use quote::quote; use syn::{ parse_quote, Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, GenericParam, Meta, MetaList, NestedMeta, @@ -415,8 +415,7 @@ fn expand_redact_event( ruma_common: &TokenStream, ) -> TokenStream { let redacted_type = kind.to_event_ident(var.to_redacted()); - let redacted_content_trait = - format_ident!("{}Content", kind.to_event_ident(EventKindVariation::Redacted)); + let redacted_event_type_enum = kind.to_event_type_enum(); let ident = &input.ident; let mut generics = input.generics.clone(); @@ -434,7 +433,8 @@ fn expand_redact_event( where_clause.predicates.push(parse_quote! { #ty_param: #ruma_common::events::RedactContent }); where_clause.predicates.push(parse_quote! { <#ty_param as #ruma_common::events::RedactContent>::Redacted: - #ruma_common::events::#redacted_content_trait + #ruma_common::events::EventContent + + #ruma_common::events::RedactedEventContent }); let (impl_generics, ty_gen, where_clause) = generics.split_for_impl(); diff --git a/crates/ruma-macros/src/events/event_content.rs b/crates/ruma-macros/src/events/event_content.rs index 93d03821..41b71225 100644 --- a/crates/ruma-macros/src/events/event_content.rs +++ b/crates/ruma-macros/src/events/event_content.rs @@ -163,11 +163,10 @@ pub fn expand_event_content( }) .transpose()?; - let event_content_impl = generate_event_content_impl(ident, event_type, ruma_common); + let event_content_impl = + generate_event_content_impl(ident, event_type, event_kind, ruma_common); let static_event_content_impl = event_kind .map(|k| generate_static_event_content_impl(ident, k, false, event_type, ruma_common)); - let marker_trait_impl = - event_kind.map(|k| generate_marker_trait_impl(k, ident, ruma_common)).transpose()?; let type_aliases = event_kind .map(|k| generate_event_type_aliases(k, ident, &event_type.value(), ruma_common)) .transpose()?; @@ -176,7 +175,6 @@ pub fn expand_event_content( #redacted_event_content #event_content_impl #static_event_content_impl - #marker_trait_impl #type_aliases }) } @@ -261,19 +259,7 @@ fn generate_redacted_event_content( }); let redacted_event_content = - generate_event_content_impl(&redacted_ident, event_type, ruma_common); - - let marker_trait_impl = match event_kind { - Some(EventKind::MessageLike) => quote! { - #[automatically_derived] - impl #ruma_common::events::RedactedMessageLikeEventContent for #redacted_ident {} - }, - Some(EventKind::State) => quote! { - #[automatically_derived] - impl #ruma_common::events::RedactedStateEventContent for #redacted_ident {} - }, - _ => TokenStream::new(), - }; + generate_event_content_impl(&redacted_ident, event_type, event_kind, ruma_common); let static_event_content_impl = event_kind.map(|k| { generate_static_event_content_impl(&redacted_ident, k, true, event_type, ruma_common) @@ -323,7 +309,6 @@ fn generate_redacted_event_content( } #static_event_content_impl - #marker_trait_impl }) } @@ -384,47 +369,28 @@ fn generate_event_type_aliases( Ok(type_aliases) } -fn generate_marker_trait_impl( - event_kind: EventKind, - ident: &Ident, - ruma_common: &TokenStream, -) -> syn::Result { - let marker_trait = match event_kind { - EventKind::GlobalAccountData => quote! { GlobalAccountDataEventContent }, - EventKind::RoomAccountData => quote! { RoomAccountDataEventContent }, - EventKind::Ephemeral => quote! { EphemeralRoomEventContent }, - EventKind::MessageLike => quote! { MessageLikeEventContent }, - EventKind::State => quote! { StateEventContent }, - EventKind::ToDevice => quote! { ToDeviceEventContent }, - EventKind::RoomRedaction - | EventKind::Presence - | EventKind::Decrypted - | EventKind::HierarchySpaceChild => { - return Err(syn::Error::new_spanned( - ident, - "valid event kinds are GlobalAccountData, RoomAccountData, \ - EphemeralRoom, MessageLike, State, ToDevice", - )); - } - }; - - Ok(quote! { - #[automatically_derived] - impl #ruma_common::events::#marker_trait for #ident {} - }) -} - fn generate_event_content_impl( ident: &Ident, event_type: &LitStr, + event_kind: Option, ruma_common: &TokenStream, ) -> TokenStream { let serde = quote! { #ruma_common::exports::serde }; let serde_json = quote! { #ruma_common::exports::serde_json }; + let event_type_ty = match event_kind { + Some(kind) => { + let i = kind.to_event_type_enum(); + quote! { #ruma_common::events::#i } + } + None => quote! { () }, + }; + quote! { #[automatically_derived] impl #ruma_common::events::EventContent for #ident { + type EventType = #event_type_ty; + fn event_type(&self) -> &str { #event_type } diff --git a/crates/ruma-macros/src/events/event_enum.rs b/crates/ruma-macros/src/events/event_enum.rs index c662e87a..fee261d3 100644 --- a/crates/ruma-macros/src/events/event_enum.rs +++ b/crates/ruma-macros/src/events/event_enum.rs @@ -71,6 +71,8 @@ fn expand_event_enum( let content: Vec<_> = events.iter().map(|event| to_event_path(event, kind, var, ruma_common)).collect(); + let custom_ty = format_ident!("Custom{}Content", kind); + let deserialize_impl = expand_deserialize_impl(kind, var, events, variants, ruma_common); let field_accessor_impl = expand_accessor_methods(kind, var, variants, ruma_common); let from_impl = expand_from_impl(&ident, &content, variants); @@ -88,9 +90,7 @@ fn expand_event_enum( /// An event not defined by the Matrix specification #[doc(hidden)] _Custom( - #ruma_common::events::#event_struct< - #ruma_common::events::_custom::CustomEventContent, - >, + #ruma_common::events::#event_struct<#ruma_common::events::_custom::#custom_ty>, ), } @@ -250,6 +250,7 @@ fn expand_content_enum( let ident = kind.to_content_enum(); + let event_type_enum = kind.to_event_type_enum(); let event_type_str = events; let content: Vec<_> = @@ -264,7 +265,6 @@ fn expand_content_enum( let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::>(); let variant_ctors = variants.iter().map(|v| v.ctor(quote! { Self })); - let marker_trait_impl = expand_marker_trait_impl(kind, ruma_common); let from_impl = expand_from_impl(&ident, &content, variants); let serialize_custom_event_error_path = @@ -290,6 +290,8 @@ fn expand_content_enum( #[automatically_derived] impl #ruma_common::events::EventContent for #ident { + type EventType = #ruma_common::events::#event_type_enum; + fn event_type(&self) -> &::std::primitive::str { match self { #( #variant_arms(content) => content.event_type(), )* @@ -317,7 +319,6 @@ fn expand_content_enum( } } - #marker_trait_impl #from_impl } } @@ -403,24 +404,6 @@ fn expand_possibly_redacted_enum( } } -fn expand_marker_trait_impl(kind: EventKind, ruma_common: &TokenStream) -> TokenStream { - let marker_trait = match kind { - EventKind::State => quote! { StateEventContent }, - EventKind::MessageLike => quote! { MessageLikeEventContent }, - EventKind::Ephemeral => quote! { EphemeralRoomEventContent }, - EventKind::GlobalAccountData => quote! { GlobalAccountDataEventContent }, - EventKind::RoomAccountData => quote! { RoomAccountDataEventContent }, - EventKind::ToDevice => quote! { ToDeviceEventContent }, - _ => return TokenStream::new(), - }; - - let ident = kind.to_content_enum(); - quote! { - #[automatically_derived] - impl #ruma_common::events::#marker_trait for #ident {} - } -} - fn expand_accessor_methods( kind: EventKind, var: EventKindVariation, diff --git a/crates/ruma-macros/src/events/event_parse.rs b/crates/ruma-macros/src/events/event_parse.rs index 6d450158..11b0800b 100644 --- a/crates/ruma-macros/src/events/event_parse.rs +++ b/crates/ruma-macros/src/events/event_parse.rs @@ -152,6 +152,10 @@ impl EventKind { format_ident!("Any{}", self.to_event_ident(var)) } + pub fn to_event_type_enum(self) -> Ident { + format_ident!("{}Type", self) + } + /// `Any[kind]EventContent` pub fn to_content_enum(self) -> Ident { format_ident!("Any{}Content", self)