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.
|
//! 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::{
|
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::{
|
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 serialize_impl = expand_serialize_event(&input, &var, &fields, &ruma_events);
|
||||||
let deserialize_impl = expand_deserialize_event(&input, &kind, &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);
|
let eq_impl = expand_eq_ord_event(&input, &fields);
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#conversion_impl
|
#conversion_impl
|
||||||
#serialize_impl
|
#serialize_impl
|
||||||
#deserialize_impl
|
#deserialize_impl
|
||||||
|
#redact_impl
|
||||||
#eq_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(
|
fn expand_from_into(
|
||||||
input: &DeriveInput,
|
input: &DeriveInput,
|
||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
|
@ -464,20 +464,10 @@ fn expand_redact(
|
|||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||||
|
|
||||||
let redacted_var = var.to_redacted()?;
|
let redacted_enum = kind.to_event_enum_ident(&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 self_variants = variants.iter().map(|v| v.match_arm(quote! { Self }));
|
let self_variants = variants.iter().map(|v| v.match_arm(quote! { Self }));
|
||||||
let redaction_variants = variants.iter().map(|v| v.ctor(&redacted_enum));
|
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! {
|
Some(quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::Redact for #ident {
|
impl #ruma_events::Redact for #ident {
|
||||||
@ -490,21 +480,13 @@ fn expand_redact(
|
|||||||
) -> #redacted_enum {
|
) -> #redacted_enum {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#(
|
||||||
#self_variants(event) => {
|
#self_variants(event) => #redaction_variants(
|
||||||
let content = #ruma_events::RedactContent::redact(event.content, version);
|
#ruma_events::Redact::redact(event, redaction, version),
|
||||||
#redaction_variants(#redacted_type {
|
),
|
||||||
content,
|
|
||||||
#fields
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)*
|
)*
|
||||||
Self::_Custom(event) => {
|
Self::_Custom(event) => #redacted_enum::_Custom(
|
||||||
let content = #ruma_events::RedactContent::redact(event.content, version);
|
#ruma_events::Redact::redact(event, redaction, version),
|
||||||
#redacted_enum::_Custom(#redacted_type {
|
)
|
||||||
content,
|
|
||||||
#fields
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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))
|
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(
|
fn generate_custom_variant(
|
||||||
event_struct: &Ident,
|
event_struct: &Ident,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
|
@ -5,7 +5,7 @@ use ruma_events_macros::{Event, EventContent};
|
|||||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Unsigned;
|
use crate::{Redact, RedactContent, RedactedUnsigned, Unsigned};
|
||||||
|
|
||||||
/// Redaction event.
|
/// Redaction event.
|
||||||
#[derive(Clone, Debug, Event)]
|
#[derive(Clone, Debug, Event)]
|
||||||
@ -33,6 +33,26 @@ pub struct RedactionEvent {
|
|||||||
pub unsigned: Unsigned,
|
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`.
|
/// Redaction event without a `room_id`.
|
||||||
#[derive(Clone, Debug, Event)]
|
#[derive(Clone, Debug, Event)]
|
||||||
#[allow(clippy::exhaustive_structs)]
|
#[allow(clippy::exhaustive_structs)]
|
||||||
@ -56,6 +76,25 @@ pub struct SyncRedactionEvent {
|
|||||||
pub unsigned: Unsigned,
|
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.
|
/// A redaction of an event.
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user