Implement generation of structs.
This commit is contained in:
parent
48d6ef7ead
commit
2f54ee3e32
@ -19,3 +19,9 @@ proc-macro2 = "0.4.30"
|
|||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
ruma-identifiers = "0.13.1"
|
||||||
|
serde_json = "1.0.39"
|
||||||
|
js_int = "0.1.0"
|
||||||
|
serde = "1.0.92"
|
||||||
|
117
src/gen.rs
117
src/gen.rs
@ -1,25 +1,126 @@
|
|||||||
//! Details of generating code for the `ruma_event` procedural macro.
|
//! Details of generating code for the `ruma_event` procedural macro.
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
|
use syn::{Attribute, Field, Ident};
|
||||||
|
|
||||||
use crate::parse::RumaEventInput;
|
use crate::parse::{EventKind, RumaEventInput};
|
||||||
|
|
||||||
/// The result of processing the `ruma_event` macro, ready for output back to source code.
|
/// The result of processing the `ruma_event` macro, ready for output back to source code.
|
||||||
pub struct RumaEvent;
|
pub struct RumaEvent {
|
||||||
|
/// Outer attributes on the field, such as a docstring.
|
||||||
|
attrs: Vec<Attribute>,
|
||||||
|
|
||||||
|
/// The name of the type of the event's `content` field.
|
||||||
|
content_name: Ident,
|
||||||
|
|
||||||
|
/// Additional named struct fields in the top level event struct.
|
||||||
|
fields: Option<Vec<Field>>,
|
||||||
|
|
||||||
|
/// The kind of event.
|
||||||
|
kind: EventKind,
|
||||||
|
|
||||||
|
/// The name of the event.
|
||||||
|
name: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RumaEvent {
|
||||||
|
/// Fills in the event's struct definition with fields common to all basic events.
|
||||||
|
fn common_basic_event_fields(&self) -> TokenStream {
|
||||||
|
let content_name = &self.content_name;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
/// The event's content.
|
||||||
|
pub content: #content_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fills in the event's struct definition with fields common to all room events.
|
||||||
|
fn common_room_event_fields(&self) -> TokenStream {
|
||||||
|
let common_basic_event_fields = self.common_basic_event_fields();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#common_basic_event_fields
|
||||||
|
|
||||||
|
/// The unique identifier for the event.
|
||||||
|
pub event_id: ruma_identifiers::EventId,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this
|
||||||
|
/// event was sent.
|
||||||
|
pub origin_server_ts: js_int::UInt,
|
||||||
|
|
||||||
|
/// The unique identifier for the room associated with this event.
|
||||||
|
pub room_id: Option<ruma_identifiers::RoomId>,
|
||||||
|
|
||||||
|
/// Additional key-value pairs not signed by the homeserver.
|
||||||
|
pub unsigned: Option<serde_json::Value>,
|
||||||
|
|
||||||
|
/// The unique identifier for the user who sent this event.
|
||||||
|
pub sender: ruma_identifiers::UserId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fills in the event's struct definition with fields common to all state events.
|
||||||
|
fn common_state_event_fields(&self) -> TokenStream {
|
||||||
|
let content_name = &self.content_name;
|
||||||
|
let common_room_event_fields = self.common_room_event_fields();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#common_room_event_fields
|
||||||
|
|
||||||
|
/// The previous content for this state key, if any.
|
||||||
|
pub prev_content: Option<#content_name>,
|
||||||
|
|
||||||
|
/// A key that determines which piece of room state the event represents.
|
||||||
|
pub state_key: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<RumaEventInput> for RumaEvent {
|
impl From<RumaEventInput> for RumaEvent {
|
||||||
// TODO: Provide an actual impl for this.
|
fn from(input: RumaEventInput) -> Self {
|
||||||
fn from(_input: RumaEventInput) -> Self {
|
Self {
|
||||||
Self
|
attrs: input.attrs,
|
||||||
|
content_name: Ident::new(&format!("{}Content", input.name), Span::call_site()),
|
||||||
|
fields: input.fields,
|
||||||
|
kind: input.kind,
|
||||||
|
name: input.name,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for RumaEvent {
|
impl ToTokens for RumaEvent {
|
||||||
// TODO: Provide an actual impl for this.
|
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let attrs = &self.attrs;
|
||||||
|
let content_name = &self.content_name;
|
||||||
|
|
||||||
|
let common_event_fields = match self.kind {
|
||||||
|
EventKind::Event => self.common_basic_event_fields(),
|
||||||
|
EventKind::RoomEvent => self.common_room_event_fields(),
|
||||||
|
EventKind::StateEvent => self.common_state_event_fields(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let event_fields = match &self.fields {
|
||||||
|
Some(fields) => fields.clone(),
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = &self.name;
|
||||||
|
|
||||||
|
let content_docstring = format!("The payload for `{}`.", name);
|
||||||
|
|
||||||
let output = quote!(
|
let output = quote!(
|
||||||
pub struct Foo {}
|
#(#attrs),*
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct #name {
|
||||||
|
#common_event_fields
|
||||||
|
#(#event_fields),*
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = #content_docstring]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct #content_name {
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
output.to_tokens(tokens);
|
output.to_tokens(tokens);
|
||||||
|
@ -62,7 +62,7 @@ mod parse;
|
|||||||
/// event_type: RoomAliases,
|
/// event_type: RoomAliases,
|
||||||
/// content: {
|
/// content: {
|
||||||
/// /// A list of room aliases.
|
/// /// A list of room aliases.
|
||||||
/// pub aliases: Vec<RoomAliasId>,
|
/// pub aliases: Vec<ruma_identifiers::RoomAliasId>,
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
@ -82,7 +82,7 @@ mod parse;
|
|||||||
/// event_type: RoomRedaction,
|
/// event_type: RoomRedaction,
|
||||||
/// fields: {
|
/// fields: {
|
||||||
/// /// The ID of the event that was redacted.
|
/// /// The ID of the event that was redacted.
|
||||||
/// pub redacts: EventId
|
/// pub redacts: ruma_identifiers::EventId
|
||||||
/// },
|
/// },
|
||||||
/// content: {
|
/// content: {
|
||||||
/// /// The reason for the redaction, if any.
|
/// /// The reason for the redaction, if any.
|
||||||
@ -109,7 +109,7 @@ mod parse;
|
|||||||
/// ///
|
/// ///
|
||||||
/// /// A mapping of `UserId`'s to a collection of `RoomId`'s which are considered
|
/// /// A mapping of `UserId`'s to a collection of `RoomId`'s which are considered
|
||||||
/// /// *direct* for that particular user.
|
/// /// *direct* for that particular user.
|
||||||
/// HashMap<UserId, Vec<RoomId>>
|
/// HashMap<UserId, Vec<ruma_identifiers::RoomId>>
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -16,7 +16,7 @@ pub struct RumaEventInput {
|
|||||||
/// Outer attributes on the field, such as a docstring.
|
/// Outer attributes on the field, such as a docstring.
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
|
|
||||||
/// The name of the field.
|
/// The name of the event.
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
|
|
||||||
/// The kind of event, determiend by the `kind` field.
|
/// The kind of event, determiend by the `kind` field.
|
||||||
|
47
tests/ruma_events_macros.rs
Normal file
47
tests/ruma_events_macros.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// See note about wrapping macro expansion in a module from `src/lib.rs`
|
||||||
|
pub mod tests {
|
||||||
|
use ruma_events_macros::ruma_event;
|
||||||
|
|
||||||
|
ruma_event! {
|
||||||
|
/// Informs the room about what room aliases it has been given.
|
||||||
|
AliasesEvent {
|
||||||
|
kind: StateEvent,
|
||||||
|
event_type: RoomAliases,
|
||||||
|
content: {
|
||||||
|
/// A list of room aliases.
|
||||||
|
pub aliases: Vec<ruma_identifiers::RoomAliasId>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ruma_event! {
|
||||||
|
/// A redaction of an event.
|
||||||
|
RedactionEvent {
|
||||||
|
kind: RoomEvent,
|
||||||
|
event_type: RoomRedaction,
|
||||||
|
fields: {
|
||||||
|
/// The ID of the event that was redacted.
|
||||||
|
pub redacts: ruma_identifiers::EventId
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
/// The reason for the redaction, if any.
|
||||||
|
pub reason: Option<String>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ruma_event! {
|
||||||
|
/// Informs the client about the rooms that are considered direct by a user.
|
||||||
|
DirectEvent {
|
||||||
|
kind: Event,
|
||||||
|
event_type: Direct,
|
||||||
|
content_type_alias: {
|
||||||
|
/// The payload of a `DirectEvent`.
|
||||||
|
///
|
||||||
|
/// A mapping of `UserId`'s to a collection of `RoomId`'s which are considered
|
||||||
|
/// *direct* for that particular user.
|
||||||
|
std::collections::HashMap<ruma_identifiers::UserId, Vec<ruma_identifiers::RoomId>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user