events: Rework the content traits

This commit is contained in:
Jonas Platte 2023-01-16 18:59:25 +01:00 committed by Jonas Platte
parent 49a0650f62
commit 2eba14f0cc
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
11 changed files with 121 additions and 99 deletions

View File

@ -4,10 +4,10 @@ use serde_json::value::RawValue as RawJsonValue;
use super::{ use super::{
EphemeralRoomEventContent, EphemeralRoomEventType, EventContent, EventContentFromType, EphemeralRoomEventContent, EphemeralRoomEventType, EventContent, EventContentFromType,
GlobalAccountDataEventContent, GlobalAccountDataEventType, MessageLikeEventContent, GlobalAccountDataEventContent, GlobalAccountDataEventType, MessageLikeEventContent,
MessageLikeEventType, MessageLikeUnsigned, OriginalStateEventContent, RedactContent, MessageLikeEventType, MessageLikeUnsigned, PossiblyRedactedStateEventContent, RedactContent,
RedactedMessageLikeEventContent, RedactedStateEventContent, RoomAccountDataEventContent, RedactedMessageLikeEventContent, RedactedStateEventContent, RoomAccountDataEventContent,
RoomAccountDataEventType, StateEventContent, StateEventType, ToDeviceEventContent, RoomAccountDataEventType, StateEventContent, StateEventType, StaticStateEventContent,
ToDeviceEventType, ToDeviceEventContent, ToDeviceEventType,
}; };
use crate::RoomVersionId; use crate::RoomVersionId;
@ -70,14 +70,19 @@ custom_room_event_content!(CustomStateEventContent, StateEventType);
impl StateEventContent for CustomStateEventContent { impl StateEventContent for CustomStateEventContent {
type StateKey = String; type StateKey = String;
} }
impl OriginalStateEventContent for CustomStateEventContent { impl StaticStateEventContent for CustomStateEventContent {
// Like `StateUnsigned`, but without `prev_content`. // Like `StateUnsigned`, but without `prev_content`.
// We don't care about `prev_content` since we'd only store the event type that is the same // We don't care about `prev_content` since we'd only store the event type that is the same
// as in the content. // as in the content.
type Unsigned = MessageLikeUnsigned; type Unsigned = MessageLikeUnsigned;
type PossiblyRedacted = Self; type PossiblyRedacted = Self;
} }
impl RedactedStateEventContent for CustomStateEventContent {} impl PossiblyRedactedStateEventContent for CustomStateEventContent {
type StateKey = String;
}
impl RedactedStateEventContent for CustomStateEventContent {
type StateKey = String;
}
custom_event_content!(CustomToDeviceEventContent, ToDeviceEventType); custom_event_content!(CustomToDeviceEventContent, ToDeviceEventType);
impl ToDeviceEventContent for CustomToDeviceEventContent {} impl ToDeviceEventContent for CustomToDeviceEventContent {}

View File

