events: Replace generic "alias" trait implementations by individual ones

… so that rustdoc lists types implementing them properly.
This commit is contained in:
Jonas Platte 2022-09-05 11:16:30 +02:00
parent 2579544883
commit 7957dd6adf
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
7 changed files with 129 additions and 101 deletions

View File

@ -2,9 +2,11 @@ use serde::Serialize;
use serde_json::value::RawValue as RawJsonValue; use serde_json::value::RawValue as RawJsonValue;
use super::{ use super::{
EphemeralRoomEventType, EventContent, GlobalAccountDataEventType, HasDeserializeFields, EphemeralRoomEventContent, EphemeralRoomEventType, EventContent, GlobalAccountDataEventContent,
MessageLikeEventType, RedactContent, RedactedEventContent, RoomAccountDataEventType, GlobalAccountDataEventType, HasDeserializeFields, MessageLikeEventContent,
StateEventContent, StateEventType, ToDeviceEventType, MessageLikeEventType, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent,
RedactedStateEventContent, RoomAccountDataEventContent, RoomAccountDataEventType,
StateEventContent, StateEventType, ToDeviceEventContent, ToDeviceEventType,
}; };
use crate::RoomVersionId; use crate::RoomVersionId;
@ -63,12 +65,23 @@ macro_rules! custom_room_event_content {
} }
custom_event_content!(CustomGlobalAccountDataEventContent, GlobalAccountDataEventType); custom_event_content!(CustomGlobalAccountDataEventContent, GlobalAccountDataEventType);
custom_event_content!(CustomRoomAccountDataEventContent, RoomAccountDataEventType); impl GlobalAccountDataEventContent for CustomGlobalAccountDataEventContent {}
custom_event_content!(CustomEphemeralRoomEventContent, EphemeralRoomEventType);
custom_room_event_content!(CustomMessageLikeEventContent, MessageLikeEventType);
custom_room_event_content!(CustomStateEventContent, StateEventType);
custom_event_content!(CustomToDeviceEventContent, ToDeviceEventType);
custom_event_content!(CustomRoomAccountDataEventContent, RoomAccountDataEventType);
impl RoomAccountDataEventContent for CustomRoomAccountDataEventContent {}
custom_event_content!(CustomEphemeralRoomEventContent, EphemeralRoomEventType);
impl EphemeralRoomEventContent for CustomEphemeralRoomEventContent {}
custom_room_event_content!(CustomMessageLikeEventContent, MessageLikeEventType);
impl MessageLikeEventContent for CustomMessageLikeEventContent {}
impl RedactedMessageLikeEventContent for CustomMessageLikeEventContent {}
custom_room_event_content!(CustomStateEventContent, StateEventType);
impl StateEventContent for CustomStateEventContent { impl StateEventContent for CustomStateEventContent {
type StateKey = String; type StateKey = String;
} }
impl RedactedStateEventContent for CustomStateEventContent {}
custom_event_content!(CustomToDeviceEventContent, ToDeviceEventType);
impl ToDeviceEventContent for CustomToDeviceEventContent {}

View File

