events: Implement Redact for event structs
… it was only implemented for the enums before.
This commit is contained in:
parent
3b786d8f78
commit
e41abbb56b
@ -1,9 +1,10 @@
|
||||
//! Implementation of the top level `*Event` derive macro.
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, Ident, Meta, MetaList, NestedMeta,
|
||||
parse_quote, Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, GenericParam, Ident,
|
||||
Meta, MetaList, NestedMeta,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -40,16 +41,17 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> {
|
||||
));
|
||||
};
|
||||
|
||||
let conversion_impl = expand_from_into(&input, &kind, &var, &fields, &ruma_events);
|
||||
let serialize_impl = expand_serialize_event(&input, &var, &fields, &ruma_events);
|
||||
let deserialize_impl = expand_deserialize_event(&input, &kind, &var, &fields, &ruma_events)?;
|
||||
let conversion_impl = expand_from_into(&input, &kind, &var, &fields, &ruma_events);
|
||||
|
||||
let redact_impl = expand_redact_event(&input, &kind, &var, &fields, &ruma_events);
|
||||
let eq_impl = expand_eq_ord_event(&input, &fields);
|
||||
|
||||
Ok(quote! {
|
||||
#conversion_impl
|
||||
#serialize_impl
|
||||
#deserialize_impl
|
||||
#redact_impl
|
||||
#eq_impl
|
||||
})
|
||||
}
|
||||
@ -391,6 +393,74 @@ fn expand_deserialize_event(
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_redact_event(
|
||||
input: &DeriveInput,
|
||||
kind: &EventKind,
|
||||
var: &EventKindVariation,
|
||||
fields: &[Field],
|
||||
ruma_events: &TokenStream,
|
||||
) -> Option<TokenStream> {
|
||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||
|
||||
let redacted_type = kind.to_event_ident(&var.to_redacted()?)?;
|
||||
let redacted_content_trait =
|
||||
format_ident!("{}Content", kind.to_event_ident(&EventKindVariation::Redacted).unwrap());
|
||||
let ident = &input.ident;
|
||||
|
||||
let mut generics = input.generics.clone();
|
||||
assert_eq!(generics.params.len(), 1, "expected one generic parameter");
|
||||
let ty_param = match &generics.params[0] {
|
||||
GenericParam::Type(ty) => ty.ident.clone(),
|
||||
_ => panic!("expected a type parameter"),
|
||||
};
|
||||
|
||||
let where_clause = generics.make_where_clause();
|
||||
where_clause.predicates.push(parse_quote! { #ty_param: #ruma_events::RedactContent });
|
||||
where_clause.predicates.push(parse_quote! {
|
||||
<#ty_param as #ruma_events::RedactContent>::Redacted:
|
||||
#ruma_events::#redacted_content_trait
|
||||
});
|
||||
|
||||
let (impl_generics, ty_gen, where_clause) = generics.split_for_impl();
|
||||
|
||||
let fields = fields.iter().filter_map(|field| {
|
||||
let ident = field.ident.as_ref().unwrap();
|
||||
|
||||
if ident == "content" || ident == "prev_content" {
|
||||
None
|
||||
} else if ident == "unsigned" {
|
||||
Some(quote! {
|
||||
unsigned:
|
||||
#ruma_events::RedactedUnsigned::new_because(::std::boxed::Box::new(redaction))
|
||||
})
|
||||
} else {
|
||||
Some(quote! {
|
||||
#ident: self.#ident
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
Some(quote! {
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #ruma_events::Redact for #ident #ty_gen #where_clause {
|
||||
type Redacted =
|
||||
#ruma_events::#redacted_type<<#ty_param as #ruma_events::RedactContent>::Redacted>;
|
||||
|
||||
fn redact(
|
||||
self,
|
||||
redaction: #ruma_events::room::redaction::SyncRedactionEvent,
|
||||
version: &#ruma_identifiers::RoomVersionId,
|
||||
) -> Self::Redacted {
|
||||
let content = #ruma_events::RedactContent::redact(self.content, version);
|
||||
#ruma_events::#redacted_type {
|
||||
content,
|
||||
#(#fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_from_into(
|
||||
input: &DeriveInput,
|
||||
kind: &EventKind,
|
||||
|
@ -464,20 +464,10 @@ fn expand_redact(
|
||||
) -> Option<TokenStream> {
|
||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||
|
||||
let redacted_var = var.to_redacted()?;
|
||||
let struct_id = kind.to_event_ident(&redacted_var)?;
|
||||
let redacted_enum = kind.to_event_enum_ident(&redacted_var)?;
|
||||
let redacted_type = quote! { #ruma_events::#struct_id };
|
||||
|
||||
let redacted_enum = kind.to_event_enum_ident(&var.to_redacted()?)?;
|
||||
let self_variants = variants.iter().map(|v| v.match_arm(quote! { Self }));
|
||||
let redaction_variants = variants.iter().map(|v| v.ctor(&redacted_enum));
|
||||
|
||||
let fields = EVENT_FIELDS.iter().map(|(name, has_field)| {
|
||||
generate_redacted_fields(name, kind, var, *has_field, ruma_events)
|
||||
});
|
||||
|
||||
let fields = quote! { #( #fields )* };
|
||||
|
||||
Some(quote! {
|
||||
#[automatically_derived]
|
||||
impl #ruma_events::Redact for #ident {
|
||||
@ -490,21 +480,13 @@ fn expand_redact(
|
||||
) -> #redacted_enum {
|
||||
match self {
|
||||
#(
|
||||
#self_variants(event) => {
|
||||
let content = #ruma_events::RedactContent::redact(event.content, version);
|
||||
#redaction_variants(#redacted_type {
|
||||
content,
|
||||
#fields
|
||||
})
|
||||
}
|
||||
#self_variants(event) => #redaction_variants(
|
||||
#ruma_events::Redact::redact(event, redaction, version),
|
||||
),
|
||||
)*
|
||||
Self::_Custom(event) => {
|
||||
let content = #ruma_events::RedactContent::redact(event.content, version);
|
||||
#redacted_enum::_Custom(#redacted_type {
|
||||
content,
|
||||
#fields
|
||||
})
|
||||
}
|
||||
Self::_Custom(event) => #redacted_enum::_Custom(
|
||||
#ruma_events::Redact::redact(event, redaction, version),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -564,28 +546,6 @@ fn generate_event_idents(kind: &EventKind, var: &EventKindVariation) -> Option<(
|
||||
kind.to_event_ident(var).zip(kind.to_event_enum_ident(var))
|
||||
}
|
||||
|
||||
fn generate_redacted_fields(
|
||||
name: &str,
|
||||
kind: &EventKind,
|
||||
var: &EventKindVariation,
|
||||
is_event_kind: EventKindFn,
|
||||
ruma_events: &TokenStream,
|
||||
) -> Option<TokenStream> {
|
||||
is_event_kind(kind, var).then(|| {
|
||||
let name = Ident::new(name, Span::call_site());
|
||||
|
||||
if name == "unsigned" {
|
||||
quote! {
|
||||
unsigned: #ruma_events::RedactedUnsigned::new_because(::std::boxed::Box::new(redaction)),
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#name: event.#name,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_custom_variant(
|
||||
event_struct: &Ident,
|
||||
var: &EventKindVariation,
|
||||
|
@ -5,7 +5,7 @@ use ruma_events_macros::{Event, EventContent};
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Unsigned;
|
||||
use crate::{Redact, RedactContent, RedactedUnsigned, Unsigned};
|
||||
|
||||
/// Redaction event.
|
||||
#[derive(Clone, Debug, Event)]
|
||||
@ -33,6 +33,26 @@ pub struct RedactionEvent {
|
||||
pub unsigned: Unsigned,
|
||||
}
|
||||
|
||||
impl Redact for RedactionEvent {
|
||||
// Temporary hack
|
||||
type Redacted = crate::RedactedMessageEvent<RedactedRedactionEventContent>;
|
||||
|
||||
fn redact(
|
||||
self,
|
||||
redaction: SyncRedactionEvent,
|
||||
version: &ruma_identifiers::RoomVersionId,
|
||||
) -> Self::Redacted {
|
||||
crate::RedactedMessageEvent {
|
||||
content: self.content.redact(version),
|
||||
event_id: self.event_id,
|
||||
sender: self.sender,
|
||||
origin_server_ts: self.origin_server_ts,
|
||||
room_id: self.room_id,
|
||||
unsigned: RedactedUnsigned::new_because(Box::new(redaction)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Redaction event without a `room_id`.
|
||||
#[derive(Clone, Debug, Event)]
|
||||
#[allow(clippy::exhaustive_structs)]
|
||||
@ -56,6 +76,25 @@ pub struct SyncRedactionEvent {
|
||||
pub unsigned: Unsigned,
|
||||
}
|
||||
|
||||
impl Redact for SyncRedactionEvent {
|
||||
// Temporary hack
|
||||
type Redacted = crate::RedactedSyncMessageEvent<RedactedRedactionEventContent>;
|
||||
|
||||
fn redact(
|
||||
self,
|
||||
redaction: SyncRedactionEvent,
|
||||
version: &ruma_identifiers::RoomVersionId,
|
||||
) -> Self::Redacted {
|
||||
crate::RedactedSyncMessageEvent {
|
||||
content: self.content.redact(version),
|
||||
event_id: self.event_id,
|
||||
sender: self.sender,
|
||||
origin_server_ts: self.origin_server_ts,
|
||||
unsigned: RedactedUnsigned::new_because(Box::new(redaction)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A redaction of an event.
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user