From e41abbb56b3adccd1810061c56468fa54b0d4717 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 2 Oct 2021 01:19:36 +0200 Subject: [PATCH] events: Implement Redact for event structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … it was only implemented for the enums before. --- crates/ruma-events-macros/src/event.rs | 78 +++++++++++++++++++-- crates/ruma-events-macros/src/event_enum.rs | 54 ++------------ crates/ruma-events/src/room/redaction.rs | 41 ++++++++++- 3 files changed, 121 insertions(+), 52 deletions(-) diff --git a/crates/ruma-events-macros/src/event.rs b/crates/ruma-events-macros/src/event.rs index d9106561..79e398dc 100644 --- a/crates/ruma-events-macros/src/event.rs +++ b/crates/ruma-events-macros/src/event.rs @@ -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 { )); }; + 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 { + 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, diff --git a/crates/ruma-events-macros/src/event_enum.rs b/crates/ruma-events-macros/src/event_enum.rs index c6880002..7c58f707 100644 --- a/crates/ruma-events-macros/src/event_enum.rs +++ b/crates/ruma-events-macros/src/event_enum.rs @@ -464,20 +464,10 @@ fn expand_redact( ) -> Option { 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 { - 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, diff --git a/crates/ruma-events/src/room/redaction.rs b/crates/ruma-events/src/room/redaction.rs index 8209ec80..8a13a6d0 100644 --- a/crates/ruma-events/src/room/redaction.rs +++ b/crates/ruma-events/src/room/redaction.rs @@ -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; + + 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; + + 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)]