@ -136,39 +136,32 @@ pub enum EventKind {
Presence, Presence,
} }
/// An alias for `EventContent<EventType = GlobalAccountDataEventType>`. /// Content of a global account-data event.
pub trait GlobalAccountDataEventContent: pub trait GlobalAccountDataEventContent:
EventContent<EventType = GlobalAccountDataEventType> EventContent<EventType = GlobalAccountDataEventType>
{ {
} }
impl<T: EventContent<EventType = GlobalAccountDataEventType>> GlobalAccountDataEventContent for T {}
/// An alias for `EventContent<EventType = RoomAccountDataEventType>`. /// Content of a room-specific account-data event.
pub trait RoomAccountDataEventContent: EventContent<EventType = RoomAccountDataEventType> {} pub trait RoomAccountDataEventContent: EventContent<EventType = RoomAccountDataEventType> {}
impl<T: EventContent<EventType = RoomAccountDataEventType>> RoomAccountDataEventContent for T {}
/// An alias for `EventContent<EventType = EphemeralRoomEventType>`. /// Content of an ephemeral room event.
pub trait EphemeralRoomEventContent: EventContent<EventType = EphemeralRoomEventType> {} pub trait EphemeralRoomEventContent: EventContent<EventType = EphemeralRoomEventType> {}
impl<T: EventContent<EventType = EphemeralRoomEventType>> EphemeralRoomEventContent for T {}
/// An alias for `EventContent<EventType = MessageLikeEventType>`. /// Content of a non-redacted message-like event.
pub trait MessageLikeEventContent: EventContent<EventType = MessageLikeEventType> {} pub trait MessageLikeEventContent: EventContent<EventType = MessageLikeEventType> {}
impl<T: EventContent<EventType = MessageLikeEventType>> MessageLikeEventContent for T {}
/// An alias for `MessageLikeEventContent + RedactedEventContent`. /// Content of a redacted message-like event.
pub trait RedactedMessageLikeEventContent: MessageLikeEventContent + RedactedEventContent {} pub trait RedactedMessageLikeEventContent: MessageLikeEventContent + RedactedEventContent {}
impl<T: MessageLikeEventContent + RedactedEventContent> RedactedMessageLikeEventContent for T {}
/// An alias for `StateEventContent + RedactedEventContent`. /// Content of a redacted state event.
pub trait RedactedStateEventContent: StateEventContent + RedactedEventContent {}
impl<T: StateEventContent + RedactedEventContent> RedactedStateEventContent for T {}
/// An alias for `EventContent<EventType = ToDeviceEventType>`.
pub trait ToDeviceEventContent: EventContent<EventType = ToDeviceEventType> {}
impl<T: EventContent<EventType = ToDeviceEventType>> ToDeviceEventContent for T {}
/// An alias for `EventContent<EventType = StateEventType>`.
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.
pub trait RedactedStateEventContent: StateEventContent + RedactedEventContent {}
/// Content of a to-device event.
pub trait ToDeviceEventContent: EventContent<EventType = ToDeviceEventType> {}

View File

