Specify content traits in attribute, remove derives
This commit is contained in:
parent
6c167fca38
commit
c7c1251f3f
@ -7,11 +7,15 @@ use syn::{
|
|||||||
DeriveInput, Ident, LitStr, Token,
|
DeriveInput, Ident, LitStr, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::event_parse::EventKind;
|
||||||
|
|
||||||
mod kw {
|
mod kw {
|
||||||
// This `content` field is kept when the event is redacted.
|
// This `content` field is kept when the event is redacted.
|
||||||
syn::custom_keyword!(skip_redaction);
|
syn::custom_keyword!(skip_redaction);
|
||||||
// Do not emit any redacted event code.
|
// Do not emit any redacted event code.
|
||||||
syn::custom_keyword!(custom_redacted);
|
syn::custom_keyword!(custom_redacted);
|
||||||
|
// The kind of event content this is.
|
||||||
|
syn::custom_keyword!(kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses attributes for `*EventContent` derives.
|
/// Parses attributes for `*EventContent` derives.
|
||||||
@ -21,6 +25,8 @@ enum EventMeta {
|
|||||||
/// Variant holds the "m.whatever" event type.
|
/// Variant holds the "m.whatever" event type.
|
||||||
Type(LitStr),
|
Type(LitStr),
|
||||||
|
|
||||||
|
Kind(EventKind),
|
||||||
|
|
||||||
/// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
|
/// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
|
||||||
/// redacted.
|
/// redacted.
|
||||||
SkipRedacted,
|
SkipRedacted,
|
||||||
@ -38,6 +44,14 @@ impl EventMeta {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_event_kind(&self) -> Option<&EventKind> {
|
||||||
|
if let Self::Kind(lit) = self {
|
||||||
|
Some(lit)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for EventMeta {
|
impl Parse for EventMeta {
|
||||||
@ -47,6 +61,10 @@ impl Parse for EventMeta {
|
|||||||
let _: Token![type] = input.parse()?;
|
let _: Token![type] = input.parse()?;
|
||||||
let _: Token![=] = input.parse()?;
|
let _: Token![=] = input.parse()?;
|
||||||
input.parse().map(EventMeta::Type)
|
input.parse().map(EventMeta::Type)
|
||||||
|
} else if lookahead.peek(kw::kind) {
|
||||||
|
let _: kw::kind = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
EventKind::parse(input).map(EventMeta::Kind)
|
||||||
} else if lookahead.peek(kw::skip_redaction) {
|
} else if lookahead.peek(kw::skip_redaction) {
|
||||||
let _: kw::skip_redaction = input.parse()?;
|
let _: kw::skip_redaction = input.parse()?;
|
||||||
Ok(EventMeta::SkipRedacted)
|
Ok(EventMeta::SkipRedacted)
|
||||||
@ -69,6 +87,10 @@ impl MetaAttrs {
|
|||||||
fn get_event_type(&self) -> Option<&LitStr> {
|
fn get_event_type(&self) -> Option<&LitStr> {
|
||||||
self.0.iter().find_map(|a| a.get_event_type())
|
self.0.iter().find_map(|a| a.get_event_type())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_event_kinds(&self) -> Vec<&EventKind> {
|
||||||
|
self.0.iter().filter_map(|a| a.get_event_kind()).collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MetaAttrs {
|
impl Parse for MetaAttrs {
|
||||||
@ -81,7 +103,6 @@ impl Parse for MetaAttrs {
|
|||||||
/// Create an `EventContent` implementation for a struct.
|
/// Create an `EventContent` implementation for a struct.
|
||||||
pub fn expand_event_content(
|
pub fn expand_event_content(
|
||||||
input: &DeriveInput,
|
input: &DeriveInput,
|
||||||
emit_redacted: bool,
|
|
||||||
ruma_events: &TokenStream,
|
ruma_events: &TokenStream,
|
||||||
) -> syn::Result<TokenStream> {
|
) -> syn::Result<TokenStream> {
|
||||||
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
|
||||||
@ -99,13 +120,16 @@ pub fn expand_event_content(
|
|||||||
|
|
||||||
let event_type = content_attr.iter().find_map(|a| a.get_event_type()).ok_or_else(|| {
|
let event_type = content_attr.iter().find_map(|a| a.get_event_type()).ok_or_else(|| {
|
||||||
let msg = "no event type attribute found, \
|
let msg = "no event type attribute found, \
|
||||||
add `#[ruma_event(type = \"any.room.event\")]` \
|
add `#[ruma_event(type = \"any.room.event\", kind = Kind)]` \
|
||||||
below the event content derive";
|
below the event content derive";
|
||||||
|
|
||||||
syn::Error::new(Span::call_site(), msg)
|
syn::Error::new(Span::call_site(), msg)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let redacted = if emit_redacted && needs_redacted(&content_attr) {
|
let content_derives =
|
||||||
|
content_attr.iter().flat_map(|args| args.get_event_kinds()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let redacted = if needs_redacted(&content_attr) {
|
||||||
let doc = format!("The payload for a redacted `{}`", ident);
|
let doc = format!("The payload for a redacted `{}`", ident);
|
||||||
let redacted_ident = format_ident!("Redacted{}", ident);
|
let redacted_ident = format_ident!("Redacted{}", ident);
|
||||||
let kept_redacted_fields = if let syn::Data::Struct(syn::DataStruct {
|
let kept_redacted_fields = if let syn::Data::Struct(syn::DataStruct {
|
||||||
@ -182,6 +206,21 @@ pub fn expand_event_content(
|
|||||||
let redacted_event_content =
|
let redacted_event_content =
|
||||||
generate_event_content_impl(&redacted_ident, event_type, ruma_events);
|
generate_event_content_impl(&redacted_ident, event_type, ruma_events);
|
||||||
|
|
||||||
|
let redacted_event_content_derive = content_derives
|
||||||
|
.iter()
|
||||||
|
.map(|kind| match kind {
|
||||||
|
EventKind::Message => quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #ruma_events::RedactedMessageEventContent for #redacted_ident {}
|
||||||
|
},
|
||||||
|
EventKind::State => quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #ruma_events::RedactedStateEventContent for #redacted_ident {}
|
||||||
|
},
|
||||||
|
_ => TokenStream::new(),
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
// this is the non redacted event content's impl
|
// this is the non redacted event content's impl
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
@ -220,106 +259,68 @@ pub fn expand_event_content(
|
|||||||
#has_deserialize_fields
|
#has_deserialize_fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#redacted_event_content_derive
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let event_content_derive =
|
||||||
|
generate_event_content_derives(&content_derives, ident, ruma_events)?;
|
||||||
|
|
||||||
let event_content = generate_event_content_impl(ident, event_type, ruma_events);
|
let event_content = generate_event_content_impl(ident, event_type, ruma_events);
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#event_content
|
#event_content
|
||||||
|
|
||||||
|
#event_content_derive
|
||||||
|
|
||||||
#redacted
|
#redacted
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `EphemeralRoomEventContent` implementation for a struct
|
fn generate_event_content_derives(
|
||||||
pub fn expand_ephemeral_room_event_content(
|
content_attr: &[&EventKind],
|
||||||
input: &DeriveInput,
|
ident: &Ident,
|
||||||
ruma_events: &TokenStream,
|
ruma_events: &TokenStream,
|
||||||
) -> syn::Result<TokenStream> {
|
) -> syn::Result<TokenStream> {
|
||||||
let ident = input.ident.clone();
|
let msg = "valid event kinds are GlobalAccountData, RoomAccountData, \
|
||||||
let event_content_impl = expand_event_content(input, false, ruma_events)?;
|
EphemeralRoom, Message, State, ToDevice";
|
||||||
|
content_attr
|
||||||
Ok(quote! {
|
.iter()
|
||||||
#event_content_impl
|
.map(|kind| {
|
||||||
|
Ok(match kind {
|
||||||
|
EventKind::GlobalAccountData => quote! {
|
||||||
|
// TODO: will this be it's own trait at some point?
|
||||||
|
},
|
||||||
|
EventKind::RoomAccountData => quote! {
|
||||||
|
// TODO: will this be it's own trait at some point?
|
||||||
|
},
|
||||||
|
EventKind::Ephemeral => quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::EphemeralRoomEventContent for #ident {}
|
impl #ruma_events::EphemeralRoomEventContent for #ident {}
|
||||||
})
|
},
|
||||||
}
|
EventKind::Message => quote! {
|
||||||
|
|
||||||
/// Create a `RoomEventContent` implementation for a struct.
|
|
||||||
pub fn expand_room_event_content(
|
|
||||||
input: &DeriveInput,
|
|
||||||
ruma_events: &TokenStream,
|
|
||||||
) -> syn::Result<TokenStream> {
|
|
||||||
let ident = input.ident.clone();
|
|
||||||
let event_content_impl = expand_event_content(input, true, ruma_events)?;
|
|
||||||
|
|
||||||
Ok(quote! {
|
|
||||||
#event_content_impl
|
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::RoomEventContent for #ident {}
|
impl #ruma_events::RoomEventContent for #ident {}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a `MessageEventContent` implementation for a struct
|
|
||||||
pub fn expand_message_event_content(
|
|
||||||
input: &DeriveInput,
|
|
||||||
ruma_events: &TokenStream,
|
|
||||||
) -> syn::Result<TokenStream> {
|
|
||||||
let ident = input.ident.clone();
|
|
||||||
let room_ev_content = expand_room_event_content(input, ruma_events)?;
|
|
||||||
|
|
||||||
let redacted_marker_trait = if needs_redacted_from_input(input) {
|
|
||||||
let ident = format_ident!("Redacted{}", &ident);
|
|
||||||
quote! {
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #ruma_events::RedactedMessageEventContent for #ident {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TokenStream::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(quote! {
|
|
||||||
#room_ev_content
|
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::MessageEventContent for #ident {}
|
impl #ruma_events::MessageEventContent for #ident {}
|
||||||
|
},
|
||||||
#redacted_marker_trait
|
EventKind::State => quote! {
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a `StateEventContent` implementation for a struct
|
|
||||||
pub fn expand_state_event_content(
|
|
||||||
input: &DeriveInput,
|
|
||||||
ruma_events: &TokenStream,
|
|
||||||
) -> syn::Result<TokenStream> {
|
|
||||||
let ident = input.ident.clone();
|
|
||||||
let room_ev_content = expand_room_event_content(input, ruma_events)?;
|
|
||||||
|
|
||||||
let redacted_marker_trait = if needs_redacted_from_input(input) {
|
|
||||||
let ident = format_ident!("Redacted{}", input.ident);
|
|
||||||
quote! {
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::RedactedStateEventContent for #ident {}
|
impl #ruma_events::RoomEventContent for #ident {}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TokenStream::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(quote! {
|
|
||||||
#room_ev_content
|
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #ruma_events::StateEventContent for #ident {}
|
impl #ruma_events::StateEventContent for #ident {}
|
||||||
|
},
|
||||||
#redacted_marker_trait
|
EventKind::ToDevice => quote! {
|
||||||
|
// TODO: will this be it's own trait at some point?
|
||||||
|
},
|
||||||
|
EventKind::Redaction => return Err(syn::Error::new(ident.span(), msg)),
|
||||||
|
EventKind::Presence => return Err(syn::Error::new(ident.span(), msg)),
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_event_content_impl(
|
fn generate_event_content_impl(
|
||||||
@ -359,7 +360,3 @@ fn needs_redacted(input: &[MetaAttrs]) -> bool {
|
|||||||
// needs a redacted struct generated.
|
// needs a redacted struct generated.
|
||||||
!input.iter().any(|a| a.is_custom())
|
!input.iter().any(|a| a.is_custom())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_redacted_from_input(input: &DeriveInput) -> bool {
|
|
||||||
!input.attrs.iter().flat_map(|a| a.parse_args::<MetaAttrs>().ok()).any(|a| a.is_custom())
|
|
||||||
}
|
|
||||||
|
@ -15,12 +15,7 @@ use quote::quote;
|
|||||||
use syn::{parse_macro_input, DeriveInput, Ident};
|
use syn::{parse_macro_input, DeriveInput, Ident};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
event::expand_event,
|
event::expand_event, event_content::expand_event_content, event_enum::expand_event_enum,
|
||||||
event_content::{
|
|
||||||
expand_ephemeral_room_event_content, expand_event_content, expand_message_event_content,
|
|
||||||
expand_room_event_content, expand_state_event_content,
|
|
||||||
},
|
|
||||||
event_enum::expand_event_enum,
|
|
||||||
event_parse::EventEnumInput,
|
event_parse::EventEnumInput,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,53 +53,7 @@ pub fn derive_event_content(input: TokenStream) -> TokenStream {
|
|||||||
let ruma_events = import_ruma_events();
|
let ruma_events = import_ruma_events();
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
expand_event_content(&input, true, &ruma_events)
|
expand_event_content(&input, &ruma_events).unwrap_or_else(syn::Error::into_compile_error).into()
|
||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates an implementation of `ruma_events::RoomEventContent` and it's super traits.
|
|
||||||
#[proc_macro_derive(RoomEventContent, attributes(ruma_event))]
|
|
||||||
pub fn derive_room_event_content(input: TokenStream) -> TokenStream {
|
|
||||||
let ruma_events = import_ruma_events();
|
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
expand_room_event_content(&input, &ruma_events)
|
|
||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates an implementation of `ruma_events::MessageEventContent` and it's super traits.
|
|
||||||
#[proc_macro_derive(MessageEventContent, attributes(ruma_event))]
|
|
||||||
pub fn derive_message_event_content(input: TokenStream) -> TokenStream {
|
|
||||||
let ruma_events = import_ruma_events();
|
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
expand_message_event_content(&input, &ruma_events)
|
|
||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates an implementation of `ruma_events::StateEventContent` and it's super traits.
|
|
||||||
#[proc_macro_derive(StateEventContent, attributes(ruma_event))]
|
|
||||||
pub fn derive_state_event_content(input: TokenStream) -> TokenStream {
|
|
||||||
let ruma_events = import_ruma_events();
|
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
expand_state_event_content(&input, &ruma_events)
|
|
||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates an implementation of `ruma_events::EphemeralRoomEventContent` and it's super traits.
|
|
||||||
#[proc_macro_derive(EphemeralRoomEventContent, attributes(ruma_event))]
|
|
||||||
pub fn derive_ephemeral_room_event_content(input: TokenStream) -> TokenStream {
|
|
||||||
let ruma_events = import_ruma_events();
|
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
expand_ephemeral_room_event_content(&input, &ruma_events)
|
|
||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates implementations needed to serialize and deserialize Matrix events.
|
/// Generates implementations needed to serialize and deserialize Matrix events.
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
//! would work.
|
//! would work.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use ruma_events::{macros::MessageEventContent, SyncMessageEvent};
|
//! use ruma_events::{macros::EventContent, SyncMessageEvent};
|
||||||
//! use ruma_identifiers::EventId;
|
//! use ruma_identifiers::EventId;
|
||||||
//! use serde::{Deserialize, Serialize};
|
//! use serde::{Deserialize, Serialize};
|
||||||
//!
|
//!
|
||||||
@ -58,8 +58,8 @@
|
|||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! /// The payload for our reaction event.
|
//! /// The payload for our reaction event.
|
||||||
//! #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
//! #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
|
||||||
//! #[ruma_event(type = "m.reaction")]
|
//! #[ruma_event(type = "m.reaction", kind = Message)]
|
||||||
//! pub struct ReactionEventContent {
|
//! pub struct ReactionEventContent {
|
||||||
//! #[serde(rename = "m.relates_to")]
|
//! #[serde(rename = "m.relates_to")]
|
||||||
//! pub relates_to: RelatesTo,
|
//! pub relates_to: RelatesTo,
|
||||||
@ -151,9 +151,7 @@ pub mod exports {
|
|||||||
|
|
||||||
/// Re-export of all the derives needed to create your own event types.
|
/// Re-export of all the derives needed to create your own event types.
|
||||||
pub mod macros {
|
pub mod macros {
|
||||||
pub use ruma_events_macros::{
|
pub use ruma_events_macros::{Event, EventContent};
|
||||||
EphemeralRoomEventContent, Event, MessageEventContent, StateEventContent,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user