Derive Serialize in ruma_events!, use json EventType string for event_type field

Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
This commit is contained in:
Ragotzy.devin 2020-03-24 09:25:50 -04:00 committed by GitHub
parent 14df832005
commit 8ea971b082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 67 additions and 80 deletions

View File

@ -1,5 +1,4 @@
//! Details of generating code for the `ruma_event` procedural macro.
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::{
@ -7,7 +6,7 @@ use syn::{
parse_quote,
punctuated::Punctuated,
spanned::Spanned,
Attribute, Field, Ident, Path, Token, Type,
Attribute, Field, Ident, LitStr, Token, Type,
};
use crate::parse::{Content, EventKind, RumaEventInput};
@ -25,7 +24,7 @@ pub struct RumaEvent {
/// The variant of `ruma_events::EventType` for this event, determined by the `event_type`
/// field.
event_type: Path,
event_type: LitStr,
/// Struct fields of the event.
fields: Vec<Field>,
@ -80,10 +79,12 @@ impl ToTokens for RumaEvent {
let content_name = &self.content_name;
let event_fields = &self.fields;
let event_type = {
let event_type = &self.event_type;
let event_type_variant = {
let event_type = to_camel_case(self.event_type.value());
let variant = Ident::new(&event_type, event_type.span());
quote! {
#event_type
::ruma_events::EventType::#variant
}
};
@ -315,7 +316,7 @@ impl ToTokens for RumaEvent {
/// The type of the event.
fn event_type(&self) -> ::ruma_events::EventType {
#event_type
#event_type_variant
}
}
@ -406,6 +407,16 @@ fn is_option(ty: &Type) -> bool {
}
}
/// Splits the given `event_type` string on `.` and `_` removing the `m.` then
/// camel casing to give the `EventType` variant.
fn to_camel_case(name: String) -> String {
assert_eq!(&name[..2], "m.");
name[2..]
.split(&['.', '_'] as &[char])
.map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..])
.collect()
}
/// A wrapper around `syn::Field` that makes it possible to parse `Punctuated<Field, Token![,]>`
/// from a `TokenStream`.
///

View File

@ -1,14 +1,10 @@
//! Details of parsing input for the `ruma_event` procedural macro.
use proc_macro2::Span;
use syn::{
braced,
parse::{self, Parse, ParseStream},
punctuated::Punctuated,
token::Colon,
Attribute, Expr, Field, FieldValue, Ident, Member, Path, PathArguments, PathSegment, Token,
TypePath,
Attribute, Expr, ExprLit, Field, FieldValue, Ident, Lit, LitStr, Member, Token, TypePath,
};
/// The entire `ruma_event!` macro structure directly as it appears in the source code..
@ -22,9 +18,11 @@ pub struct RumaEventInput {
/// The kind of event, determiend by the `kind` field.
pub kind: EventKind,
/// The variant of `ruma_events::EventType` for this event, determined by the `event_type`
/// field.
pub event_type: Path,
/// The value for the `type` field in the JSON representation of this event. There needs to be a
/// corresponding 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 snake_case to CamelCase).
pub event_type: LitStr,
/// Additional named struct fields in the top level event struct.
pub fields: Option<Vec<Field>>,
@ -98,35 +96,13 @@ impl Parse for RumaEventInput {
kind = Some(event_kind);
} else if ident == "event_type" {
match field_value.expr {
Expr::Path(expr_path) => {
if expr_path.path.segments.len() != 1 {
panic!("value of field `event_type` is required to be an ident by `ruma_event!`");
}
let path = expr_path.path;
let variant = path.segments.first().unwrap();
let mut punctuated = Punctuated::new();
punctuated.push(PathSegment {
ident: Ident::new("ruma_events", Span::call_site()),
arguments: PathArguments::None,
});
punctuated.push(PathSegment {
ident: Ident::new("EventType", Span::call_site()),
arguments: PathArguments::None,
});
punctuated.push(variant.clone());
event_type = Some(Path {
leading_colon: Some(Default::default()),
segments: punctuated,
});
}
event_type = Some(match field_value.expr {
Expr::Lit(ExprLit { lit: Lit::Str(s), .. }) => s,
// TODO: Span info
_ => panic!(
"value of field `event_type` is required to be an ident by `ruma_event!`"
"value of field `event_type` is required to be a string literal by `ruma_event!`"
),
}
})
} else {
panic!("unexpected field-value pair with field name `{}`", ident);
}

View File

@ -9,7 +9,7 @@ ruma_event! {
/// This event is sent by the callee when they wish to answer the call.
AnswerEvent {
kind: RoomEvent,
event_type: CallAnswer,
event_type: "m.call.answer",
content: {
/// The VoIP session description object. The session description type must be *answer*.
pub answer: SessionDescription,

View File

@ -10,7 +10,7 @@ ruma_event! {
/// communicate.
CandidatesEvent {
kind: RoomEvent,
event_type: CallCandidates,
event_type: "m.call.candidates",
content: {
/// The ID of the call this event relates to.
pub call_id: String,

View File

@ -9,7 +9,7 @@ ruma_event! {
/// the call has has been established or before to abort the call.
HangupEvent {
kind: RoomEvent,
event_type: CallHangup,
event_type: "m.call.hangup",
content: {
/// The ID of the call this event relates to.
pub call_id: String,

View File

@ -9,7 +9,7 @@ ruma_event! {
/// This event is sent by the caller when they wish to establish a call.
InviteEvent {
kind: RoomEvent,
event_type: CallInvite,
event_type: "m.call.invite",
content: {
/// A unique identifer for the call.
pub call_id: String,

View File

@ -9,7 +9,7 @@ ruma_event! {
/// Informs the client about the rooms that are considered direct by a user.
DirectEvent {
kind: Event,
event_type: Direct,
event_type: "m.direct",
content_type_alias: {
/// The payload for `DirectEvent`.
///

View File

@ -16,7 +16,7 @@ ruma_event! {
/// sending client receiving keys over the newly established session.
DummyEvent {
kind: Event,
event_type: Dummy,
event_type: "m.dummy",
content_type_alias: {
/// The payload for `DummyEvent`.
Empty

View File

@ -11,7 +11,7 @@ ruma_event! {
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
ForwardedRoomKeyEvent {
kind: Event,
event_type: ForwardedRoomKey,
event_type: "m.forwarded_room_key",
content: {
/// The encryption algorithm the key in this event is to be used with.
pub algorithm: Algorithm,

View File

@ -10,7 +10,7 @@ ruma_event! {
/// for.
FullyReadEvent {
kind: Event,
event_type: FullyRead,
event_type: "m.fully_read",
fields: {
/// The unique identifier for the room associated with this event.
///

View File

@ -13,7 +13,7 @@ ruma_event! {
/// Typically sent as a to-device event.
AcceptEvent {
kind: Event,
event_type: KeyVerificationAccept,
event_type: "m.key.verification.accept",
content: {
/// An opaque identifier for the verification process.
///

View File

@ -14,7 +14,7 @@ ruma_event! {
/// Typically sent as a to-device event.
CancelEvent {
kind: Event,
event_type: KeyVerificationCancel,
event_type: "m.key.verification.cancel",
content: {
/// The opaque identifier for the verification process/request.
pub transaction_id: String,

View File

@ -8,7 +8,7 @@ ruma_event! {
/// Typically sent as a to-device event.
KeyEvent {
kind: Event,
event_type: KeyVerificationKey,
event_type: "m.key.verification.key",
content: {
/// An opaque identifier for the verification process.
///

View File

@ -10,7 +10,7 @@ ruma_event! {
/// Typically sent as a to-device event.
MacEvent {
kind: Event,
event_type: KeyVerificationMac,
event_type: "m.key.verification.mac",
content: {
/// An opaque identifier for the verification process.
///

View File

@ -12,7 +12,7 @@ ruma_event! {
/// Typically sent as a to-device event.
RequestEvent {
kind: Event,
event_type: KeyVerificationRequest,
event_type: "m.key.verification.request",
content: {
/// The device ID which is initiating the request.
pub from_device: DeviceId,

View File

@ -9,7 +9,7 @@ ruma_event! {
/// Informs the client of a user's presence state change.
PresenceEvent {
kind: Event,
event_type: Presence,
event_type: "m.presence",
fields: {
/// The unique identifier for the user associated with this event.
pub sender: UserId,

View File

@ -19,7 +19,7 @@ ruma_event! {
/// Describes all push rules for a user.
PushRulesEvent {
kind: Event,
event_type: PushRules,
event_type: "m.push_rules",
content: {
/// The global ruleset.
pub global: Ruleset,

View File

@ -11,7 +11,7 @@ ruma_event! {
/// Informs the client of new receipts.
ReceiptEvent {
kind: Event,
event_type: Receipt,
event_type: "m.receipt",
fields: {
/// The unique identifier for the room associated with this event.
///

View File

@ -7,7 +7,7 @@ ruma_event! {
/// Informs the room about what room aliases it has been given.
AliasesEvent {
kind: StateEvent,
event_type: RoomAliases,
event_type: "m.room.aliases",
content: {
/// A list of room aliases.
pub aliases: Vec<RoomAliasId>,

View File

@ -10,7 +10,7 @@ ruma_event! {
/// This can be displayed alongside the room information.
AvatarEvent {
kind: StateEvent,
event_type: RoomAvatar,
event_type: "m.room.avatar",
content: {
/// Information about the avatar image.
#[serde(skip_serializing_if = "Option::is_none")]

View File

@ -13,7 +13,7 @@ ruma_event! {
/// events.
CreateEvent {
kind: StateEvent,
event_type: RoomCreate,
event_type: "m.room.create",
content: {
/// The `user_id` of the room creator. This is set by the homeserver.
pub creator: UserId,

View File

@ -9,7 +9,7 @@ ruma_event! {
/// Defines how messages sent in this room should be encrypted.
EncryptionEvent {
kind: StateEvent,
event_type: RoomEncryption,
event_type: "m.room.encryption",
content: {
/// The encryption algorithm to be used to encrypt messages sent in this room.
///

View File

@ -10,7 +10,7 @@ ruma_event! {
/// servers should act as if it is present and has the value `GuestAccess::Forbidden`.
GuestAccessEvent {
kind: StateEvent,
event_type: RoomGuestAccess,
event_type: "m.room.guest_access",
content: {
/// A policy for guest user access to a room.
pub guest_access: GuestAccess,

View File

@ -8,7 +8,7 @@ ruma_event! {
/// from before they joined.
HistoryVisibilityEvent {
kind: StateEvent,
event_type: RoomHistoryVisibility,
event_type: "m.room.history_visibility",
content: {
/// Who can see the room history.
pub history_visibility: HistoryVisibility,

View File

@ -7,7 +7,7 @@ ruma_event! {
/// Describes how users are allowed to join the room.
JoinRulesEvent {
kind: StateEvent,
event_type: RoomJoinRules,
event_type: "m.room.join_rules",
content: {
/// The type of rules used for users wishing to join this room.
pub join_rule: JoinRule,

View File

@ -34,7 +34,7 @@ ruma_event! {
/// must be assumed as leave.
MemberEvent {
kind: StateEvent,
event_type: RoomMember,
event_type: "m.room.member",
content: {
/// The avatar URL for this user, if any. This is added by the homeserver.
#[serde(skip_serializing_if = "Option::is_none")]

View File

@ -11,7 +11,7 @@ ruma_event! {
/// not recognize this event.
FeedbackEvent {
kind: RoomEvent,
event_type: RoomMessageFeedback,
event_type: "m.room.message.feedback",
content: {
/// The event that this feedback is related to.
pub target_event_id: EventId,

View File

@ -7,7 +7,7 @@ ruma_event! {
/// Used to "pin" particular events in a room for other participants to review later.
PinnedEventsEvent {
kind: StateEvent,
event_type: RoomPinnedEvents,
event_type: "m.room.pinned_events",
content: {
/// An ordered list of event IDs to pin.
pub pinned: Vec<EventId>,

View File

@ -7,7 +7,7 @@ ruma_event! {
/// A redaction of an event.
RedactionEvent {
kind: RoomEvent,
event_type: RoomRedaction,
event_type: "m.room.redaction",
fields: {
/// The ID of the event that was redacted.
pub redacts: EventId,

View File

@ -11,7 +11,7 @@ ruma_event! {
/// Any user who can present that signature may use this invitation to join the target room.
ThirdPartyInviteEvent {
kind: StateEvent,
event_type: RoomThirdPartyInvite,
event_type: "m.room.third_party_invite",
content: {
/// A user-readable string which represents the user who has been invited.
pub display_name: String,

View File

@ -8,7 +8,7 @@ ruma_event! {
/// clients should go there.
TombstoneEvent {
kind: StateEvent,
event_type: RoomTombstone,
event_type: "m.room.tombstone",
content: {
/// A server-defined message.
pub body: String,

View File

@ -6,7 +6,7 @@ ruma_event! {
/// A topic is a short message detailing what is currently being discussed in the room.
TopicEvent {
kind: StateEvent,
event_type: RoomTopic,
event_type: "m.room.topic",
content: {
/// The topic text.
pub topic: String,

View File

@ -11,7 +11,7 @@ ruma_event! {
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
RoomKeyEvent {
kind: Event,
event_type: RoomKey,
event_type: "m.room_key",
content: {
/// The encryption algorithm the key in this event is to be used with.
///

View File

@ -12,7 +12,7 @@ ruma_event! {
/// It is sent as an unencrypted to-device event.
RoomKeyRequestEvent {
kind: Event,
event_type: RoomKeyRequest,
event_type: "m.room_key_request",
content: {
/// Whether this is a new key request or a cancellation of a previous request.
pub action: Action,

View File

@ -8,7 +8,7 @@ ruma_event! {
/// A sticker message.
StickerEvent {
kind: RoomEvent,
event_type: Sticker,
event_type: "m.sticker",
content: {
/// A textual representation or associated description of the sticker image. This could
/// be the alt text of the original image, or a message to accompany and further

View File

@ -9,7 +9,7 @@ ruma_event! {
/// Informs the client of tags on a room.
TagEvent {
kind: Event,
event_type: Tag,
event_type: "m.tag",
content: {
/// A map of tag names to tag info.
pub tags: HashMap<String, TagInfo>,

View File

@ -7,7 +7,7 @@ ruma_event! {
/// Informs the client of the list of users currently typing.
TypingEvent {
kind: Event,
event_type: Typing,
event_type: "m.typing",
fields: {
/// The unique identifier for the room associated with this event.
///

View File

@ -14,7 +14,7 @@ mod common_case {
/// Informs the room about what room aliases it has been given.
AliasesEvent {
kind: StateEvent,
event_type: RoomAliases,
event_type: "m.room.aliases",
content: {
/// A list of room aliases.
pub aliases: Vec<ruma_identifiers::RoomAliasId>,
@ -126,7 +126,7 @@ mod extra_fields {
/// A redaction of an event.
RedactionEvent {
kind: RoomEvent,
event_type: RoomRedaction,
event_type: "m.room.redaction",
fields: {
/// The ID of the event that was redacted.
pub redacts: ruma_identifiers::EventId
@ -174,7 +174,7 @@ mod type_alias {
/// Informs the client about the rooms that are considered direct by a user.
DirectEvent {
kind: Event,
event_type: Direct,
event_type: "m.direct",
content_type_alias: {
/// The payload of a `DirectEvent`.
///