Implement Serialize and Event.
This commit is contained in:
parent
3b65905784
commit
78e25552fb
58
src/gen.rs
58
src/gen.rs
@ -6,7 +6,7 @@ use syn::{
|
|||||||
parse::{self, Parse, ParseStream},
|
parse::{self, Parse, ParseStream},
|
||||||
parse_quote,
|
parse_quote,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
Attribute, Field, Ident, Token,
|
Attribute, Field, Ident, Path, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parse::{Content, EventKind, RumaEventInput};
|
use crate::parse::{Content, EventKind, RumaEventInput};
|
||||||
@ -22,6 +22,10 @@ pub struct RumaEvent {
|
|||||||
/// The name of the type of the event's `content` field.
|
/// The name of the type of the event's `content` field.
|
||||||
content_name: Ident,
|
content_name: Ident,
|
||||||
|
|
||||||
|
/// The variant of `ruma_events::EventType` for this event, determined by the `event_type`
|
||||||
|
/// field.
|
||||||
|
event_type: Path,
|
||||||
|
|
||||||
/// Struct fields of the event.
|
/// Struct fields of the event.
|
||||||
fields: Vec<Field>,
|
fields: Vec<Field>,
|
||||||
|
|
||||||
@ -58,6 +62,7 @@ impl From<RumaEventInput> for RumaEvent {
|
|||||||
attrs: input.attrs,
|
attrs: input.attrs,
|
||||||
content: input.content,
|
content: input.content,
|
||||||
content_name,
|
content_name,
|
||||||
|
event_type: input.event_type,
|
||||||
fields,
|
fields,
|
||||||
kind,
|
kind,
|
||||||
name,
|
name,
|
||||||
@ -69,18 +74,17 @@ impl ToTokens for RumaEvent {
|
|||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
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 name_str = format!("{}", 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) => {
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #content_docstring]
|
#[doc = #content_docstring]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, serde::Serialize)]
|
||||||
pub struct #content_name {
|
pub struct #content_name {
|
||||||
#(#fields),*
|
#(#fields),*
|
||||||
}
|
}
|
||||||
@ -110,6 +114,21 @@ impl ToTokens for RumaEvent {
|
|||||||
Content::Typedef(_) => TokenStream::new(),
|
Content::Typedef(_) => TokenStream::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let field_count = event_fields.len() + 1; // + 1 because of manually adding `event_type`
|
||||||
|
|
||||||
|
let mut serialize_field_calls: Vec<TokenStream> = Vec::with_capacity(event_fields.len());
|
||||||
|
|
||||||
|
for field in event_fields {
|
||||||
|
let ident = field.ident.clone().unwrap();
|
||||||
|
let ident_str = format!("{}", ident);
|
||||||
|
|
||||||
|
let token_stream = quote! {
|
||||||
|
state.serialize_field(#ident_str, &self.#ident)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_field_calls.push(token_stream);
|
||||||
|
}
|
||||||
|
|
||||||
let output = quote!(
|
let output = quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -119,6 +138,35 @@ impl ToTokens for RumaEvent {
|
|||||||
|
|
||||||
#content
|
#content
|
||||||
|
|
||||||
|
use serde::ser::SerializeStruct as _;
|
||||||
|
|
||||||
|
impl serde::Serialize for #name {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer
|
||||||
|
{
|
||||||
|
let mut state = serializer.serialize_struct(#name_str, #field_count)?;
|
||||||
|
|
||||||
|
#(#serialize_field_calls)*
|
||||||
|
state.serialize_field("type", &self.event_type())?;
|
||||||
|
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::Event for #name {
|
||||||
|
/// The type of the event.
|
||||||
|
const EVENT_TYPE: crate::EventType = #event_type;
|
||||||
|
|
||||||
|
/// The type of this event's `content` field.
|
||||||
|
type Content = #content_name;
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
fn content(&self) -> &Self::Content {
|
||||||
|
&self.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// "Raw" versions of the event and its content which implement `serde::Deserialize`.
|
/// "Raw" versions of the event and its content which implement `serde::Deserialize`.
|
||||||
mod raw {
|
mod raw {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
clippy::wrong_pub_self_convention,
|
clippy::wrong_pub_self_convention,
|
||||||
clippy::wrong_self_convention
|
clippy::wrong_self_convention
|
||||||
)]
|
)]
|
||||||
|
#![recursion_limit = "128"]
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ mod parse;
|
|||||||
/// The most common form of event is a struct with all the standard fields for an event of its
|
/// The most common form of event is a struct with all the standard fields for an event of its
|
||||||
/// kind and a struct for its `content` field:
|
/// kind and a struct for its `content` field:
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```ignore
|
||||||
/// # pub mod example {
|
/// # pub mod example {
|
||||||
/// # use ruma_events_macros::ruma_event;
|
/// # use ruma_events_macros::ruma_event;
|
||||||
/// ruma_event! {
|
/// ruma_event! {
|
||||||
@ -72,7 +73,7 @@ mod parse;
|
|||||||
/// Occasionally an event will have non-standard fields at its top level (outside the `content`
|
/// Occasionally an event will have non-standard fields at its top level (outside the `content`
|
||||||
/// field). These extra fields are declared in block labeled with `fields`:
|
/// field). These extra fields are declared in block labeled with `fields`:
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```ignore
|
||||||
/// # pub mod example {
|
/// # pub mod example {
|
||||||
/// # use ruma_events_macros::ruma_event;
|
/// # use ruma_events_macros::ruma_event;
|
||||||
/// ruma_event! {
|
/// ruma_event! {
|
||||||
@ -96,7 +97,7 @@ mod parse;
|
|||||||
/// Sometimes the type of the `content` should be a type alias rather than a struct or enum. This
|
/// Sometimes the type of the `content` should be a type alias rather than a struct or enum. This
|
||||||
/// is designated with `content_type_alias`:
|
/// is designated with `content_type_alias`:
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```ignore
|
||||||
/// # pub mod example {
|
/// # pub mod example {
|
||||||
/// # use ruma_events_macros::ruma_event;
|
/// # use ruma_events_macros::ruma_event;
|
||||||
/// ruma_event! {
|
/// ruma_event! {
|
||||||
|
@ -1,5 +1,44 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// The type of an event.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
pub enum EventType {
|
||||||
|
/// m.direct
|
||||||
|
Direct,
|
||||||
|
|
||||||
|
/// m.room.aliases
|
||||||
|
RoomAliases,
|
||||||
|
|
||||||
|
/// m.room.redaction
|
||||||
|
RoomRedaction,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A basic event.
|
||||||
|
pub trait Event
|
||||||
|
where
|
||||||
|
Self: Debug + Serialize,
|
||||||
|
{
|
||||||
|
/// The type of the event.
|
||||||
|
const EVENT_TYPE: EventType;
|
||||||
|
|
||||||
|
/// The type of this event's `content` field.
|
||||||
|
type Content: Debug + Serialize;
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
fn content(&self) -> &Self::Content;
|
||||||
|
|
||||||
|
/// The type of the event.
|
||||||
|
fn event_type(&self) -> EventType {
|
||||||
|
Self::EVENT_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// See note about wrapping macro expansion in a module from `src/lib.rs`
|
// See note about wrapping macro expansion in a module from `src/lib.rs`
|
||||||
pub mod common_case {
|
pub mod common_case {
|
||||||
|
use super::Event;
|
||||||
|
|
||||||
use ruma_events_macros::ruma_event;
|
use ruma_events_macros::ruma_event;
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
@ -16,6 +55,8 @@ pub mod common_case {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod extra_fields {
|
pub mod extra_fields {
|
||||||
|
use super::Event;
|
||||||
|
|
||||||
use ruma_events_macros::ruma_event;
|
use ruma_events_macros::ruma_event;
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
@ -36,6 +77,8 @@ pub mod extra_fields {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod type_alias {
|
pub mod type_alias {
|
||||||
|
use super::Event;
|
||||||
|
|
||||||
use ruma_events_macros::ruma_event;
|
use ruma_events_macros::ruma_event;
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user