@ -7,10 +7,9 @@ use serde_json::value::RawValue as RawJsonValue;
use super::{ use super::{
room::redaction::SyncRoomRedactionEvent, EphemeralRoomEventContent, EventContent, room::redaction::SyncRoomRedactionEvent, EphemeralRoomEventContent, EventContent,
GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType, GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType,
MessageLikeUnsigned, Redact, RedactContent, RedactedEventContent, MessageLikeUnsigned, Redact, RedactContent, RedactedMessageLikeEventContent,
RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned, RedactedStateEventContent, RedactedUnsigned, RedactionDeHelper, RoomAccountDataEventContent,
RedactionDeHelper, RoomAccountDataEventContent, StateEventContent, StateEventType, StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent,
StateUnsigned, ToDeviceEventContent,
}; };
use crate::{ use crate::{
serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId,
@ -151,7 +150,7 @@ pub struct RedactedSyncMessageLikeEvent<C: RedactedMessageLikeEventContent> {
#[serde(untagged)] #[serde(untagged)]
pub enum MessageLikeEvent<C: MessageLikeEventContent + RedactContent> pub enum MessageLikeEvent<C: MessageLikeEventContent + RedactContent>
where where
C::Redacted: MessageLikeEventContent + RedactedEventContent, C::Redacted: RedactedMessageLikeEventContent,
{ {
/// Original, unredacted form of the event. /// Original, unredacted form of the event.
Original(OriginalMessageLikeEvent<C>), Original(OriginalMessageLikeEvent<C>),
@ -169,7 +168,7 @@ where
#[serde(untagged)] #[serde(untagged)]
pub enum SyncMessageLikeEvent<C: MessageLikeEventContent + RedactContent> pub enum SyncMessageLikeEvent<C: MessageLikeEventContent + RedactContent>
where where
C::Redacted: MessageLikeEventContent + RedactedEventContent, C::Redacted: RedactedMessageLikeEventContent,
{ {
/// Original, unredacted form of the event. /// Original, unredacted form of the event.
Original(OriginalSyncMessageLikeEvent<C>), Original(OriginalSyncMessageLikeEvent<C>),
@ -336,7 +335,7 @@ pub struct RedactedSyncStateEvent<C: RedactedStateEventContent> {
#[serde(untagged)] #[serde(untagged)]
pub enum StateEvent<C: StateEventContent + RedactContent> pub enum StateEvent<C: StateEventContent + RedactContent>
where where
C::Redacted: StateEventContent + RedactedEventContent, C::Redacted: RedactedStateEventContent,
{ {
/// Original, unredacted form of the event. /// Original, unredacted form of the event.
Original(OriginalStateEvent<C>), Original(OriginalStateEvent<C>),
@ -354,7 +353,7 @@ where
#[serde(untagged)] #[serde(untagged)]
pub enum SyncStateEvent<C: StateEventContent + RedactContent> pub enum SyncStateEvent<C: StateEventContent + RedactContent>
where where
C::Redacted: StateEventContent + RedactedEventContent, C::Redacted: RedactedStateEventContent,
{ {
/// Original, unredacted form of the event. /// Original, unredacted form of the event.
Original(OriginalSyncStateEvent<C>), Original(OriginalSyncStateEvent<C>),
@ -411,14 +410,14 @@ pub struct DecryptedMegolmV1Event<C: MessageLikeEventContent> {
macro_rules! impl_possibly_redacted_event { macro_rules! impl_possibly_redacted_event {
( (
$ty:ident ( $content_trait:ident, $event_type:ident ) $ty:ident ( $content_trait:ident, $redacted_content_trait:ident, $event_type:ident )
$( where C::Redacted: $trait:ident<StateKey = C::StateKey>, )? $( where C::Redacted: $trait:ident<StateKey = C::StateKey>, )?
{ $($extra:tt)* } { $($extra:tt)* }
) => { ) => {
impl<C> $ty<C> impl<C> $ty<C>
where where
C: $content_trait + RedactContent, C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent, C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )? $( C::Redacted: $trait<StateKey = C::StateKey>, )?
{ {
/// Returns the `type` of this event. /// Returns the `type` of this event.
@ -460,7 +459,7 @@ macro_rules! impl_possibly_redacted_event {
impl<C> Redact for $ty<C> impl<C> Redact for $ty<C>
where where
C: $content_trait + RedactContent, C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent, C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )? $( C::Redacted: $trait<StateKey = C::StateKey>, )?
{ {
type Redacted = Self; type Redacted = Self;
@ -476,7 +475,7 @@ macro_rules! impl_possibly_redacted_event {
impl<'de, C> Deserialize<'de> for $ty<C> impl<'de, C> Deserialize<'de> for $ty<C>
where where
C: $content_trait + RedactContent, C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent, C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )? $( C::Redacted: $trait<StateKey = C::StateKey>, )?
{ {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -496,44 +495,52 @@ macro_rules! impl_possibly_redacted_event {
} }
} }
impl_possibly_redacted_event!(MessageLikeEvent(MessageLikeEventContent, MessageLikeEventType) { impl_possibly_redacted_event!(
/// Returns this event's `room_id` field. MessageLikeEvent(
pub fn room_id(&self) -> &RoomId { MessageLikeEventContent, RedactedMessageLikeEventContent, MessageLikeEventType
match self { ) {
Self::Original(ev) => &ev.room_id, /// Returns this event's `room_id` field.
Self::Redacted(ev) => &ev.room_id, pub fn room_id(&self) -> &RoomId {
match self {
Self::Original(ev) => &ev.room_id,
Self::Redacted(ev) => &ev.room_id,
}
} }
}
/// Get the inner `OriginalMessageLikeEvent` if this is an unredacted event. /// Get the inner `OriginalMessageLikeEvent` if this is an unredacted event.
pub fn as_original(&self) -> Option<&OriginalMessageLikeEvent<C>> { pub fn as_original(&self) -> Option<&OriginalMessageLikeEvent<C>> {
match self { match self {
Self::Original(v) => Some(v), Self::Original(v) => Some(v),
_ => None, _ => None,
}
} }
} }
}); );
impl_possibly_redacted_event!(SyncMessageLikeEvent(MessageLikeEventContent, MessageLikeEventType) {
/// Get the inner `OriginalSyncMessageLikeEvent` if this is an unredacted event.
pub fn as_original(&self) -> Option<&OriginalSyncMessageLikeEvent<C>> {
match self {
Self::Original(v) => Some(v),
_ => None,
}
}
/// Convert this sync event into a full event (one with a `room_id` field).
pub fn into_full_event(self, room_id: OwnedRoomId) -> MessageLikeEvent<C> {
match self {
Self::Original(ev) => MessageLikeEvent::Original(ev.into_full_event(room_id)),
Self::Redacted(ev) => MessageLikeEvent::Redacted(ev.into_full_event(room_id)),
}
}
});
impl_possibly_redacted_event!( impl_possibly_redacted_event!(
StateEvent(StateEventContent, StateEventType) SyncMessageLikeEvent(
MessageLikeEventContent, RedactedMessageLikeEventContent, MessageLikeEventType
) {
/// Get the inner `OriginalSyncMessageLikeEvent` if this is an unredacted event.
pub fn as_original(&self) -> Option<&OriginalSyncMessageLikeEvent<C>> {
match self {
Self::Original(v) => Some(v),
_ => None,
}
}
/// Convert this sync event into a full event (one with a `room_id` field).
pub fn into_full_event(self, room_id: OwnedRoomId) -> MessageLikeEvent<C> {
match self {
Self::Original(ev) => MessageLikeEvent::Original(ev.into_full_event(room_id)),
Self::Redacted(ev) => MessageLikeEvent::Redacted(ev.into_full_event(room_id)),
}
}
}
);
impl_possibly_redacted_event!(
StateEvent(StateEventContent, RedactedStateEventContent, StateEventType)
where where
C::Redacted: StateEventContent<StateKey = C::StateKey>, C::Redacted: StateEventContent<StateKey = C::StateKey>,
{ {
@ -564,7 +571,7 @@ impl_possibly_redacted_event!(
); );
impl_possibly_redacted_event!( impl_possibly_redacted_event!(
SyncStateEvent(StateEventContent, StateEventType) SyncStateEvent(StateEventContent, RedactedStateEventContent, StateEventType)
where where
C::Redacted: StateEventContent<StateKey = C::StateKey>, C::Redacted: StateEventContent<StateKey = C::StateKey>,
{ {
@ -595,11 +602,11 @@ impl_possibly_redacted_event!(
); );
macro_rules! impl_sync_from_full { macro_rules! impl_sync_from_full {
($ty:ident, $full:ident, $content_trait:ident) => { ($ty:ident, $full:ident, $content_trait:ident, $redacted_content_trait: ident) => {
impl<C> From<$full<C>> for $ty<C> impl<C> From<$full<C>> for $ty<C>
where where
C: $content_trait + RedactContent, C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent, C::Redacted: $redacted_content_trait,
{ {
fn from(full: $full<C>) -> Self { fn from(full: $full<C>) -> Self {
match full { match full {
@ -611,5 +618,10 @@ macro_rules! impl_sync_from_full {
}; };
} }
impl_sync_from_full!(SyncMessageLikeEvent, MessageLikeEvent, MessageLikeEventContent); impl_sync_from_full!(
impl_sync_from_full!(SyncStateEvent, StateEvent, StateEventContent); SyncMessageLikeEvent,
MessageLikeEvent,
MessageLikeEventContent,
RedactedMessageLikeEventContent
);
impl_sync_from_full!(SyncStateEvent, StateEvent, StateEventContent, RedactedStateEventContent);

View File

@ -6,8 +6,8 @@ use serde_json::value::RawValue as RawJsonValue;
use crate::{ use crate::{
events::{ events::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventContent, EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
StateEventType, RedactedStateEventContent, StateEventContent, StateEventType,
}, },
OwnedRoomAliasId, OwnedServerName, RoomVersionId, OwnedRoomAliasId, OwnedServerName, RoomVersionId,
}; };
@ -99,6 +99,8 @@ impl StateEventContent for RedactedRoomAliasesEventContent {
type StateKey = OwnedServerName; type StateKey = OwnedServerName;
} }
impl RedactedStateEventContent for RedactedRoomAliasesEventContent {}
// Since this redacted event has fields we leave the default `empty` method // Since this redacted event has fields we leave the default `empty` method
// that will error if called. // that will error if called.
impl RedactedEventContent for RedactedRoomAliasesEventContent { impl RedactedEventContent for RedactedRoomAliasesEventContent {

View File

@ -10,8 +10,8 @@ use serde_json::value::RawValue as RawJsonValue;
use crate::{ use crate::{
events::{ events::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventContent, EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
StateEventType, RedactedStateEventContent, StateEventContent, StateEventType,
}, },
serde::StringEnum, serde::StringEnum,
OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, PrivOwnedStr, OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, PrivOwnedStr,
@ -204,6 +204,8 @@ impl StateEventContent for RedactedRoomMemberEventContent {
type StateKey = OwnedUserId; type StateKey = OwnedUserId;
} }
impl RedactedStateEventContent for RedactedRoomMemberEventContent {}
// Since this redacted event has fields we leave the default `empty` method // Since this redacted event has fields we leave the default `empty` method
// that will error if called. // that will error if called.
impl RedactedEventContent for RedactedRoomMemberEventContent { impl RedactedEventContent for RedactedRoomMemberEventContent {

View File

@ -1,7 +1,7 @@
//! Implementation of the top level `*Event` derive macro. //! Implementation of the top level `*Event` derive macro.
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::quote; use quote::{format_ident, quote};
use syn::{parse_quote, Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, GenericParam}; use syn::{parse_quote, Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, GenericParam};
use super::{ use super::{
@ -359,7 +359,6 @@ fn expand_redact_event(
ruma_common: &TokenStream, ruma_common: &TokenStream,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
let redacted_type = kind.to_event_ident(var.to_redacted())?; let redacted_type = kind.to_event_ident(var.to_redacted())?;
let redacted_event_type_enum = kind.to_event_type_enum();
let ident = &input.ident; let ident = &input.ident;
let mut generics = input.generics.clone(); let mut generics = input.generics.clone();
@ -376,20 +375,14 @@ fn expand_redact_event(
let where_clause = generics.make_where_clause(); let where_clause = generics.make_where_clause();
where_clause.predicates.push(parse_quote! { #ty_param: #ruma_common::events::RedactContent }); where_clause.predicates.push(parse_quote! { #ty_param: #ruma_common::events::RedactContent });
let redacted_event_content_bound = if kind == EventKind::State { let assoc_type_bounds =
quote! { (kind == EventKind::State).then(|| quote! { StateKey = #ty_param::StateKey });
#ruma_common::events::StateEventContent<StateKey = #ty_param::StateKey> let trait_name = format_ident!("Redacted{kind}Content");
} let redacted_event_content_bound = quote! {
} else { #ruma_common::events::#trait_name<#assoc_type_bounds>
quote! {
#ruma_common::events::EventContent<
EventType = #ruma_common::events::#redacted_event_type_enum
>
}
}; };
where_clause.predicates.push(parse_quote! { where_clause.predicates.push(parse_quote! {
<#ty_param as #ruma_common::events::RedactContent>::Redacted: <#ty_param as #ruma_common::events::RedactContent>::Redacted: #redacted_event_content_bound
#redacted_event_content_bound + #ruma_common::events::RedactedEventContent
}); });
let (impl_generics, ty_gen, where_clause) = generics.split_for_impl(); let (impl_generics, ty_gen, where_clause) = generics.split_for_impl();

View File

@ -407,8 +407,10 @@ fn generate_redacted_event_content<'a>(
) )
.unwrap_or_else(syn::Error::into_compile_error); .unwrap_or_else(syn::Error::into_compile_error);
let static_event_content_impl = event_kind.map(|k| { let sub_trait_name = event_kind.map(|kind| format_ident!("Redacted{kind}Content"));
generate_static_event_content_impl(&redacted_ident, k, true, event_type, ruma_common)
let static_event_content_impl = event_kind.map(|kind| {
generate_static_event_content_impl(&redacted_ident, kind, true, event_type, ruma_common)
}); });
let mut event_types = aliases.to_owned(); let mut event_types = aliases.to_owned();
@ -460,6 +462,9 @@ fn generate_redacted_event_content<'a>(
} }
} }
#[automatically_derived]
impl #ruma_common::events::#sub_trait_name for #redacted_ident {}
#static_event_content_impl #static_event_content_impl
}) })
} }
@ -611,12 +616,20 @@ fn generate_event_content_impl<'a>(
} }
} }
let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| { let sub_trait_impl = event_kind.map(|kind| {
assert!(state_key_type.is_some()); let trait_name = format_ident!("{kind}Content");
let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| {
assert!(state_key_type.is_some());
quote! {
type StateKey = #state_key_type;
}
});
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #ruma_common::events::StateEventContent for #ident { impl #ruma_common::events::#trait_name for #ident {
type StateKey = #state_key_type; #state_event_content_impl
} }
} }
}); });
@ -682,7 +695,7 @@ fn generate_event_content_impl<'a>(
} }
} }
#state_event_content_impl #sub_trait_impl
}) })
} }