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,91 +476,83 @@ 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();
|
#[automatically_derived]
|
||||||
Some(quote! {
|
impl #impl_generics ::std::convert::From<#full_struct #ty_gen>
|
||||||
#[automatically_derived]
|
for #ident #ty_gen #where_clause
|
||||||
impl #impl_generics ::std::convert::From<#full_struct #ty_gen>
|
{
|
||||||
for #ident #ty_gen #where_clause
|
fn from(event: #full_struct #ty_gen) -> Self {
|
||||||
{
|
let #full_struct { #( #fields, )* .. } = event;
|
||||||
fn from(event: #full_struct #ty_gen) -> Self {
|
Self { #( #fields, )* }
|
||||||
let #full_struct { #( #fields, )* .. } = event;
|
|
||||||
Self { #( #fields, )* }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics #ident #ty_gen #where_clause {
|
impl #impl_generics #ident #ty_gen #where_clause {
|
||||||
/// Convert this sync event into a full event, one with a room_id field.
|
/// Convert this sync event into a full event, one with a room_id field.
|
||||||
pub fn into_full_event(
|
pub fn into_full_event(
|
||||||
self,
|
self,
|
||||||
room_id: #ruma_identifiers::RoomId,
|
room_id: #ruma_identifiers::RoomId,
|
||||||
) -> #full_struct #ty_gen {
|
) -> #full_struct #ty_gen {
|
||||||
let Self { #( #fields, )* } = self;
|
let Self { #( #fields, )* } = self;
|
||||||
#full_struct {
|
#full_struct {
|
||||||
#( #fields, )*
|
#( #fields, )*
|
||||||
room_id,
|
room_id,
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_eq_ord_event(input: &DeriveInput, fields: &[Field]) -> Option<TokenStream> {
|
|
||||||
fields.iter().flat_map(|f| f.ident.as_ref()).any(|f| f == "event_id").then(|| {
|
|
||||||
let ident = &input.ident;
|
|
||||||
let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #impl_gen ::std::cmp::PartialEq for #ident #ty_gen #where_clause {
|
|
||||||
/// Checks if two `EventId`s are equal.
|
|
||||||
fn eq(&self, other: &Self) -> ::std::primitive::bool {
|
|
||||||
self.event_id == other.event_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #impl_gen ::std::cmp::Eq for #ident #ty_gen #where_clause {}
|
|
||||||
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #impl_gen ::std::cmp::PartialOrd for #ident #ty_gen #where_clause {
|
|
||||||
/// Compares `EventId`s and orders them lexicographically.
|
|
||||||
fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
|
|
||||||
self.event_id.partial_cmp(&other.event_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #impl_gen ::std::cmp::Ord for #ident #ty_gen #where_clause {
|
|
||||||
/// Compares `EventId`s and orders them lexicographically.
|
|
||||||
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
|
|
||||||
self.event_id.cmp(&other.event_id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_eq_ord_event(input: &DeriveInput) -> TokenStream {
|
||||||
|
let ident = &input.ident;
|
||||||
|
let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #impl_gen ::std::cmp::PartialEq for #ident #ty_gen #where_clause {
|
||||||
|
/// Checks if two `EventId`s are equal.
|
||||||
|
fn eq(&self, other: &Self) -> ::std::primitive::bool {
|
||||||
|
self.event_id == other.event_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #impl_gen ::std::cmp::Eq for #ident #ty_gen #where_clause {}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #impl_gen ::std::cmp::PartialOrd for #ident #ty_gen #where_clause {
|
||||||
|
/// Compares `EventId`s and orders them lexicographically.
|
||||||
|
fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
|
||||||
|
self.event_id.partial_cmp(&other.event_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #impl_gen ::std::cmp::Ord for #ident #ty_gen #where_clause {
|
||||||
|
/// Compares `EventId`s and orders them lexicographically.
|
||||||
|
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
|
||||||
|
self.event_id.cmp(&other.event_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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