@ -6,7 +6,7 @@ use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
use crate::serde::{CanBeEmpty, Raw}; use crate::serde::{CanBeEmpty, Raw};
use super::{ use super::{
EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType, RedactContent, EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType,
RoomAccountDataEventType, StateEventType, ToDeviceEventType, RoomAccountDataEventType, StateEventType, ToDeviceEventType,
}; };
@ -52,29 +52,38 @@ pub trait RoomAccountDataEventContent: EventContent<EventType = RoomAccountDataE
/// Content of an ephemeral room event. /// Content of an ephemeral room event.
pub trait EphemeralRoomEventContent: EventContent<EventType = EphemeralRoomEventType> {} pub trait EphemeralRoomEventContent: EventContent<EventType = EphemeralRoomEventType> {}
/// Content of a message-like event. /// Content of a non-redacted message-like event.
pub trait MessageLikeEventContent: EventContent<EventType = MessageLikeEventType> {} pub trait MessageLikeEventContent: EventContent<EventType = MessageLikeEventType> {}
/// Content of a redacted message-like event. /// Content of a redacted message-like event.
pub trait RedactedMessageLikeEventContent: MessageLikeEventContent {} pub trait RedactedMessageLikeEventContent: EventContent<EventType = MessageLikeEventType> {}
/// Content of a state event. /// Content of a non-redacted state event.
pub trait StateEventContent: EventContent<EventType = StateEventType> { pub trait StateEventContent: EventContent<EventType = StateEventType> {
/// The type of the event's `state_key` field. /// The type of the event's `state_key` field.
type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize; type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
} }
/// Content of a non-redacted state event. /// Content of a non-redacted state event with a corresponding possibly-redacted type.
pub trait OriginalStateEventContent: StateEventContent + RedactContent { pub trait StaticStateEventContent: StateEventContent {
/// The possibly redacted form of the event's content.
type PossiblyRedacted: PossiblyRedactedStateEventContent;
/// The type of the event's `unsigned` field. /// The type of the event's `unsigned` field.
type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + DeserializeOwned; type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + DeserializeOwned;
/// The possibly redacted form of the event's content.
type PossiblyRedacted: StateEventContent;
} }
/// Content of a redacted state event. /// Content of a redacted state event.
pub trait RedactedStateEventContent: StateEventContent {} pub trait RedactedStateEventContent: EventContent<EventType = StateEventType> {
/// The type of the event's `state_key` field.
type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
}
/// Content of a state event.
pub trait PossiblyRedactedStateEventContent: EventContent<EventType = StateEventType> {
/// The type of the event's `state_key` field.
type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize;
}
/// Content of a to-device event. /// Content of a to-device event.
pub trait ToDeviceEventContent: EventContent<EventType = ToDeviceEventType> {} pub trait ToDeviceEventContent: EventContent<EventType = ToDeviceEventType> {}

View File

