events-macros: Reorganize event impl generation
This commit is contained in:
parent
7a4af83207
commit
9103ad74bb
@ -10,6 +10,7 @@ use syn::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
event_parse::{to_kind_variation, EventKind, EventKindVariation},
|
event_parse::{to_kind_variation, EventKind, EventKindVariation},
|
||||||
import_ruma_events,
|
import_ruma_events,
|
||||||
|
util::is_non_stripped_room_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Derive `Event` macro code generation.
|
/// Derive `Event` macro code generation.
|
||||||
@ -41,19 +42,26 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let conversion_impl = expand_from_into(&input, kind, var, &fields, &ruma_events);
|
let mut res = TokenStream::new();
|
||||||
let serialize_impl = expand_serialize_event(&input, var, &fields, &ruma_events);
|
|
||||||
let deserialize_impl = expand_deserialize_event(&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! {
|
res.extend(expand_serialize_event(&input, var, &fields, &ruma_events));
|
||||||
#conversion_impl
|
res.extend(expand_deserialize_event(&input, kind, var, &fields, &ruma_events)?);
|
||||||
#serialize_impl
|
|
||||||
#deserialize_impl
|
if var.is_sync() {
|
||||||
#redact_impl
|
res.extend(expand_sync_from_into_full(&input, kind, var, &fields, &ruma_events));
|
||||||
#eq_impl
|
}
|
||||||
})
|
|
||||||
|
if matches!(kind, EventKind::Message | EventKind::State)
|
||||||
|
&& matches!(var, EventKindVariation::Full | EventKindVariation::Sync)
|
||||||
|
{
|
||||||
|
res.extend(expand_redact_event(&input, kind, var, &fields, &ruma_events));
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_non_stripped_room_event(kind, var) {
|
||||||
|
res.extend(expand_eq_ord_event(&input));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_serialize_event(
|
fn expand_serialize_event(
|
||||||
@ -405,17 +413,17 @@ fn expand_redact_event(
|
|||||||
var: EventKindVariation,
|
var: EventKindVariation,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
ruma_events: &TokenStream,
|
ruma_events: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> TokenStream {
|
||||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||||
|
|
||||||
let redacted_type = kind.to_event_ident(var.to_redacted()?)?;
|
let redacted_type = kind.to_event_ident(var.to_redacted().unwrap()).unwrap();
|
||||||
let redacted_content_trait =
|
let redacted_content_trait =
|
||||||
format_ident!("{}Content", kind.to_event_ident(EventKindVariation::Redacted).unwrap());
|
format_ident!("{}Content", kind.to_event_ident(EventKindVariation::Redacted).unwrap());
|
||||||
let ident = &input.ident;
|
let ident = &input.ident;
|
||||||
|
|
||||||
let mut generics = input.generics.clone();
|
let mut generics = input.generics.clone();
|
||||||
if generics.params.is_empty() {
|
if generics.params.is_empty() {
|
||||||
return None;
|
return TokenStream::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(generics.params.len(), 1, "expected one generic parameter");
|
assert_eq!(generics.params.len(), 1, "expected one generic parameter");
|
||||||
@ -450,7 +458,7 @@ fn expand_redact_event(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(quote! {
|
quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics #ruma_events::Redact for #ident #ty_gen #where_clause {
|
impl #impl_generics #ruma_events::Redact for #ident #ty_gen #where_clause {
|
||||||
type Redacted =
|
type Redacted =
|
||||||
@ -468,27 +476,24 @@ fn expand_redact_event(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_from_into(
|
fn expand_sync_from_into_full(
|
||||||
input: &DeriveInput,
|
input: &DeriveInput,
|
||||||
kind: EventKind,
|
kind: EventKind,
|
||||||
var: EventKindVariation,
|
var: EventKindVariation,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
ruma_events: &TokenStream,
|
ruma_events: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> TokenStream {
|
||||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||||
|
|
||||||
let ident = &input.ident;
|
let ident = &input.ident;
|
||||||
|
let full_struct = kind.to_event_ident(var.to_full().unwrap()).unwrap();
|
||||||
let (impl_generics, ty_gen, where_clause) = input.generics.split_for_impl();
|
let (impl_generics, ty_gen, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
let fields: Vec<_> = fields.iter().flat_map(|f| &f.ident).collect();
|
let fields: Vec<_> = fields.iter().flat_map(|f| &f.ident).collect();
|
||||||
|
|
||||||
if let EventKindVariation::Sync | EventKindVariation::RedactedSync = var {
|
quote! {
|
||||||
let full_struct = kind.to_event_ident(var.to_full().unwrap()).unwrap();
|
|
||||||
Some(quote! {
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics ::std::convert::From<#full_struct #ty_gen>
|
impl #impl_generics ::std::convert::From<#full_struct #ty_gen>
|
||||||
for #ident #ty_gen #where_clause
|
for #ident #ty_gen #where_clause
|
||||||
@ -513,14 +518,10 @@ fn expand_from_into(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_eq_ord_event(input: &DeriveInput, fields: &[Field]) -> Option<TokenStream> {
|
fn expand_eq_ord_event(input: &DeriveInput) -> TokenStream {
|
||||||
fields.iter().flat_map(|f| f.ident.as_ref()).any(|f| f == "event_id").then(|| {
|
|
||||||
let ident = &input.ident;
|
let ident = &input.ident;
|
||||||
let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl();
|
let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
@ -552,7 +553,6 @@ fn expand_eq_ord_event(input: &DeriveInput, fields: &[Field]) -> Option<TokenStr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CamelCase's a field ident like "foo_bar" to "FooBar".
|
/// CamelCase's a field ident like "foo_bar" to "FooBar".
|
||||||
|
@ -4,43 +4,10 @@ use proc_macro2::{Span, TokenStream};
|
|||||||
use quote::{format_ident, quote, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr};
|
use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr};
|
||||||
|
|
||||||
use crate::event_parse::{EventEnumDecl, EventEnumEntry, EventKind, EventKindVariation};
|
use crate::{
|
||||||
|
event_parse::{EventEnumDecl, EventEnumEntry, EventKind, EventKindVariation},
|
||||||
fn is_non_stripped_room_event(kind: EventKind, var: EventKindVariation) -> bool {
|
util::{has_prev_content_field, EVENT_FIELDS},
|
||||||
matches!(kind, EventKind::Message | EventKind::State)
|
};
|
||||||
&& matches!(
|
|
||||||
var,
|
|
||||||
EventKindVariation::Full
|
|
||||||
| EventKindVariation::Sync
|
|
||||||
| EventKindVariation::Redacted
|
|
||||||
| EventKindVariation::RedactedSync
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_prev_content_field(kind: EventKind, var: EventKindVariation) -> bool {
|
|
||||||
matches!(kind, EventKind::State)
|
|
||||||
&& matches!(var, EventKindVariation::Full | EventKindVariation::Sync)
|
|
||||||
}
|
|
||||||
|
|
||||||
type EventKindFn = fn(EventKind, EventKindVariation) -> bool;
|
|
||||||
|
|
||||||
/// This const is used to generate the accessor methods for the `Any*Event` enums.
|
|
||||||
///
|
|
||||||
/// DO NOT alter the field names unless the structs in `ruma_events::event_kinds` have changed.
|
|
||||||
const EVENT_FIELDS: &[(&str, EventKindFn)] = &[
|
|
||||||
("origin_server_ts", is_non_stripped_room_event),
|
|
||||||
("room_id", |kind, var| {
|
|
||||||
matches!(kind, EventKind::Message | EventKind::State | EventKind::Ephemeral)
|
|
||||||
&& matches!(var, EventKindVariation::Full | EventKindVariation::Redacted)
|
|
||||||
}),
|
|
||||||
("event_id", is_non_stripped_room_event),
|
|
||||||
("sender", |kind, var| {
|
|
||||||
matches!(kind, EventKind::Message | EventKind::State | EventKind::ToDevice)
|
|
||||||
&& var != EventKindVariation::Initial
|
|
||||||
}),
|
|
||||||
("state_key", |kind, _| matches!(kind, EventKind::State)),
|
|
||||||
("unsigned", is_non_stripped_room_event),
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Create a content enum from `EventEnumInput`.
|
/// Create a content enum from `EventEnumInput`.
|
||||||
pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result<TokenStream> {
|
pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result<TokenStream> {
|
||||||
|
@ -45,6 +45,10 @@ impl EventKindVariation {
|
|||||||
matches!(self, Self::Redacted | Self::RedactedSync)
|
matches!(self, Self::Redacted | Self::RedactedSync)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_sync(self) -> bool {
|
||||||
|
matches!(self, Self::Sync | Self::RedactedSync)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_redacted(self) -> Option<Self> {
|
pub fn to_redacted(self) -> Option<Self> {
|
||||||
match self {
|
match self {
|
||||||
EventKindVariation::Full => Some(EventKindVariation::Redacted),
|
EventKindVariation::Full => Some(EventKindVariation::Redacted),
|
||||||
|
@ -27,6 +27,7 @@ mod event_content;
|
|||||||
mod event_enum;
|
mod event_enum;
|
||||||
mod event_parse;
|
mod event_parse;
|
||||||
mod event_type;
|
mod event_type;
|
||||||
|
mod util;
|
||||||
|
|
||||||
/// Generates an enum to represent the various Matrix event types.
|
/// Generates an enum to represent the various Matrix event types.
|
||||||
///
|
///
|
||||||
|
37
crates/ruma-events-macros/src/util.rs
Normal file
37
crates/ruma-events-macros/src/util.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use crate::event_parse::{EventKind, EventKindVariation};
|
||||||
|
|
||||||
|
pub(crate) fn is_non_stripped_room_event(kind: EventKind, var: EventKindVariation) -> bool {
|
||||||
|
matches!(kind, EventKind::Message | EventKind::State)
|
||||||
|
&& matches!(
|
||||||
|
var,
|
||||||
|
EventKindVariation::Full
|
||||||
|
| EventKindVariation::Sync
|
||||||
|
| EventKindVariation::Redacted
|
||||||
|
| EventKindVariation::RedactedSync
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_prev_content_field(kind: EventKind, var: EventKindVariation) -> bool {
|
||||||
|
matches!(kind, EventKind::State)
|
||||||
|
&& matches!(var, EventKindVariation::Full | EventKindVariation::Sync)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) type EventKindFn = fn(EventKind, EventKindVariation) -> bool;
|
||||||
|
|
||||||
|
/// This const is used to generate the accessor methods for the `Any*Event` enums.
|
||||||
|
///
|
||||||
|
/// DO NOT alter the field names unless the structs in `ruma_events::event_kinds` have changed.
|
||||||
|
pub(crate) const EVENT_FIELDS: &[(&str, EventKindFn)] = &[
|
||||||
|
("origin_server_ts", is_non_stripped_room_event),
|
||||||
|
("room_id", |kind, var| {
|
||||||
|
matches!(kind, EventKind::Message | EventKind::State | EventKind::Ephemeral)
|
||||||
|
&& matches!(var, EventKindVariation::Full | EventKindVariation::Redacted)
|
||||||
|
}),
|
||||||
|
("event_id", is_non_stripped_room_event),
|
||||||
|
("sender", |kind, var| {
|
||||||
|
matches!(kind, EventKind::Message | EventKind::State | EventKind::ToDevice)
|
||||||
|
&& var != EventKindVariation::Initial
|
||||||
|
}),
|
||||||
|
("state_key", |kind, _| matches!(kind, EventKind::State)),
|
||||||
|
("unsigned", is_non_stripped_room_event),
|
||||||
|
];
|
Loading…
x
Reference in New Issue
Block a user