Add derive macro for StateEventContent
This commit is contained in:
parent
27a9b36499
commit
ef6e2e7023
@ -80,15 +80,25 @@ impl ToTokens for RumaEvent {
|
|||||||
// let attrs = &self.attrs;
|
// let attrs = &self.attrs;
|
||||||
let content_name = &self.content_name;
|
let content_name = &self.content_name;
|
||||||
// let event_fields = &self.fields;
|
// let event_fields = &self.fields;
|
||||||
|
let event_type = &self.event_type;
|
||||||
|
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let content_docstring = format!("The payload for `{}`.", name);
|
let content_docstring = format!("The payload for `{}`.", name);
|
||||||
|
|
||||||
let content = match &self.content {
|
let content = match &self.content {
|
||||||
Content::Struct(fields) => {
|
Content::Struct(fields) => {
|
||||||
|
// TODO this will all be removed so this is only temp
|
||||||
|
let event_content_derive = match self.kind {
|
||||||
|
EventKind::StateEvent => quote! {
|
||||||
|
#[derive(::ruma_events_macros::StateEventContent)]
|
||||||
|
#[ruma_event(type = #event_type)]
|
||||||
|
},
|
||||||
|
EventKind::RoomEvent | EventKind::Event => TokenStream::new(),
|
||||||
|
};
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #content_docstring]
|
#[doc = #content_docstring]
|
||||||
#[derive(Clone, Debug, serde::Serialize, ::ruma_events_macros::FromRaw)]
|
#[derive(Clone, Debug, ::serde::Serialize, ::ruma_events_macros::FromRaw)]
|
||||||
|
#event_content_derive
|
||||||
pub struct #content_name {
|
pub struct #content_name {
|
||||||
#(#fields),*
|
#(#fields),*
|
||||||
}
|
}
|
||||||
@ -105,8 +115,6 @@ impl ToTokens for RumaEvent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// let event_type_name = self.event_type.value();
|
|
||||||
|
|
||||||
content.to_tokens(tokens);
|
content.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,14 @@ use proc_macro::TokenStream;
|
|||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::{parse_macro_input, DeriveInput};
|
use syn::{parse_macro_input, DeriveInput};
|
||||||
|
|
||||||
use self::{from_raw::expand_from_raw, gen::RumaEvent, parse::RumaEventInput};
|
use self::{
|
||||||
|
from_raw::expand_from_raw, gen::RumaEvent, parse::RumaEventInput, state::expand_state_event,
|
||||||
|
};
|
||||||
|
|
||||||
mod from_raw;
|
mod from_raw;
|
||||||
mod gen;
|
mod gen;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
mod state;
|
||||||
|
|
||||||
// A note about the `example` modules that appears in doctests:
|
// A note about the `example` modules that appears in doctests:
|
||||||
//
|
//
|
||||||
@ -145,3 +148,12 @@ pub fn derive_from_raw(input: TokenStream) -> TokenStream {
|
|||||||
.unwrap_or_else(|err| err.to_compile_error())
|
.unwrap_or_else(|err| err.to_compile_error())
|
||||||
.into()
|
.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 input = parse_macro_input!(input as DeriveInput);
|
||||||
|
expand_state_event(input)
|
||||||
|
.unwrap_or_else(|err| err.to_compile_error())
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ pub struct RumaEventInput {
|
|||||||
/// The name of the event.
|
/// The name of the event.
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
|
|
||||||
/// The kind of event, determiend by the `kind` field.
|
/// The kind of event, determined by the `kind` field.
|
||||||
pub kind: EventKind,
|
pub kind: EventKind,
|
||||||
|
|
||||||
/// The value for the `type` field in the JSON representation of this event. There needs to be a
|
/// The value for the `type` field in the JSON representation of this event. There needs to be a
|
||||||
|
78
ruma-events-macros/src/state.rs
Normal file
78
ruma-events-macros/src/state.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//! Implementation of the `StateEventContent` derive macro
|
||||||
|
|
||||||
|
use proc_macro2::{Span, TokenStream};
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{
|
||||||
|
parse::{Parse, ParseStream},
|
||||||
|
DeriveInput, LitStr, Token,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parses attributes for `*EventContent` derives.
|
||||||
|
///
|
||||||
|
/// `#[ruma_event(type = "m.room.alias")]`
|
||||||
|
enum EventMeta {
|
||||||
|
/// Variant holds the "m.room.whatever" event type.
|
||||||
|
Type(LitStr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for EventMeta {
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
input.parse::<Token![type]>()?;
|
||||||
|
input.parse::<Token![=]>()?;
|
||||||
|
Ok(EventMeta::Type(input.parse::<LitStr>()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a `StateEventContent` implementation for a struct
|
||||||
|
pub fn expand_state_event(input: DeriveInput) -> syn::Result<TokenStream> {
|
||||||
|
let ident = &input.ident;
|
||||||
|
|
||||||
|
let event_type_attr = input
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.find(|attr| attr.path.is_ident("ruma_event"))
|
||||||
|
.ok_or_else(|| {
|
||||||
|
let msg = "no event type attribute found, \
|
||||||
|
add `#[ruma_events(type = \"any.room.event\")]` \
|
||||||
|
below the event content derive";
|
||||||
|
|
||||||
|
syn::Error::new(Span::call_site(), msg)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let event_type = {
|
||||||
|
let event_meta = event_type_attr.parse_args::<EventMeta>()?;
|
||||||
|
let EventMeta::Type(lit) = event_meta;
|
||||||
|
lit
|
||||||
|
};
|
||||||
|
|
||||||
|
let event_content_impl = quote! {
|
||||||
|
impl ::ruma_events::EventContent for #ident {
|
||||||
|
fn event_type(&self) -> &str {
|
||||||
|
#event_type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_parts(
|
||||||
|
ev_type: &str,
|
||||||
|
content: Box<::serde_json::value::RawValue>
|
||||||
|
) -> Result<Self, ::ruma_events::InvalidEvent> {
|
||||||
|
if ev_type != #event_type {
|
||||||
|
return Err(::ruma_events::InvalidEvent {
|
||||||
|
kind: ::ruma_events::error::InvalidEventKind::Deserialization,
|
||||||
|
message: format!("expected `{}` found {}", #event_type, ev_type),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let ev_json = ::ruma_events::EventJson::from(content);
|
||||||
|
ev_json.deserialize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#event_content_impl
|
||||||
|
|
||||||
|
impl ::ruma_events::RoomEventContent for #ident { }
|
||||||
|
|
||||||
|
impl ::ruma_events::StateEventContent for #ident { }
|
||||||
|
})
|
||||||
|
}
|
@ -20,25 +20,3 @@ ruma_event! {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventContent for AliasesEventContent {
|
|
||||||
fn event_type(&self) -> &str {
|
|
||||||
"m.room.aliases"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent> {
|
|
||||||
if event_type != "m.room.aliases" {
|
|
||||||
return Err(InvalidEvent {
|
|
||||||
kind: InvalidEventKind::Deserialization,
|
|
||||||
message: format!("expected `m.room.aliases` found {}", event_type),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let ev_json = EventJson::from(content);
|
|
||||||
ev_json.deserialize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RoomEventContent for AliasesEventContent {}
|
|
||||||
|
|
||||||
impl StateEventContent for AliasesEventContent {}
|
|
||||||
|
@ -27,25 +27,3 @@ ruma_event! {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventContent for AvatarEventContent {
|
|
||||||
fn event_type(&self) -> &str {
|
|
||||||
"m.room.avatar"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, InvalidEvent> {
|
|
||||||
if event_type != "m.room.avatar" {
|
|
||||||
return Err(InvalidEvent {
|
|
||||||
kind: InvalidEventKind::Deserialization,
|
|
||||||
message: format!("expected `m.room.avatar` found {}", event_type),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let ev_json = EventJson::from(content);
|
|
||||||
ev_json.deserialize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RoomEventContent for AvatarEventContent {}
|
|
||||||
|
|
||||||
impl StateEventContent for AvatarEventContent {}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user