From 6dc0bf248bb8251e14060bc2041ca2ba9c11dc78 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 15 Mar 2022 13:26:13 +0100 Subject: [PATCH] Use *EventType enums in more places --- .../src/config/set_global_account_data.rs | 4 +- .../src/config/set_room_account_data.rs | 4 +- .../src/message/send_message_event.rs | 4 +- .../src/state/send_state_event.rs | 43 ++++++++------- crates/ruma-common/src/events.rs | 8 +-- crates/ruma-common/src/events/_custom.rs | 4 +- crates/ruma-common/src/events/room/aliases.rs | 4 +- crates/ruma-common/src/events/room/member.rs | 4 +- crates/ruma-common/tests/events/enums.rs | 2 +- .../ruma-common/tests/events/message_event.rs | 4 +- .../ruma-common/tests/events/state_event.rs | 4 +- crates/ruma-macros/src/events/event.rs | 2 + .../ruma-macros/src/events/event_content.rs | 55 ++++++++++++++----- crates/ruma-macros/src/events/event_enum.rs | 19 +++++-- 14 files changed, 99 insertions(+), 62 deletions(-) diff --git a/crates/ruma-client-api/src/config/set_global_account_data.rs b/crates/ruma-client-api/src/config/set_global_account_data.rs index d6eb57e4..067805e5 100644 --- a/crates/ruma-client-api/src/config/set_global_account_data.rs +++ b/crates/ruma-client-api/src/config/set_global_account_data.rs @@ -36,7 +36,7 @@ pub mod v3 { /// /// Custom types should be namespaced to avoid clashes. #[ruma_api(path)] - pub event_type: &'a str, + pub event_type: GlobalAccountDataEventType, /// Arbitrary JSON to store as config data. /// @@ -72,7 +72,7 @@ pub mod v3 { /// Creates a new `Request` with the given raw data, event type and user ID. pub fn new_raw( data: Raw, - event_type: &'a str, + event_type: GlobalAccountDataEventType, user_id: &'a UserId, ) -> Self { Self { user_id, event_type, data } diff --git a/crates/ruma-client-api/src/config/set_room_account_data.rs b/crates/ruma-client-api/src/config/set_room_account_data.rs index 4909e2b9..53a11f53 100644 --- a/crates/ruma-client-api/src/config/set_room_account_data.rs +++ b/crates/ruma-client-api/src/config/set_room_account_data.rs @@ -36,7 +36,7 @@ pub mod v3 { /// /// Custom types should be namespaced to avoid clashes. #[ruma_api(path)] - pub event_type: &'a str, + pub event_type: RoomAccountDataEventType, /// The ID of the room to set account_data on. #[ruma_api(path)] @@ -81,7 +81,7 @@ pub mod v3 { /// Creates a new `Request` with the given raw data, event type, room ID and user ID. pub fn new_raw( data: Raw, - event_type: &'a str, + event_type: RoomAccountDataEventType, room_id: &'a RoomId, user_id: &'a UserId, ) -> Self { diff --git a/crates/ruma-client-api/src/message/send_message_event.rs b/crates/ruma-client-api/src/message/send_message_event.rs index ed324889..f5c12303 100644 --- a/crates/ruma-client-api/src/message/send_message_event.rs +++ b/crates/ruma-client-api/src/message/send_message_event.rs @@ -32,7 +32,7 @@ pub mod v3 { /// The type of event to send. #[ruma_api(path)] - pub event_type: &'a str, + pub event_type: MessageLikeEventType, /// The transaction ID for this event. /// @@ -83,7 +83,7 @@ pub mod v3 { pub fn new_raw( room_id: &'a RoomId, txn_id: &'a TransactionId, - event_type: &'a str, + event_type: MessageLikeEventType, body: Raw, ) -> Self { Self { room_id, event_type, txn_id, body } diff --git a/crates/ruma-client-api/src/state/send_state_event.rs b/crates/ruma-client-api/src/state/send_state_event.rs index f4ab0721..a7aa2caa 100644 --- a/crates/ruma-client-api/src/state/send_state_event.rs +++ b/crates/ruma-client-api/src/state/send_state_event.rs @@ -44,7 +44,7 @@ pub mod v3 { pub room_id: &'a RoomId, /// The type of event to send. - pub event_type: &'a str, + pub event_type: StateEventType, /// The state_key for the state to send. pub state_key: &'a str, @@ -80,7 +80,7 @@ pub mod v3 { /// content. pub fn new_raw( room_id: &'a RoomId, - event_type: &'a str, + event_type: StateEventType, state_key: &'a str, body: Raw, ) -> Self { @@ -114,7 +114,8 @@ pub mod v3 { use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; let room_id_percent = utf8_percent_encode(self.room_id.as_str(), NON_ALPHANUMERIC); - let event_type_percent = utf8_percent_encode(self.event_type, NON_ALPHANUMERIC); + let event_type_percent = + utf8_percent_encode(self.event_type.as_str(), NON_ALPHANUMERIC); let mut url = format!( "{}{}", @@ -173,25 +174,25 @@ pub mod v3 { { // FIXME: find a way to make this if-else collapse with serde recognizing trailing // Option - let (room_id, event_type, state_key): (Box, String, String) = if path_args.len() - == 3 - { - serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::< - _, - serde::de::value::Error, - >::new( - path_args.iter().map(::std::convert::AsRef::as_ref), - ))? - } else { - let (a, b) = serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::< - _, - serde::de::value::Error, - >::new( - path_args.iter().map(::std::convert::AsRef::as_ref), - ))?; + let (room_id, event_type, state_key): (Box, StateEventType, String) = + if path_args.len() == 3 { + serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::< + _, + serde::de::value::Error, + >::new( + path_args.iter().map(::std::convert::AsRef::as_ref), + ))? + } else { + let (a, b) = + serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::< + _, + serde::de::value::Error, + >::new( + path_args.iter().map(::std::convert::AsRef::as_ref), + ))?; - (a, b, "".into()) - }; + (a, b, "".into()) + }; let body = serde_json::from_slice(request.body().as_ref())?; diff --git a/crates/ruma-common/src/events.rs b/crates/ruma-common/src/events.rs index 4bf8d71b..063a0434 100644 --- a/crates/ruma-common/src/events.rs +++ b/crates/ruma-common/src/events.rs @@ -202,10 +202,10 @@ pub use self::{ /// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually. pub trait EventContent: Sized + Serialize { /// The Rust enum for the event kind's known types. - type EventType; + type EventType: AsRef; /// Get the event's type, like `m.room.message`. - fn event_type(&self) -> &str; + fn event_type(&self) -> Self::EventType; /// Constructs the given event content. #[doc(hidden)] @@ -240,8 +240,8 @@ pub trait RedactContent { impl Raw { /// Try to deserialize the JSON as an event's content. - pub fn deserialize_content(&self, event_type: &str) -> serde_json::Result { - T::from_parts(event_type, self.json()) + pub fn deserialize_content(&self, event_type: T::EventType) -> serde_json::Result { + T::from_parts(event_type.as_ref(), self.json()) } } diff --git a/crates/ruma-common/src/events/_custom.rs b/crates/ruma-common/src/events/_custom.rs index 75ca4798..cb79d21f 100644 --- a/crates/ruma-common/src/events/_custom.rs +++ b/crates/ruma-common/src/events/_custom.rs @@ -23,8 +23,8 @@ macro_rules! custom_event_content { impl EventContent for $i { type EventType = $evt; - fn event_type(&self) -> &str { - &self.event_type + fn event_type(&self) -> Self::EventType { + self.event_type[..].into() } fn from_parts(event_type: &str, _content: &RawJsonValue) -> serde_json::Result { diff --git a/crates/ruma-common/src/events/room/aliases.rs b/crates/ruma-common/src/events/room/aliases.rs index eb365aaf..3b287e15 100644 --- a/crates/ruma-common/src/events/room/aliases.rs +++ b/crates/ruma-common/src/events/room/aliases.rs @@ -78,8 +78,8 @@ impl RedactedRoomAliasesEventContent { impl EventContent for RedactedRoomAliasesEventContent { type EventType = StateEventType; - fn event_type(&self) -> &str { - "m.room.aliases" + fn event_type(&self) -> StateEventType { + StateEventType::RoomAliases } fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result { diff --git a/crates/ruma-common/src/events/room/member.rs b/crates/ruma-common/src/events/room/member.rs index adb03e11..8bad93a9 100644 --- a/crates/ruma-common/src/events/room/member.rs +++ b/crates/ruma-common/src/events/room/member.rs @@ -161,8 +161,8 @@ impl RedactedRoomMemberEventContent { impl EventContent for RedactedRoomMemberEventContent { type EventType = StateEventType; - fn event_type(&self) -> &str { - "m.room.member" + fn event_type(&self) -> StateEventType { + StateEventType::RoomMember } fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result { diff --git a/crates/ruma-common/tests/events/enums.rs b/crates/ruma-common/tests/events/enums.rs index a4386df8..6ed882c0 100644 --- a/crates/ruma-common/tests/events/enums.rs +++ b/crates/ruma-common/tests/events/enums.rs @@ -299,7 +299,7 @@ fn alias_event_field_access() { } else { panic!("the `Any*Event` enum's accessor methods may have been altered") } - assert_eq!(deser.event_type(), "m.room.aliases"); + assert_eq!(deser.event_type().as_str(), "m.room.aliases"); } #[test] diff --git a/crates/ruma-common/tests/events/message_event.rs b/crates/ruma-common/tests/events/message_event.rs index f9b3c5e6..0c06f1f5 100644 --- a/crates/ruma-common/tests/events/message_event.rs +++ b/crates/ruma-common/tests/events/message_event.rs @@ -8,7 +8,7 @@ use ruma_common::{ room::{ImageInfo, ThumbnailInfo}, sticker::StickerEventContent, AnyMessageLikeEvent, AnyMessageLikeEventContent, AnySyncMessageLikeEvent, MessageLikeEvent, - Unsigned, + MessageLikeEventType, Unsigned, }, mxc_uri, room_id, serde::Raw, @@ -86,7 +86,7 @@ fn deserialize_message_call_answer_content() { assert_matches!( from_json_value::>(json_data) .unwrap() - .deserialize_content("m.call.answer") + .deserialize_content(MessageLikeEventType::CallAnswer) .unwrap(), AnyMessageLikeEventContent::CallAnswer(CallAnswerEventContent { answer: SessionDescription { diff --git a/crates/ruma-common/tests/events/state_event.rs b/crates/ruma-common/tests/events/state_event.rs index 29ee7c32..39b4d5ee 100644 --- a/crates/ruma-common/tests/events/state_event.rs +++ b/crates/ruma-common/tests/events/state_event.rs @@ -9,7 +9,7 @@ use ruma_common::{ ThumbnailInfo, }, AnyRoomEvent, AnyStateEvent, AnyStateEventContent, AnySyncStateEvent, StateEvent, - SyncStateEvent, Unsigned, + StateEventType, SyncStateEvent, Unsigned, }, mxc_uri, room_alias_id, room_id, serde::Raw, @@ -99,7 +99,7 @@ fn deserialize_aliases_content() { assert_matches!( from_json_value::>(json_data) .unwrap() - .deserialize_content("m.room.aliases") + .deserialize_content(StateEventType::RoomAliases) .unwrap(), AnyStateEventContent::RoomAliases(content) if content.aliases == vec![room_alias_id!("#somewhere:localhost")] diff --git a/crates/ruma-macros/src/events/event.rs b/crates/ruma-macros/src/events/event.rs index 88b831f5..a1ddee76 100644 --- a/crates/ruma-macros/src/events/event.rs +++ b/crates/ruma-macros/src/events/event.rs @@ -120,6 +120,8 @@ fn expand_serialize_event( use #serde::ser::{SerializeStruct as _, Error as _}; let event_type = #ruma_common::events::EventContent::event_type(&self.content); + let event_type = + ::std::convert::AsRef::<::std::primitive::str>::as_ref(&event_type); let mut state = serializer.serialize_struct(stringify!(#ident), 7)?; diff --git a/crates/ruma-macros/src/events/event_content.rs b/crates/ruma-macros/src/events/event_content.rs index 895af55c..9e5cc932 100644 --- a/crates/ruma-macros/src/events/event_content.rs +++ b/crates/ruma-macros/src/events/event_content.rs @@ -9,6 +9,8 @@ use syn::{ DeriveInput, Ident, LitStr, Token, }; +use crate::util::m_prefix_name_to_type_name; + use super::event_parse::{EventKind, EventKindVariation}; mod kw { @@ -164,7 +166,7 @@ pub fn expand_event_content( .transpose()?; let event_content_impl = - generate_event_content_impl(ident, event_type, event_kind, ruma_common); + generate_event_content_impl(ident, event_type, event_kind, ruma_common)?; let static_event_content_impl = event_kind .map(|k| generate_static_event_content_impl(ident, k, false, event_type, ruma_common)); let type_aliases = event_kind @@ -259,7 +261,7 @@ fn generate_redacted_event_content( }); let redacted_event_content = - generate_event_content_impl(&redacted_ident, event_type, event_kind, ruma_common); + generate_event_content_impl(&redacted_ident, event_type, event_kind, ruma_common)?; let static_event_content_impl = event_kind.map(|k| { generate_static_event_content_impl(&redacted_ident, k, true, event_type, ruma_common) @@ -374,41 +376,66 @@ fn generate_event_content_impl( event_type: &LitStr, event_kind: Option, ruma_common: &TokenStream, -) -> TokenStream { +) -> syn::Result { let serde = quote! { #ruma_common::exports::serde }; let serde_json = quote! { #ruma_common::exports::serde_json }; - let event_type_ty = match event_kind { + let (event_type_ty_decl, event_type_ty, event_type_fn_impl); + + match event_kind { Some(kind) => { let i = kind.to_event_type_enum(); - quote! { #ruma_common::events::#i } + event_type_ty_decl = None; + event_type_ty = quote! { #ruma_common::events::#i }; + event_type_fn_impl = quote! { ::std::convert::From::from(#event_type) }; } - None => quote! { () }, - }; + None => { + let camel_case_type_name = m_prefix_name_to_type_name(event_type)?; + let i = format_ident!("{}EventType", camel_case_type_name); + event_type_ty_decl = Some(quote! { + /// Implementation detail, you don't need to care about this. + #[doc(hidden)] + pub struct #i { + // Set to None for intended type, Some for a different one + ty: ::std::option::Option, + } + + impl ::std::convert::AsRef<::std::primitive::str> for #i { + fn as_ref(&self) -> &::std::primitive::str { + self.ty.as_ref().map(|t| &t.0[..]).unwrap_or(#event_type) + } + } + }); + event_type_ty = quote! { #i }; + event_type_fn_impl = quote! { #event_type_ty { ty: ::std::option::Option::None } }; + } + } + + Ok(quote! { + #event_type_ty_decl - quote! { #[automatically_derived] impl #ruma_common::events::EventContent for #ident { type EventType = #event_type_ty; - fn event_type(&self) -> &str { - #event_type + fn event_type(&self) -> Self::EventType { + #event_type_fn_impl } fn from_parts( - ev_type: &str, + ev_type: &::std::primitive::str, content: &#serde_json::value::RawValue, ) -> #serde_json::Result { if ev_type != #event_type { - return Err(#serde::de::Error::custom( - format!("expected event type `{}`, found `{}`", #event_type, ev_type) + return ::std::result::Result::Err(#serde::de::Error::custom( + ::std::format!("expected event type `{}`, found `{}`", #event_type, ev_type) )); } #serde_json::from_str(content.get()) } } - } + }) } fn generate_static_event_content_impl( diff --git a/crates/ruma-macros/src/events/event_enum.rs b/crates/ruma-macros/src/events/event_enum.rs index fee261d3..62519b48 100644 --- a/crates/ruma-macros/src/events/event_enum.rs +++ b/crates/ruma-macros/src/events/event_enum.rs @@ -292,10 +292,10 @@ fn expand_content_enum( impl #ruma_common::events::EventContent for #ident { type EventType = #ruma_common::events::#event_type_enum; - fn event_type(&self) -> &::std::primitive::str { + fn event_type(&self) -> Self::EventType { match self { #( #variant_arms(content) => content.event_type(), )* - Self::_Custom { event_type } => &event_type.0, + Self::_Custom { event_type } => ::std::convert::From::from(&event_type.0[..]), } } @@ -411,6 +411,7 @@ fn expand_accessor_methods( ruma_common: &TokenStream, ) -> TokenStream { let ident = kind.to_event_enum_ident(var); + let event_type_enum = format_ident!("{}Type", kind); let self_variants: Vec<_> = variants.iter().map(|v| v.match_arm(quote! { Self })).collect(); let content_accessors = (!var.is_redacted()).then(|| { @@ -430,7 +431,9 @@ fn expand_accessor_methods( Self::_Custom(event) => { event.prev_content.as_ref().map(|c| #content_enum::_Custom { event_type: crate::PrivOwnedStr( - #ruma_common::events::EventContent::event_type(c).into(), + ::std::convert::From::from( + #ruma_common::events::EventContent::event_type(c).as_str() + ), ), }) }, @@ -446,7 +449,10 @@ fn expand_accessor_methods( #( #self_variants(event) => #content_variants(event.content.clone()), )* Self::_Custom(event) => #content_enum::_Custom { event_type: crate::PrivOwnedStr( - #ruma_common::events::EventContent::event_type(&event.content).into(), + ::std::convert::From::from( + #ruma_common::events::EventContent::event_type(&event.content) + .as_str(), + ), ), }, } @@ -479,12 +485,13 @@ fn expand_accessor_methods( #[automatically_derived] impl #ident { /// Returns the `type` of this event. - pub fn event_type(&self) -> &::std::primitive::str { + pub fn event_type(&self) -> #ruma_common::events::#event_type_enum { match self { #( #self_variants(event) => #ruma_common::events::EventContent::event_type(&event.content), )* - Self::_Custom(event) => + Self::_Custom(event) => ::std::convert::From::from( #ruma_common::events::EventContent::event_type(&event.content), + ), } }