events: Support attributes on items in event_enum!
This commit is contained in:
parent
1dee89393a
commit
b7e15efe43
@ -1,10 +1,10 @@
|
|||||||
//! Implementation of event enum and event content enum macros.
|
//! Implementation of event enum and event content enum macros.
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use syn::{Attribute, Ident, LitStr};
|
use syn::{Attribute, Ident, LitStr};
|
||||||
|
|
||||||
use crate::event_parse::{EventEnumInput, EventKind, EventKindVariation};
|
use crate::event_parse::{EventEnumEntry, EventEnumInput, EventKind, EventKindVariation};
|
||||||
|
|
||||||
fn is_non_stripped_room_event(kind: &EventKind, var: &EventKindVariation) -> bool {
|
fn is_non_stripped_room_event(kind: &EventKind, var: &EventKindVariation) -> bool {
|
||||||
matches!(kind, EventKind::Message | EventKind::State)
|
matches!(kind, EventKind::Message | EventKind::State)
|
||||||
@ -47,13 +47,14 @@ pub fn expand_event_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
|||||||
let import_path = crate::import_ruma_events();
|
let import_path = crate::import_ruma_events();
|
||||||
|
|
||||||
let name = &input.name;
|
let name = &input.name;
|
||||||
let events = &input.events;
|
|
||||||
let attrs = &input.attrs;
|
let attrs = &input.attrs;
|
||||||
let variants = events.iter().map(to_camel_case).collect::<syn::Result<Vec<_>>>()?;
|
let events: Vec<_> = input.events.iter().map(|entry| entry.ev_type.clone()).collect();
|
||||||
|
let variants: Vec<_> =
|
||||||
|
input.events.iter().map(EventEnumEntry::to_variant).collect::<syn::Result<_>>()?;
|
||||||
|
|
||||||
let event_enum = expand_any_with_deser(
|
let event_enum = expand_any_with_deser(
|
||||||
name,
|
name,
|
||||||
events,
|
&events,
|
||||||
attrs,
|
attrs,
|
||||||
&variants,
|
&variants,
|
||||||
&EventKindVariation::Full,
|
&EventKindVariation::Full,
|
||||||
@ -62,7 +63,7 @@ pub fn expand_event_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
|||||||
|
|
||||||
let sync_event_enum = expand_any_with_deser(
|
let sync_event_enum = expand_any_with_deser(
|
||||||
name,
|
name,
|
||||||
events,
|
&events,
|
||||||
attrs,
|
attrs,
|
||||||
&variants,
|
&variants,
|
||||||
&EventKindVariation::Sync,
|
&EventKindVariation::Sync,
|
||||||
@ -71,7 +72,7 @@ pub fn expand_event_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
|||||||
|
|
||||||
let stripped_event_enum = expand_any_with_deser(
|
let stripped_event_enum = expand_any_with_deser(
|
||||||
name,
|
name,
|
||||||
events,
|
&events,
|
||||||
attrs,
|
attrs,
|
||||||
&variants,
|
&variants,
|
||||||
&EventKindVariation::Stripped,
|
&EventKindVariation::Stripped,
|
||||||
@ -80,16 +81,16 @@ pub fn expand_event_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
|||||||
|
|
||||||
let initial_event_enum = expand_any_with_deser(
|
let initial_event_enum = expand_any_with_deser(
|
||||||
name,
|
name,
|
||||||
events,
|
&events,
|
||||||
attrs,
|
attrs,
|
||||||
&variants,
|
&variants,
|
||||||
&EventKindVariation::Initial,
|
&EventKindVariation::Initial,
|
||||||
&import_path,
|
&import_path,
|
||||||
);
|
);
|
||||||
|
|
||||||
let redacted_event_enums = expand_any_redacted(name, events, attrs, &variants, &import_path);
|
let redacted_event_enums = expand_any_redacted(name, &events, attrs, &variants, &import_path);
|
||||||
|
|
||||||
let event_content_enum = expand_content_enum(name, events, attrs, &variants, &import_path);
|
let event_content_enum = expand_content_enum(name, &events, attrs, &variants, &import_path);
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#event_enum
|
#event_enum
|
||||||
@ -110,7 +111,7 @@ fn expand_any_with_deser(
|
|||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
events: &[LitStr],
|
events: &[LitStr],
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
@ -124,6 +125,9 @@ fn expand_any_with_deser(
|
|||||||
.map(|event| to_event_path(event, &event_struct, import_path))
|
.map(|event| to_event_path(event, &event_struct, import_path))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let variant_decls = variants.iter().map(|v| v.decl());
|
||||||
|
let self_variants = variants.iter().map(|v| v.ctor(quote!(Self)));
|
||||||
|
|
||||||
let (custom_variant, custom_deserialize) =
|
let (custom_variant, custom_deserialize) =
|
||||||
generate_custom_variant(&event_struct, var, import_path);
|
generate_custom_variant(&event_struct, var, import_path);
|
||||||
|
|
||||||
@ -135,12 +139,17 @@ fn expand_any_with_deser(
|
|||||||
pub enum #ident {
|
pub enum #ident {
|
||||||
#(
|
#(
|
||||||
#[doc = #events]
|
#[doc = #events]
|
||||||
#variants(#content),
|
#variant_decls(#content),
|
||||||
)*
|
)*
|
||||||
#custom_variant
|
#custom_variant
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let variant_attrs = variants.iter().map(|v| {
|
||||||
|
let attrs = &v.attrs;
|
||||||
|
quote! { #(#attrs)* }
|
||||||
|
});
|
||||||
|
|
||||||
let event_deserialize_impl = quote! {
|
let event_deserialize_impl = quote! {
|
||||||
impl<'de> #import_path::exports::serde::de::Deserialize<'de> for #ident {
|
impl<'de> #import_path::exports::serde::de::Deserialize<'de> for #ident {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
@ -155,10 +164,10 @@ fn expand_any_with_deser(
|
|||||||
|
|
||||||
match ev_type.as_str() {
|
match ev_type.as_str() {
|
||||||
#(
|
#(
|
||||||
#events => {
|
#variant_attrs #events => {
|
||||||
let event = #import_path::exports::serde_json::from_str::<#content>(json.get())
|
let event = #import_path::exports::serde_json::from_str::<#content>(json.get())
|
||||||
.map_err(D::Error::custom)?;
|
.map_err(D::Error::custom)?;
|
||||||
Ok(Self::#variants(event))
|
Ok(#self_variants(event))
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
#custom_deserialize
|
#custom_deserialize
|
||||||
@ -193,17 +202,17 @@ fn expand_any_with_deser(
|
|||||||
fn expand_conversion_impl(
|
fn expand_conversion_impl(
|
||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
let ident = kind.to_event_enum_ident(var)?;
|
let ident = kind.to_event_enum_ident(var)?;
|
||||||
let variants = &variants
|
let variants = &variants
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|id| {
|
.filter(|v| {
|
||||||
// We filter this variant out only for non redacted events.
|
// We filter this variant out only for non redacted events.
|
||||||
// The type of the struct held in the enum variant is different in this case
|
// The type of the struct held in the enum variant is different in this case
|
||||||
// so we construct the variant manually.
|
// so we construct the variant manually.
|
||||||
!(id.to_string().as_str() == "RoomRedaction"
|
!(v.ident == "RoomRedaction"
|
||||||
&& matches!(var, EventKindVariation::Full | EventKindVariation::Sync))
|
&& matches!(var, EventKindVariation::Full | EventKindVariation::Sync))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -220,6 +229,9 @@ fn expand_conversion_impl(
|
|||||||
let sync = kind.to_event_enum_ident(&variation)?;
|
let sync = kind.to_event_enum_ident(&variation)?;
|
||||||
let sync_struct = kind.to_event_ident(&variation)?;
|
let sync_struct = kind.to_event_ident(&variation)?;
|
||||||
|
|
||||||
|
let ident_variants = variants.iter().map(|v| v.match_arm(&ident));
|
||||||
|
let self_variants = variants.iter().map(|v| v.ctor(quote!(Self)));
|
||||||
|
|
||||||
let redaction = if let (EventKind::Message, EventKindVariation::Full) = (kind, var) {
|
let redaction = if let (EventKind::Message, EventKindVariation::Full) = (kind, var) {
|
||||||
quote! {
|
quote! {
|
||||||
#ident::RoomRedaction(event) => Self::RoomRedaction(
|
#ident::RoomRedaction(event) => Self::RoomRedaction(
|
||||||
@ -235,8 +247,8 @@ fn expand_conversion_impl(
|
|||||||
fn from(event: #ident) -> Self {
|
fn from(event: #ident) -> Self {
|
||||||
match event {
|
match event {
|
||||||
#(
|
#(
|
||||||
#ident::#variants(event) => {
|
#ident_variants(event) => {
|
||||||
Self::#variants(#import_path::#sync_struct::from(event))
|
#self_variants(#import_path::#sync_struct::from(event))
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
#redaction
|
#redaction
|
||||||
@ -256,6 +268,9 @@ fn expand_conversion_impl(
|
|||||||
};
|
};
|
||||||
let full = kind.to_event_enum_ident(&variation)?;
|
let full = kind.to_event_enum_ident(&variation)?;
|
||||||
|
|
||||||
|
let self_variants = variants.iter().map(|v| v.match_arm(quote!(Self)));
|
||||||
|
let full_variants = variants.iter().map(|v| v.ctor(&full));
|
||||||
|
|
||||||
let redaction = if let (EventKind::Message, EventKindVariation::Sync) = (kind, var) {
|
let redaction = if let (EventKind::Message, EventKindVariation::Sync) = (kind, var) {
|
||||||
quote! {
|
quote! {
|
||||||
Self::RoomRedaction(event) => {
|
Self::RoomRedaction(event) => {
|
||||||
@ -269,11 +284,14 @@ fn expand_conversion_impl(
|
|||||||
Some(quote! {
|
Some(quote! {
|
||||||
impl #ident {
|
impl #ident {
|
||||||
/// 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(self, room_id: #import_path::exports::ruma_identifiers::RoomId) -> #full {
|
pub fn into_full_event(
|
||||||
|
self,
|
||||||
|
room_id: #import_path::exports::ruma_identifiers::RoomId
|
||||||
|
) -> #full {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#(
|
||||||
Self::#variants(event) => {
|
#self_variants(event) => {
|
||||||
#full::#variants(event.into_full_event(room_id))
|
#full_variants(event.into_full_event(room_id))
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
#redaction
|
#redaction
|
||||||
@ -298,7 +316,7 @@ fn expand_any_redacted(
|
|||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
events: &[LitStr],
|
events: &[LitStr],
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
use EventKindVariation as V;
|
use EventKindVariation as V;
|
||||||
@ -339,7 +357,7 @@ fn expand_content_enum(
|
|||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
events: &[LitStr],
|
events: &[LitStr],
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let ident = kind.to_content_enum();
|
let ident = kind.to_content_enum();
|
||||||
@ -348,6 +366,8 @@ fn expand_content_enum(
|
|||||||
let content =
|
let content =
|
||||||
events.iter().map(|ev| to_event_content_path(ev, import_path)).collect::<Vec<_>>();
|
events.iter().map(|ev| to_event_content_path(ev, import_path)).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let variant_decls = variants.iter().map(|v| v.decl());
|
||||||
|
|
||||||
let content_enum = quote! {
|
let content_enum = quote! {
|
||||||
#( #attrs )*
|
#( #attrs )*
|
||||||
#[derive(Clone, Debug, #import_path::exports::serde::Serialize)]
|
#[derive(Clone, Debug, #import_path::exports::serde::Serialize)]
|
||||||
@ -356,18 +376,25 @@ fn expand_content_enum(
|
|||||||
pub enum #ident {
|
pub enum #ident {
|
||||||
#(
|
#(
|
||||||
#[doc = #event_type_str]
|
#[doc = #event_type_str]
|
||||||
#variants(#content),
|
#variant_decls(#content),
|
||||||
)*
|
)*
|
||||||
/// Content of an event not defined by the Matrix specification.
|
/// Content of an event not defined by the Matrix specification.
|
||||||
Custom(#import_path::custom::CustomEventContent),
|
Custom(#import_path::custom::CustomEventContent),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let variant_attrs = variants.iter().map(|v| {
|
||||||
|
let attrs = &v.attrs;
|
||||||
|
quote! { #(#attrs)* }
|
||||||
|
});
|
||||||
|
let variant_arms = variants.iter().map(|v| v.match_arm(quote!(Self)));
|
||||||
|
let variant_ctors = variants.iter().map(|v| v.ctor(quote!(Self)));
|
||||||
|
|
||||||
let event_content_impl = quote! {
|
let event_content_impl = quote! {
|
||||||
impl #import_path::EventContent for #ident {
|
impl #import_path::EventContent for #ident {
|
||||||
fn event_type(&self) -> &str {
|
fn event_type(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
#( Self::#variants(content) => content.event_type(), )*
|
#( #variant_arms(content) => content.event_type(), )*
|
||||||
Self::Custom(content) => content.event_type(),
|
Self::Custom(content) => content.event_type(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,9 +404,9 @@ fn expand_content_enum(
|
|||||||
) -> Result<Self, #import_path::exports::serde_json::Error> {
|
) -> Result<Self, #import_path::exports::serde_json::Error> {
|
||||||
match event_type {
|
match event_type {
|
||||||
#(
|
#(
|
||||||
#event_type_str => {
|
#variant_attrs #event_type_str => {
|
||||||
let content = #content::from_parts(event_type, input)?;
|
let content = #content::from_parts(event_type, input)?;
|
||||||
Ok(Self::#variants(content))
|
Ok(#variant_ctors(content))
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
ev_type => {
|
ev_type => {
|
||||||
@ -407,7 +434,7 @@ fn expand_redact(
|
|||||||
ident: &Ident,
|
ident: &Ident,
|
||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
if let EventKindVariation::Full | EventKindVariation::Sync | EventKindVariation::Stripped = var
|
if let EventKindVariation::Full | EventKindVariation::Sync | EventKindVariation::Stripped = var
|
||||||
@ -440,6 +467,9 @@ fn expand_redact(
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let self_variants = variants.iter().map(|v| v.match_arm(quote!(Self)));
|
||||||
|
let redaction_variants = variants.iter().map(|v| v.ctor(&redaction_enum));
|
||||||
|
|
||||||
let fields = EVENT_FIELDS.iter().map(|(name, has_field)| {
|
let fields = EVENT_FIELDS.iter().map(|(name, has_field)| {
|
||||||
generate_redacted_fields(name, kind, var, *has_field, import_path)
|
generate_redacted_fields(name, kind, var, *has_field, import_path)
|
||||||
});
|
});
|
||||||
@ -456,9 +486,9 @@ fn expand_redact(
|
|||||||
) -> #redaction_enum {
|
) -> #redaction_enum {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#(
|
||||||
Self::#variants(event) => {
|
#self_variants(event) => {
|
||||||
let content = event.content.redact(version);
|
let content = event.content.redact(version);
|
||||||
#redaction_enum::#variants(#redaction_type {
|
#redaction_variants(#redaction_type {
|
||||||
content,
|
content,
|
||||||
#fields
|
#fields
|
||||||
})
|
})
|
||||||
@ -636,7 +666,7 @@ fn marker_traits(kind: &EventKind, import_path: &TokenStream) -> TokenStream {
|
|||||||
fn accessor_methods(
|
fn accessor_methods(
|
||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
use EventKindVariation as V;
|
use EventKindVariation as V;
|
||||||
@ -654,13 +684,14 @@ fn accessor_methods(
|
|||||||
|
|
||||||
let content_enum = kind.to_content_enum();
|
let content_enum = kind.to_content_enum();
|
||||||
|
|
||||||
|
let self_variants: Vec<_> = variants.iter().map(|v| v.match_arm(quote!(Self))).collect();
|
||||||
|
let content_variants: Vec<_> = variants.iter().map(|v| v.ctor(&content_enum)).collect();
|
||||||
|
|
||||||
let content = quote! {
|
let content = quote! {
|
||||||
/// Returns the any content enum for this event.
|
/// Returns the any content enum for this event.
|
||||||
pub fn content(&self) -> #content_enum {
|
pub fn content(&self) -> #content_enum {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#( #self_variants(event) => #content_variants(event.content.clone()), )*
|
||||||
Self::#variants(event) => #content_enum::#variants(event.content.clone()),
|
|
||||||
)*
|
|
||||||
Self::Custom(event) => #content_enum::Custom(event.content.clone()),
|
Self::Custom(event) => #content_enum::Custom(event.content.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -672,8 +703,8 @@ fn accessor_methods(
|
|||||||
pub fn prev_content(&self) -> Option<#content_enum> {
|
pub fn prev_content(&self) -> Option<#content_enum> {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#(
|
||||||
Self::#variants(event) => {
|
#self_variants(event) => {
|
||||||
event.prev_content.as_ref().map(|c| #content_enum::#variants(c.clone()))
|
event.prev_content.as_ref().map(|c| #content_variants(c.clone()))
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
Self::Custom(event) => {
|
Self::Custom(event) => {
|
||||||
@ -720,7 +751,7 @@ fn inner_enum_idents(kind: &EventKind, var: &EventKindVariation) -> (Option<Iden
|
|||||||
fn redacted_accessor_methods(
|
fn redacted_accessor_methods(
|
||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
// this will never fail as it is called in `expand_any_with_deser`.
|
// this will never fail as it is called in `expand_any_with_deser`.
|
||||||
@ -830,22 +861,21 @@ fn generate_accessor(
|
|||||||
kind: &EventKind,
|
kind: &EventKind,
|
||||||
var: &EventKindVariation,
|
var: &EventKindVariation,
|
||||||
is_event_kind: EventKindFn,
|
is_event_kind: EventKindFn,
|
||||||
variants: &[Ident],
|
variants: &[EventEnumVariant],
|
||||||
import_path: &TokenStream,
|
import_path: &TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
if is_event_kind(kind, var) {
|
if is_event_kind(kind, var) {
|
||||||
|
let docs = format!("Returns this event's {} field.", name);
|
||||||
|
let ident = Ident::new(name, Span::call_site());
|
||||||
let field_type = field_return_type(name, var, import_path);
|
let field_type = field_return_type(name, var, import_path);
|
||||||
|
let variants = variants.iter().map(|v| v.match_arm(quote!(Self)));
|
||||||
|
|
||||||
let name = Ident::new(name, Span::call_site());
|
|
||||||
let docs = format!("Returns this events {} field.", name);
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #docs]
|
#[doc = #docs]
|
||||||
pub fn #name(&self) -> &#field_type {
|
pub fn #ident(&self) -> &#field_type {
|
||||||
match self {
|
match self {
|
||||||
#(
|
#( #variants(event) => &event.#ident, )*
|
||||||
Self::#variants(event) => &event.#name,
|
Self::Custom(event) => &event.#ident,
|
||||||
)*
|
|
||||||
Self::Custom(event) => &event.#name,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -875,3 +905,48 @@ fn field_return_type(
|
|||||||
_ => panic!("the `ruma_events_macros::event_enum::EVENT_FIELD` const was changed"),
|
_ => panic!("the `ruma_events_macros::event_enum::EVENT_FIELD` const was changed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EventEnumVariant {
|
||||||
|
pub attrs: Vec<Attribute>,
|
||||||
|
pub ident: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEnumVariant {
|
||||||
|
fn to_tokens<T>(&self, prefix: Option<T>, with_attrs: bool) -> TokenStream
|
||||||
|
where
|
||||||
|
T: ToTokens,
|
||||||
|
{
|
||||||
|
let mut tokens = TokenStream::new();
|
||||||
|
if with_attrs {
|
||||||
|
for attr in &self.attrs {
|
||||||
|
attr.to_tokens(&mut tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(p) = prefix {
|
||||||
|
tokens.extend(quote! { #p :: })
|
||||||
|
}
|
||||||
|
self.ident.to_tokens(&mut tokens);
|
||||||
|
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decl(&self) -> TokenStream {
|
||||||
|
self.to_tokens::<TokenStream>(None, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_arm(&self, prefix: impl ToTokens) -> TokenStream {
|
||||||
|
self.to_tokens(Some(prefix), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ctor(&self, prefix: impl ToTokens) -> TokenStream {
|
||||||
|
self.to_tokens(Some(prefix), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEnumEntry {
|
||||||
|
fn to_variant(&self) -> syn::Result<EventEnumVariant> {
|
||||||
|
let attrs = self.attrs.clone();
|
||||||
|
let ident = to_camel_case(&self.ev_type)?;
|
||||||
|
Ok(EventEnumVariant { attrs, ident })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,8 +5,9 @@ use std::fmt;
|
|||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::format_ident;
|
use quote::format_ident;
|
||||||
use syn::{
|
use syn::{
|
||||||
|
bracketed,
|
||||||
parse::{self, Parse, ParseStream},
|
parse::{self, Parse, ParseStream},
|
||||||
Attribute, Expr, ExprLit, Ident, Lit, LitStr, Token,
|
Attribute, Ident, LitStr, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Custom keywords for the `event_enum!` macro
|
/// Custom keywords for the `event_enum!` macro
|
||||||
@ -193,7 +194,7 @@ pub struct EventEnumInput {
|
|||||||
/// variant in `ruma_events::EventType` for this event (converted to a valid Rust-style type
|
/// variant in `ruma_events::EventType` for this event (converted to a valid Rust-style type
|
||||||
/// name by stripping `m.`, replacing the remaining dots by underscores and then converting from
|
/// name by stripping `m.`, replacing the remaining dots by underscores and then converting from
|
||||||
/// snake_case to CamelCase).
|
/// snake_case to CamelCase).
|
||||||
pub events: Vec<LitStr>,
|
pub events: Vec<EventEnumEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for EventEnumInput {
|
impl Parse for EventEnumInput {
|
||||||
@ -212,20 +213,22 @@ impl Parse for EventEnumInput {
|
|||||||
input.parse::<Token![:]>()?;
|
input.parse::<Token![:]>()?;
|
||||||
|
|
||||||
// an array of event names `["m.room.whatever", ...]`
|
// an array of event names `["m.room.whatever", ...]`
|
||||||
let ev_array = input.parse::<syn::ExprArray>()?;
|
let content;
|
||||||
let events = ev_array
|
bracketed!(content in input);
|
||||||
.elems
|
let events = content.parse_terminated::<_, Token![,]>(EventEnumEntry::parse)?;
|
||||||
.into_iter()
|
let events = events.into_iter().collect();
|
||||||
.map(|item| {
|
|
||||||
if let Expr::Lit(ExprLit { lit: Lit::Str(lit_str), .. }) = item {
|
|
||||||
Ok(lit_str)
|
|
||||||
} else {
|
|
||||||
let msg = "values of field `events` are required to be a string literal";
|
|
||||||
Err(syn::Error::new_spanned(item, msg))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<syn::Result<_>>()?;
|
|
||||||
|
|
||||||
Ok(Self { attrs, name, events })
|
Ok(Self { attrs, name, events })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EventEnumEntry {
|
||||||
|
pub attrs: Vec<Attribute>,
|
||||||
|
pub ev_type: LitStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for EventEnumEntry {
|
||||||
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
Ok(Self { attrs: input.call(Attribute::parse_outer)?, ev_type: input.parse()? })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,10 +5,13 @@ event_enum! {
|
|||||||
kind: Basic,
|
kind: Basic,
|
||||||
events: [
|
events: [
|
||||||
"m.direct",
|
"m.direct",
|
||||||
|
#[cfg(test)]
|
||||||
"m.dummy",
|
"m.dummy",
|
||||||
"m.ignored_user_list",
|
"m.ignored_user_list",
|
||||||
"m.push_rules",
|
"m.push_rules",
|
||||||
"m.room_key",
|
"m.room_key",
|
||||||
|
#[cfg(any())]
|
||||||
|
"m.ruma_test",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user