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 super::{
EphemeralRoomEventType, EventContent, GlobalAccountDataEventType, HasDeserializeFields,
MessageLikeEventType, RedactContent, RedactedEventContent, RoomAccountDataEventType,
StateEventContent, StateEventType, ToDeviceEventType,
EphemeralRoomEventContent, EphemeralRoomEventType, EventContent, GlobalAccountDataEventContent,
GlobalAccountDataEventType, HasDeserializeFields, MessageLikeEventContent,
MessageLikeEventType, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent,
RedactedStateEventContent, RoomAccountDataEventContent, RoomAccountDataEventType,
StateEventContent, StateEventType, ToDeviceEventContent, ToDeviceEventType,
};
use crate::RoomVersionId;
@ -63,12 +65,23 @@ macro_rules! custom_room_event_content {
}
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);
impl GlobalAccountDataEventContent for CustomGlobalAccountDataEventContent {}
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 {
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,
}
/// An alias for `EventContent<EventType = GlobalAccountDataEventType>`.
/// Content of a global account-data event.
pub trait GlobalAccountDataEventContent:
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> {}
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> {}
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> {}
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 {}
impl<T: MessageLikeEventContent + RedactedEventContent> RedactedMessageLikeEventContent for T {}
/// An alias for `StateEventContent + RedactedEventContent`.
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>`.
/// Content of a redacted state event.
pub trait StateEventContent: EventContent<EventType = StateEventType> {
/// The type of the event's `state_key` field.
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::{
room::redaction::SyncRoomRedactionEvent, EphemeralRoomEventContent, EventContent,
GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType,
MessageLikeUnsigned, Redact, RedactContent, RedactedEventContent,
RedactedMessageLikeEventContent, RedactedStateEventContent, RedactedUnsigned,
RedactionDeHelper, RoomAccountDataEventContent, StateEventContent, StateEventType,
StateUnsigned, ToDeviceEventContent,
MessageLikeUnsigned, Redact, RedactContent, RedactedMessageLikeEventContent,
RedactedStateEventContent, RedactedUnsigned, RedactionDeHelper, RoomAccountDataEventContent,
StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent,
};
use crate::{
serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId,
@ -151,7 +150,7 @@ pub struct RedactedSyncMessageLikeEvent<C: RedactedMessageLikeEventContent> {
#[serde(untagged)]
pub enum MessageLikeEvent<C: MessageLikeEventContent + RedactContent>
where
C::Redacted: MessageLikeEventContent + RedactedEventContent,
C::Redacted: RedactedMessageLikeEventContent,
{
/// Original, unredacted form of the event.
Original(OriginalMessageLikeEvent<C>),
@ -169,7 +168,7 @@ where
#[serde(untagged)]
pub enum SyncMessageLikeEvent<C: MessageLikeEventContent + RedactContent>
where
C::Redacted: MessageLikeEventContent + RedactedEventContent,
C::Redacted: RedactedMessageLikeEventContent,
{
/// Original, unredacted form of the event.
Original(OriginalSyncMessageLikeEvent<C>),
@ -336,7 +335,7 @@ pub struct RedactedSyncStateEvent<C: RedactedStateEventContent> {
#[serde(untagged)]
pub enum StateEvent<C: StateEventContent + RedactContent>
where
C::Redacted: StateEventContent + RedactedEventContent,
C::Redacted: RedactedStateEventContent,
{
/// Original, unredacted form of the event.
Original(OriginalStateEvent<C>),
@ -354,7 +353,7 @@ where
#[serde(untagged)]
pub enum SyncStateEvent<C: StateEventContent + RedactContent>
where
C::Redacted: StateEventContent + RedactedEventContent,
C::Redacted: RedactedStateEventContent,
{
/// Original, unredacted form of the event.
Original(OriginalSyncStateEvent<C>),
@ -411,14 +410,14 @@ pub struct DecryptedMegolmV1Event<C: MessageLikeEventContent> {
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>, )?
{ $($extra:tt)* }
) => {
impl<C> $ty<C>
where
C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent,
C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )?
{
/// Returns the `type` of this event.
@ -460,7 +459,7 @@ macro_rules! impl_possibly_redacted_event {
impl<C> Redact for $ty<C>
where
C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent,
C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )?
{
type Redacted = Self;
@ -476,7 +475,7 @@ macro_rules! impl_possibly_redacted_event {
impl<'de, C> Deserialize<'de> for $ty<C>
where
C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent,
C::Redacted: $redacted_content_trait,
$( C::Redacted: $trait<StateKey = C::StateKey>, )?
{
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) {
/// Returns this event's `room_id` field.
pub fn room_id(&self) -> &RoomId {
match self {
Self::Original(ev) => &ev.room_id,
Self::Redacted(ev) => &ev.room_id,
impl_possibly_redacted_event!(
MessageLikeEvent(
MessageLikeEventContent, RedactedMessageLikeEventContent, MessageLikeEventType
) {
/// Returns this event's `room_id` field.
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.
pub fn as_original(&self) -> Option<&OriginalMessageLikeEvent<C>> {
match self {
Self::Original(v) => Some(v),
_ => None,
/// Get the inner `OriginalMessageLikeEvent` if this is an unredacted event.
pub fn as_original(&self) -> Option<&OriginalMessageLikeEvent<C>> {
match self {
Self::Original(v) => Some(v),
_ => 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!(
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
C::Redacted: StateEventContent<StateKey = C::StateKey>,
{
@ -564,7 +571,7 @@ impl_possibly_redacted_event!(
);
impl_possibly_redacted_event!(
SyncStateEvent(StateEventContent, StateEventType)
SyncStateEvent(StateEventContent, RedactedStateEventContent, StateEventType)
where
C::Redacted: StateEventContent<StateKey = C::StateKey>,
{
@ -595,11 +602,11 @@ impl_possibly_redacted_event!(
);
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>
where
C: $content_trait + RedactContent,
C::Redacted: $content_trait + RedactedEventContent,
C::Redacted: $redacted_content_trait,
{
fn from(full: $full<C>) -> Self {
match full {
@ -611,5 +618,10 @@ macro_rules! impl_sync_from_full {
};
}
impl_sync_from_full!(SyncMessageLikeEvent, MessageLikeEvent, MessageLikeEventContent);
impl_sync_from_full!(SyncStateEvent, StateEvent, StateEventContent);
impl_sync_from_full!(
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::{
events::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventContent,
StateEventType,
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
RedactedStateEventContent, StateEventContent, StateEventType,
},
OwnedRoomAliasId, OwnedServerName, RoomVersionId,
};
@ -99,6 +99,8 @@ impl StateEventContent for RedactedRoomAliasesEventContent {
type StateKey = OwnedServerName;
}
impl RedactedStateEventContent for RedactedRoomAliasesEventContent {}
// Since this redacted event has fields we leave the default `empty` method
// that will error if called.
impl RedactedEventContent for RedactedRoomAliasesEventContent {

View File

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

View File

@ -1,7 +1,7 @@
//! Implementation of the top level `*Event` derive macro.
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 super::{
@ -359,7 +359,6 @@ fn expand_redact_event(
ruma_common: &TokenStream,
) -> syn::Result<TokenStream> {
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 mut generics = input.generics.clone();
@ -376,20 +375,14 @@ fn expand_redact_event(
let where_clause = generics.make_where_clause();
where_clause.predicates.push(parse_quote! { #ty_param: #ruma_common::events::RedactContent });
let redacted_event_content_bound = if kind == EventKind::State {
quote! {
#ruma_common::events::StateEventContent<StateKey = #ty_param::StateKey>
}
} else {
quote! {
#ruma_common::events::EventContent<
EventType = #ruma_common::events::#redacted_event_type_enum
>
}
let assoc_type_bounds =
(kind == EventKind::State).then(|| quote! { StateKey = #ty_param::StateKey });
let trait_name = format_ident!("Redacted{kind}Content");
let redacted_event_content_bound = quote! {
#ruma_common::events::#trait_name<#assoc_type_bounds>
};
where_clause.predicates.push(parse_quote! {
<#ty_param as #ruma_common::events::RedactContent>::Redacted:
#redacted_event_content_bound + #ruma_common::events::RedactedEventContent
<#ty_param as #ruma_common::events::RedactContent>::Redacted: #redacted_event_content_bound
});
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);
let static_event_content_impl = event_kind.map(|k| {
generate_static_event_content_impl(&redacted_ident, k, true, event_type, ruma_common)
let sub_trait_name = event_kind.map(|kind| format_ident!("Redacted{kind}Content"));
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();
@ -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
})
}
@ -611,12 +616,20 @@ fn generate_event_content_impl<'a>(
}
}
let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| {
assert!(state_key_type.is_some());
let sub_trait_impl = event_kind.map(|kind| {
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! {
#[automatically_derived]
impl #ruma_common::events::StateEventContent for #ident {
type StateKey = #state_key_type;
impl #ruma_common::events::#trait_name for #ident {
#state_event_content_impl
}
}
});
@ -682,7 +695,7 @@ fn generate_event_content_impl<'a>(
}
}
#state_event_content_impl
#sub_trait_impl
})
}