diff --git a/ruma-events-macros/src/event.rs b/ruma-events-macros/src/event.rs index 58703e2c..91395e61 100644 --- a/ruma-events-macros/src/event.rs +++ b/ruma-events-macros/src/event.rs @@ -4,9 +4,15 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, Ident}; +use crate::event_parse::{to_kind_variation, EventKindVariation}; + /// Derive `Event` macro code generation. pub fn expand_event(input: DeriveInput) -> syn::Result { let ident = &input.ident; + + let (_kind, var) = to_kind_variation(ident) + .ok_or(syn::Error::new(Span::call_site(), "not a valid ruma event struct identifier"))?; + let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl(); let is_generic = !input.generics.params.is_empty(); @@ -37,7 +43,12 @@ pub fn expand_event(input: DeriveInput) -> syn::Result { .iter() .map(|field| { let name = field.ident.as_ref().unwrap(); - if name == "content" && ident.to_string().contains("Redacted") { + if name == "content" && matches!( + var, + EventKindVariation::Redacted + | EventKindVariation::RedactedSync + | EventKindVariation::RedactedStripped + ) { quote! { if ::ruma_events::RedactedEventContent::has_serialize_fields(&self.content) { state.serialize_field("content", &self.content)?; @@ -92,7 +103,7 @@ pub fn expand_event(input: DeriveInput) -> syn::Result { } }; - let deserialize_impl = expand_deserialize_event(is_generic, input, fields)?; + let deserialize_impl = expand_deserialize_event(input, &var, fields, is_generic)?; Ok(quote! { #serialize_impl @@ -102,9 +113,10 @@ pub fn expand_event(input: DeriveInput) -> syn::Result { } fn expand_deserialize_event( - is_generic: bool, input: DeriveInput, + var: &EventKindVariation, fields: Vec, + is_generic: bool, ) -> syn::Result { let ident = &input.ident; // we know there is a content field already @@ -149,7 +161,12 @@ fn expand_deserialize_event( .map(|field| { let name = field.ident.as_ref().unwrap(); if name == "content" { - if is_generic && ident.to_string().contains("Redacted") { + if is_generic && matches!( + var, + EventKindVariation::Redacted + | EventKindVariation::RedactedSync + | EventKindVariation::RedactedStripped + ) { quote! { let content = match C::has_deserialize_fields() { ::ruma_events::HasDeserializeFields::False => { diff --git a/ruma-events-macros/src/event_parse.rs b/ruma-events-macros/src/event_parse.rs index 813c414a..e6cfd01c 100644 --- a/ruma-events-macros/src/event_parse.rs +++ b/ruma-events-macros/src/event_parse.rs @@ -22,6 +22,7 @@ pub enum EventKindVariation { Redacted, RedactedSync, RedactedStripped, + ManuallyImpled, } // If the variants of this enum change `to_event_path` needs to be updated as well. @@ -31,6 +32,7 @@ pub enum EventKind { Message(Ident), State(Ident), ToDevice(Ident), + ManuallyImpled(Ident), } impl EventKind { @@ -78,7 +80,8 @@ impl EventKind { | EventKind::Ephemeral(i) | EventKind::Message(i) | EventKind::State(i) - | EventKind::ToDevice(i) => i, + | EventKind::ToDevice(i) + | EventKind::ManuallyImpled(i) => i, } } } @@ -105,6 +108,44 @@ impl Parse for EventKind { } } +pub fn to_kind_variation(ident: &Ident) -> Option<(EventKind, EventKindVariation)> { + let ident_str = ident.to_string(); + match ident_str.as_str() { + "BasicEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Full)), + "EphemeralRoomEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Full)), + "SyncEphemeralRoomEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::Sync)) + } + "MessageEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Full)), + "SyncMessageEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Sync)), + "RedactedMessageEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::Redacted)) + } + "RedactedSyncMessageEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::RedactedSync)) + } + "StateEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Full)), + "SyncStateEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Sync)), + "StrippedStateEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::Stripped)) + } + "RedactedStateEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::Redacted)) + } + "RedactedSyncStateEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::RedactedSync)) + } + "RedactedStrippedStateEvent" => { + Some((EventKind::Basic(ident.clone()), EventKindVariation::RedactedStripped)) + } + "ToDeviceEvent" => Some((EventKind::Basic(ident.clone()), EventKindVariation::Full)), + "PresenceEvent" | "RedactionEvent" | "SyncRedactionEvent" => { + Some((EventKind::ManuallyImpled(ident.clone()), EventKindVariation::ManuallyImpled)) + } + _ => None, + } +} + /// The entire `event_enum!` macro structure directly as it appears in the source code. pub struct EventEnumInput { /// Outer attributes on the field, such as a docstring.