@ -6,9 +6,9 @@ use serde_json::value::RawValue as RawJsonValue;
use super::{ use super::{
EphemeralRoomEventContent, EventContent, EventContentFromType, GlobalAccountDataEventContent, EphemeralRoomEventContent, EventContent, EventContentFromType, GlobalAccountDataEventContent,
MessageLikeEventContent, MessageLikeEventType, MessageLikeUnsigned, OriginalStateEventContent, MessageLikeEventContent, MessageLikeEventType, MessageLikeUnsigned, RedactContent,
RedactContent, RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned, RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned,
RedactionDeHelper, RoomAccountDataEventContent, StateEventContent, StateEventType, RedactionDeHelper, RoomAccountDataEventContent, StateEventType, StaticStateEventContent,
ToDeviceEventContent, ToDeviceEventContent,
}; };
use crate::{ use crate::{
@ -229,7 +229,7 @@ where
/// `OriginalStateEvent` implements the comparison traits using only the `event_id` field, a sorted /// `OriginalStateEvent` implements the comparison traits using only the `event_id` field, a sorted
/// list would be sorted lexicographically based on the event's `EventId`. /// list would be sorted lexicographically based on the event's `EventId`.
#[derive(Clone, Debug, Event)] #[derive(Clone, Debug, Event)]
pub struct OriginalStateEvent<C: OriginalStateEventContent> { pub struct OriginalStateEvent<C: StaticStateEventContent> {
/// Data specific to the event type. /// Data specific to the event type.
pub content: C, pub content: C,
@ -260,7 +260,7 @@ pub struct OriginalStateEvent<C: OriginalStateEventContent> {
/// `OriginalSyncStateEvent` implements the comparison traits using only the `event_id` field, a /// `OriginalSyncStateEvent` implements the comparison traits using only the `event_id` field, a
/// sorted list would be sorted lexicographically based on the event's `EventId`. /// sorted list would be sorted lexicographically based on the event's `EventId`.
#[derive(Clone, Debug, Event)] #[derive(Clone, Debug, Event)]
pub struct OriginalSyncStateEvent<C: OriginalStateEventContent> { pub struct OriginalSyncStateEvent<C: StaticStateEventContent> {
/// Data specific to the event type. /// Data specific to the event type.
pub content: C, pub content: C,
@ -285,7 +285,7 @@ pub struct OriginalSyncStateEvent<C: OriginalStateEventContent> {
/// A stripped-down state event, used for previews of rooms the user has been invited to. /// A stripped-down state event, used for previews of rooms the user has been invited to.
#[derive(Clone, Debug, Event)] #[derive(Clone, Debug, Event)]
pub struct StrippedStateEvent<C: StateEventContent> { pub struct StrippedStateEvent<C: StaticStateEventContent> {
/// Data specific to the event type. /// Data specific to the event type.
pub content: C, pub content: C,
@ -301,7 +301,7 @@ pub struct StrippedStateEvent<C: StateEventContent> {
/// A minimal state event, used for creating a new room. /// A minimal state event, used for creating a new room.
#[derive(Clone, Debug, Event)] #[derive(Clone, Debug, Event)]
pub struct InitialStateEvent<C: StateEventContent> { pub struct InitialStateEvent<C: StaticStateEventContent> {
/// Data specific to the event type. /// Data specific to the event type.
pub content: C, pub content: C,
@ -379,7 +379,7 @@ pub struct RedactedSyncStateEvent<C: RedactedStateEventContent> {
/// would be sorted lexicographically based on the event's `EventId`. /// would be sorted lexicographically based on the event's `EventId`.
#[allow(clippy::exhaustive_enums)] #[allow(clippy::exhaustive_enums)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum StateEvent<C: OriginalStateEventContent> pub enum StateEvent<C: StaticStateEventContent + RedactContent>
where where
C::Redacted: RedactedStateEventContent, C::Redacted: RedactedStateEventContent,
{ {
@ -396,7 +396,7 @@ where
/// would be sorted lexicographically based on the event's `EventId`. /// would be sorted lexicographically based on the event's `EventId`.
#[allow(clippy::exhaustive_enums)] #[allow(clippy::exhaustive_enums)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum SyncStateEvent<C: OriginalStateEventContent> pub enum SyncStateEvent<C: StaticStateEventContent + RedactContent>
where where
C::Redacted: RedactedStateEventContent, C::Redacted: RedactedStateEventContent,
{ {
@ -471,10 +471,7 @@ pub struct DecryptedMegolmV1Event<C: MessageLikeEventContent> {
/// A non-redacted content also contains the `prev_content` from the unsigned event data. /// A non-redacted content also contains the `prev_content` from the unsigned event data.
#[allow(clippy::exhaustive_enums)] #[allow(clippy::exhaustive_enums)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum FullStateEventContent<C: OriginalStateEventContent> pub enum FullStateEventContent<C: StaticStateEventContent + RedactContent> {
where
C::Redacted: RedactedStateEventContent,
{
/// Original, unredacted content of the event. /// Original, unredacted content of the event.
Original { Original {
/// Current content of the room state. /// Current content of the room state.
@ -488,7 +485,7 @@ where
Redacted(C::Redacted), Redacted(C::Redacted),
} }
impl<C: OriginalStateEventContent> FullStateEventContent<C> impl<C: StaticStateEventContent + RedactContent> FullStateEventContent<C>
where where
C::Redacted: RedactedStateEventContent, C::Redacted: RedactedStateEventContent,
{ {
@ -617,9 +614,9 @@ impl_possibly_redacted_event!(
); );
impl_possibly_redacted_event!( impl_possibly_redacted_event!(
StateEvent(OriginalStateEventContent, RedactedStateEventContent, StateEventType) StateEvent(StaticStateEventContent, RedactedStateEventContent, StateEventType)
where where
C::Redacted: StateEventContent<StateKey = C::StateKey>, C::Redacted: RedactedStateEventContent<StateKey = C::StateKey>,
{ {
/// Returns this event's `room_id` field. /// Returns this event's `room_id` field.
pub fn room_id(&self) -> &RoomId { pub fn room_id(&self) -> &RoomId {
@ -648,9 +645,9 @@ impl_possibly_redacted_event!(
); );
impl_possibly_redacted_event!( impl_possibly_redacted_event!(
SyncStateEvent(OriginalStateEventContent, RedactedStateEventContent, StateEventType) SyncStateEvent(StaticStateEventContent, RedactedStateEventContent, StateEventType)
where where
C::Redacted: StateEventContent<StateKey = C::StateKey>, C::Redacted: RedactedStateEventContent<StateKey = C::StateKey>,
{ {
/// Returns this event's `state_key` field. /// Returns this event's `state_key` field.
pub fn state_key(&self) -> &C::StateKey { pub fn state_key(&self) -> &C::StateKey {
@ -704,6 +701,6 @@ impl_sync_from_full!(
impl_sync_from_full!( impl_sync_from_full!(
SyncStateEvent, SyncStateEvent,
StateEvent, StateEvent,
OriginalStateEventContent, StaticStateEventContent,
RedactedStateEventContent RedactedStateEventContent
); );

View File

@ -6,7 +6,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent}; use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent};
use crate::events::{EventContent, StateEventContent, StateEventType}; use crate::events::{EventContent, PossiblyRedactedStateEventContent, StateEventType};
/// The content of an `m.policy.rule.room` event. /// The content of an `m.policy.rule.room` event.
/// ///
@ -31,7 +31,7 @@ impl EventContent for PossiblyRedactedPolicyRuleRoomEventContent {
} }
} }
impl StateEventContent for PossiblyRedactedPolicyRuleRoomEventContent { impl PossiblyRedactedStateEventContent for PossiblyRedactedPolicyRuleRoomEventContent {
type StateKey = String; type StateKey = String;
} }

View File

@ -6,7 +6,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent}; use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent};
use crate::events::{EventContent, StateEventContent, StateEventType}; use crate::events::{EventContent, PossiblyRedactedStateEventContent, StateEventType};
/// The content of an `m.policy.rule.server` event. /// The content of an `m.policy.rule.server` event.
/// ///
@ -31,6 +31,6 @@ impl EventContent for PossiblyRedactedPolicyRuleServerEventContent {
} }
} }
impl StateEventContent for PossiblyRedactedPolicyRuleServerEventContent { impl PossiblyRedactedStateEventContent for PossiblyRedactedPolicyRuleServerEventContent {
type StateKey = String; type StateKey = String;
} }

View File

@ -6,7 +6,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent}; use super::{PolicyRuleEventContent, PossiblyRedactedPolicyRuleEventContent};
use crate::events::{EventContent, StateEventContent, StateEventType}; use crate::events::{EventContent, PossiblyRedactedStateEventContent, StateEventType};
/// The content of an `m.policy.rule.user` event. /// The content of an `m.policy.rule.user` event.
/// ///
@ -31,6 +31,6 @@ impl EventContent for PossiblyRedactedPolicyRuleUserEventContent {
} }
} }
impl StateEventContent for PossiblyRedactedPolicyRuleUserEventContent { impl PossiblyRedactedStateEventContent for PossiblyRedactedPolicyRuleUserEventContent {
type StateKey = String; type StateKey = String;
} }

View File

@ -4,9 +4,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
events::{ events::{EventContent, RedactContent, RedactedStateEventContent, StateEventType},
EventContent, RedactContent, RedactedStateEventContent, StateEventContent, StateEventType,
},
OwnedRoomAliasId, OwnedServerName, RoomVersionId, OwnedRoomAliasId, OwnedServerName, RoomVersionId,
}; };
@ -83,8 +81,6 @@ impl EventContent for RedactedRoomAliasesEventContent {
} }
} }
impl StateEventContent for RedactedRoomAliasesEventContent { impl RedactedStateEventContent for RedactedRoomAliasesEventContent {
type StateKey = OwnedServerName; type StateKey = OwnedServerName;
} }
impl RedactedStateEventContent for RedactedRoomAliasesEventContent {}

View File

@ -10,8 +10,8 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
events::{ events::{
AnyStrippedStateEvent, BundledRelations, EventContent, RedactContent, AnyStrippedStateEvent, BundledRelations, EventContent, PossiblyRedactedStateEventContent,
RedactedStateEventContent, StateEventContent, StateEventType, RedactContent, RedactedStateEventContent, StateEventType,
}, },
serde::{CanBeEmpty, Raw, StringEnum}, serde::{CanBeEmpty, Raw, StringEnum},
OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedTransactionId, OwnedUserId, OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedTransactionId, OwnedUserId,
@ -183,6 +183,10 @@ impl RedactContent for RoomMemberEventContent {
/// This type is used when it's not obvious whether the content is redacted or not. /// This type is used when it's not obvious whether the content is redacted or not.
pub type PossiblyRedactedRoomMemberEventContent = RoomMemberEventContent; pub type PossiblyRedactedRoomMemberEventContent = RoomMemberEventContent;
impl PossiblyRedactedStateEventContent for RoomMemberEventContent {
type StateKey = OwnedUserId;
}
/// A member event that has been redacted. /// A member event that has been redacted.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
@ -244,12 +248,10 @@ impl EventContent for RedactedRoomMemberEventContent {
} }
} }
impl StateEventContent for RedactedRoomMemberEventContent { impl RedactedStateEventContent for RedactedRoomMemberEventContent {
type StateKey = OwnedUserId; type StateKey = OwnedUserId;
} }
impl RedactedStateEventContent for RedactedRoomMemberEventContent {}
impl RoomMemberEvent { impl RoomMemberEvent {
/// Obtain the membership state, regardless of whether this event is redacted. /// Obtain the membership state, regardless of whether this event is redacted.
pub fn membership(&self) -> &MembershipState { pub fn membership(&self) -> &MembershipState {

View File

@ -2,7 +2,8 @@ use js_int::Int;
use serde::Deserialize; use serde::Deserialize;
use super::{ use super::{
relation::BundledRelations, room::redaction::RoomRedactionEventContent, StateEventContent, relation::BundledRelations, room::redaction::RoomRedactionEventContent,
PossiblyRedactedStateEventContent,
}; };
use crate::{ use crate::{
serde::CanBeEmpty, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId, serde::CanBeEmpty, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
@ -51,7 +52,7 @@ impl CanBeEmpty for MessageLikeUnsigned {
/// Extra information about a state event that is not incorporated into the event's hash. /// Extra information about a state event that is not incorporated into the event's hash.
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct StateUnsigned<C: StateEventContent> { pub struct StateUnsigned<C: PossiblyRedactedStateEventContent> {
/// The time in milliseconds that has elapsed since the event was sent. /// The time in milliseconds that has elapsed since the event was sent.
/// ///
/// This field is generated by the local homeserver, and may be incorrect if the local time on /// This field is generated by the local homeserver, and may be incorrect if the local time on
@ -73,14 +74,14 @@ pub struct StateUnsigned<C: StateEventContent> {
pub relations: BundledRelations, pub relations: BundledRelations,
} }
impl<C: StateEventContent> StateUnsigned<C> { impl<C: PossiblyRedactedStateEventContent> StateUnsigned<C> {
/// Create a new `Unsigned` with fields set to `None`. /// Create a new `Unsigned` with fields set to `None`.
pub fn new() -> Self { pub fn new() -> Self {
Self { age: None, transaction_id: None, prev_content: None, relations: Default::default() } Self { age: None, transaction_id: None, prev_content: None, relations: Default::default() }
} }
} }
impl<C: StateEventContent> CanBeEmpty for StateUnsigned<C> { impl<C: PossiblyRedactedStateEventContent> CanBeEmpty for StateUnsigned<C> {
/// Whether this unsigned data is empty (all fields are `None`). /// Whether this unsigned data is empty (all fields are `None`).
/// ///
/// This method is used to determine whether to skip serializing the `unsigned` field in room /// This method is used to determine whether to skip serializing the `unsigned` field in room
@ -94,7 +95,7 @@ impl<C: StateEventContent> CanBeEmpty for StateUnsigned<C> {
} }
} }
impl<C: StateEventContent> Default for StateUnsigned<C> { impl<C: PossiblyRedactedStateEventContent> Default for StateUnsigned<C> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }

View File

@ -1,20 +1,19 @@
use ruma_common::{ use ruma_common::{
events::{StateEventContent, StateUnsigned}, events::StaticStateEventContent, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId,
MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, OwnedUserId,
}; };
use ruma_macros::Event; use ruma_macros::Event;
use serde::de::DeserializeOwned;
/// State event. /// State event.
#[derive(Clone, Debug, Event)] #[derive(Clone, Debug, Event)]
pub struct OriginalStateEvent<C: StateEventContent + DeserializeOwned> { pub struct OriginalStateEvent<C: StaticStateEventContent> {
pub content: C, pub content: C,
pub event_id: OwnedEventId, pub event_id: OwnedEventId,
pub sender: OwnedUserId, pub sender: OwnedUserId,
pub origin_server_ts: MilliSecondsSinceUnixEpoch, pub origin_server_ts: MilliSecondsSinceUnixEpoch,
pub room_id: OwnedRoomId, pub room_id: OwnedRoomId,
pub state_key: C::StateKey, pub state_key: C::StateKey,
pub unsigned: StateUnsigned<C>, pub unsigned: C::Unsigned,
} }
fn main() {} fn main() {}

View File

@ -1,7 +1,7 @@
//! Implementations of the EventContent derive macro. //! Implementations of the EventContent derive macro.
#![allow(clippy::too_many_arguments)] // FIXME #![allow(clippy::too_many_arguments)] // FIXME
use std::borrow::Cow; use std::{borrow::Cow, fmt};
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens}; use quote::{format_ident, quote, ToTokens};
@ -326,12 +326,11 @@ pub fn expand_event_content(
// We only generate possibly redacted content structs for state events. // We only generate possibly redacted content structs for state events.
let possibly_redacted_event_content = event_kind let possibly_redacted_event_content = event_kind
.filter(|kind| needs_possibly_redacted(is_custom_possibly_redacted, *kind)) .filter(|kind| needs_possibly_redacted(is_custom_possibly_redacted, *kind))
.map(|kind| { .map(|_| {
generate_possibly_redacted_event_content( generate_possibly_redacted_event_content(
ident, ident,
fields.clone(), fields.clone(),
&event_type, &event_type,
kind,
state_key_type.as_ref(), state_key_type.as_ref(),
unsigned_type.clone(), unsigned_type.clone(),
&aliases, &aliases,
@ -350,11 +349,11 @@ pub fn expand_event_content(
fields, fields,
&event_type, &event_type,
event_kind, event_kind,
EventKindContentVariation::Original,
state_key_type.as_ref(), state_key_type.as_ref(),
unsigned_type, unsigned_type,
&aliases, &aliases,
ruma_common, ruma_common,
true,
) )
.unwrap_or_else(syn::Error::into_compile_error); .unwrap_or_else(syn::Error::into_compile_error);
let static_event_content_impl = let static_event_content_impl =
@ -443,16 +442,14 @@ fn generate_redacted_event_content<'a>(
kept_redacted_fields.iter(), kept_redacted_fields.iter(),
event_type, event_type,
Some(event_kind), Some(event_kind),
EventKindContentVariation::Redacted,
state_key_type, state_key_type,
unsigned_type, unsigned_type,
aliases, aliases,
ruma_common, ruma_common,
false,
) )
.unwrap_or_else(syn::Error::into_compile_error); .unwrap_or_else(syn::Error::into_compile_error);
let sub_trait_name = format_ident!("Redacted{event_kind}Content");
let static_event_content_impl = let static_event_content_impl =
generate_static_event_content_impl(&redacted_ident, event_type, ruma_common); generate_static_event_content_impl(&redacted_ident, event_type, ruma_common);
@ -480,9 +477,6 @@ fn generate_redacted_event_content<'a>(
#redacted_event_content #redacted_event_content
#[automatically_derived]
impl #ruma_common::events::#sub_trait_name for #redacted_ident {}
#static_event_content_impl #static_event_content_impl
}) })
} }
@ -491,7 +485,6 @@ fn generate_possibly_redacted_event_content<'a>(
ident: &Ident, ident: &Ident,
fields: impl Iterator<Item = &'a Field>, fields: impl Iterator<Item = &'a Field>,
event_type: &LitStr, event_type: &LitStr,
event_kind: EventKind,
state_key_type: Option<&TokenStream>, state_key_type: Option<&TokenStream>,
unsigned_type: Option<TokenStream>, unsigned_type: Option<TokenStream>,
aliases: &[LitStr], aliases: &[LitStr],
@ -599,12 +592,12 @@ fn generate_possibly_redacted_event_content<'a>(
&possibly_redacted_ident, &possibly_redacted_ident,
possibly_redacted_fields.iter(), possibly_redacted_fields.iter(),
event_type, event_type,
Some(event_kind), Some(EventKind::State),
EventKindContentVariation::PossiblyRedacted,
state_key_type, state_key_type,
unsigned_type, unsigned_type,
aliases, aliases,
ruma_common, ruma_common,
false,
) )
.unwrap_or_else(syn::Error::into_compile_error); .unwrap_or_else(syn::Error::into_compile_error);
@ -627,6 +620,11 @@ fn generate_possibly_redacted_event_content<'a>(
Ok(quote! { Ok(quote! {
#[doc = #doc] #[doc = #doc]
pub type #possibly_redacted_ident = #ident; pub type #possibly_redacted_ident = #ident;
#[automatically_derived]
impl #ruma_common::events::PossiblyRedactedStateEventContent for #ident {
type StateKey = #state_key_type;
}
}) })
} }
} }
@ -756,16 +754,33 @@ fn generate_event_type_aliases(
Ok(type_aliases) Ok(type_aliases)
} }
#[derive(PartialEq)]
enum EventKindContentVariation {
Original,
Redacted,
PossiblyRedacted,
}
impl fmt::Display for EventKindContentVariation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EventKindContentVariation::Original => Ok(()),
EventKindContentVariation::Redacted => write!(f, "Redacted"),
EventKindContentVariation::PossiblyRedacted => write!(f, "PossiblyRedacted"),
}
}
}
fn generate_event_content_impl<'a>( fn generate_event_content_impl<'a>(
ident: &Ident, ident: &Ident,
mut fields: impl Iterator<Item = &'a Field>, mut fields: impl Iterator<Item = &'a Field>,
event_type: &LitStr, event_type: &LitStr,
event_kind: Option<EventKind>, event_kind: Option<EventKind>,
variation: EventKindContentVariation,
state_key_type: Option<&TokenStream>, state_key_type: Option<&TokenStream>,
unsigned_type: Option<TokenStream>, unsigned_type: Option<TokenStream>,
aliases: &[LitStr], aliases: &[LitStr],
ruma_common: &TokenStream, ruma_common: &TokenStream,
is_original: bool,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
let serde = quote! { #ruma_common::exports::serde }; let serde = quote! { #ruma_common::exports::serde };
let serde_json = quote! { #ruma_common::exports::serde_json }; let serde_json = quote! { #ruma_common::exports::serde_json };
@ -845,9 +860,9 @@ fn generate_event_content_impl<'a>(
} }
let sub_trait_impl = event_kind.map(|kind| { let sub_trait_impl = event_kind.map(|kind| {
let trait_name = format_ident!("{kind}Content"); let trait_name = format_ident!("{variation}{kind}Content");
let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| { let state_key = (kind == EventKind::State).then(|| {
assert!(state_key_type.is_some()); assert!(state_key_type.is_some());
quote! { quote! {
@ -855,34 +870,32 @@ fn generate_event_content_impl<'a>(
} }
}); });
let original_state_event_content_impl =
(event_kind == Some(EventKind::State) && is_original).then(|| {
let trait_name = format_ident!("Original{kind}Content");
let possibly_redacted_ident = format_ident!("PossiblyRedacted{ident}");
let unsigned_type = unsigned_type.unwrap_or_else(
|| quote! { #ruma_common::events::StateUnsigned<Self::PossiblyRedacted> },
);
quote! {
#[automatically_derived]
impl #ruma_common::events::#trait_name for #ident {
type Unsigned = #unsigned_type;
type PossiblyRedacted = #possibly_redacted_ident;
}
}
});
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #ruma_common::events::#trait_name for #ident { impl #ruma_common::events::#trait_name for #ident {
#state_event_content_impl #state_key
} }
#original_state_event_content_impl
} }
}); });
let static_state_event_content_impl = (event_kind == Some(EventKind::State)
&& variation == EventKindContentVariation::Original)
.then(|| {
let possibly_redacted_ident = format_ident!("PossiblyRedacted{ident}");
let unsigned_type = unsigned_type.unwrap_or_else(
|| quote! { #ruma_common::events::StateUnsigned<Self::PossiblyRedacted> },
);
quote! {
#[automatically_derived]
impl #ruma_common::events::StaticStateEventContent for #ident {
type PossiblyRedacted = #possibly_redacted_ident;
type Unsigned = #unsigned_type;
}
}
});
let event_types = aliases.iter().chain([event_type]); let event_types = aliases.iter().chain([event_type]);
let event_content_from_type_impl = type_suffix_data.map(|(_, type_fragment_field)| { let event_content_from_type_impl = type_suffix_data.map(|(_, type_fragment_field)| {
@ -944,8 +957,8 @@ fn generate_event_content_impl<'a>(
} }
#event_content_from_type_impl #event_content_from_type_impl
#sub_trait_impl #sub_trait_impl
#static_state_event_content_impl
}) })
} }