events: Allow customizing the unsigned type of state events
This commit is contained in:
		
							parent
							
								
									35d8bdd5a1
								
							
						
					
					
						commit
						aa8e48d1c3
					
				| @ -6,7 +6,7 @@ use super::{ | |||||||
|     GlobalAccountDataEventType, HasDeserializeFields, MessageLikeEventContent, |     GlobalAccountDataEventType, HasDeserializeFields, MessageLikeEventContent, | ||||||
|     MessageLikeEventType, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent, |     MessageLikeEventType, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent, | ||||||
|     RedactedStateEventContent, RoomAccountDataEventContent, RoomAccountDataEventType, |     RedactedStateEventContent, RoomAccountDataEventContent, RoomAccountDataEventType, | ||||||
|     StateEventContent, StateEventType, ToDeviceEventContent, ToDeviceEventType, |     StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent, ToDeviceEventType, | ||||||
| }; | }; | ||||||
| use crate::RoomVersionId; | use crate::RoomVersionId; | ||||||
| 
 | 
 | ||||||
| @ -80,6 +80,7 @@ impl RedactedMessageLikeEventContent for CustomMessageLikeEventContent {} | |||||||
| custom_room_event_content!(CustomStateEventContent, StateEventType); | custom_room_event_content!(CustomStateEventContent, StateEventType); | ||||||
| impl StateEventContent for CustomStateEventContent { | impl StateEventContent for CustomStateEventContent { | ||||||
|     type StateKey = String; |     type StateKey = String; | ||||||
|  |     type Unsigned = StateUnsigned<Self>; | ||||||
| } | } | ||||||
| impl RedactedStateEventContent for CustomStateEventContent {} | impl RedactedStateEventContent for CustomStateEventContent {} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,11 +3,11 @@ use std::fmt; | |||||||
| use serde::{de::DeserializeOwned, Serialize}; | use serde::{de::DeserializeOwned, Serialize}; | ||||||
| use serde_json::value::RawValue as RawJsonValue; | use serde_json::value::RawValue as RawJsonValue; | ||||||
| 
 | 
 | ||||||
| use crate::serde::Raw; | use crate::serde::{CanBeEmpty, Raw}; | ||||||
| 
 | 
 | ||||||
| use super::{ | use super::{ | ||||||
|     EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType, |     EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType, | ||||||
|     RoomAccountDataEventType, StateEventType, ToDeviceEventType, |     RoomAccountDataEventType, StateEventType, StateUnsignedFromParts, ToDeviceEventType, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// The base trait that all event content types implement.
 | /// The base trait that all event content types implement.
 | ||||||
| @ -158,6 +158,9 @@ pub trait RedactedMessageLikeEventContent: MessageLikeEventContent + RedactedEve | |||||||
| pub trait StateEventContent: EventContent<EventType = StateEventType> { | pub trait StateEventContent: EventContent<EventType = StateEventType> { | ||||||
|     /// The type of the event's `state_key` field.
 |     /// The type of the event's `state_key` field.
 | ||||||
|     type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize; |     type StateKey: AsRef<str> + Clone + fmt::Debug + DeserializeOwned + Serialize; | ||||||
|  | 
 | ||||||
|  |     /// The type of the event's `unsigned` field.
 | ||||||
|  |     type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + StateUnsignedFromParts + Serialize; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Content of a non-redacted state event.
 | /// Content of a non-redacted state event.
 | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use super::{ | |||||||
|     GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType, |     GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType, | ||||||
|     MessageLikeUnsigned, Redact, RedactContent, RedactedMessageLikeEventContent, |     MessageLikeUnsigned, Redact, RedactContent, RedactedMessageLikeEventContent, | ||||||
|     RedactedStateEventContent, RedactedUnsigned, RedactionDeHelper, RoomAccountDataEventContent, |     RedactedStateEventContent, RedactedUnsigned, RedactionDeHelper, RoomAccountDataEventContent, | ||||||
|     StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent, |     StateEventContent, StateEventType, ToDeviceEventContent, | ||||||
| }; | }; | ||||||
| use crate::{ | use crate::{ | ||||||
|     serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, |     serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, | ||||||
| @ -205,7 +205,7 @@ pub struct OriginalStateEvent<C: StateEventContent> { | |||||||
|     pub state_key: C::StateKey, |     pub state_key: C::StateKey, | ||||||
| 
 | 
 | ||||||
|     /// Additional key-value pairs not signed by the homeserver.
 |     /// Additional key-value pairs not signed by the homeserver.
 | ||||||
|     pub unsigned: StateUnsigned<C>, |     pub unsigned: C::Unsigned, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// An unredacted state event without a `room_id`.
 | /// An unredacted state event without a `room_id`.
 | ||||||
| @ -233,7 +233,7 @@ pub struct OriginalSyncStateEvent<C: StateEventContent> { | |||||||
|     pub state_key: C::StateKey, |     pub state_key: C::StateKey, | ||||||
| 
 | 
 | ||||||
|     /// Additional key-value pairs not signed by the homeserver.
 |     /// Additional key-value pairs not signed by the homeserver.
 | ||||||
|     pub unsigned: StateUnsigned<C>, |     pub unsigned: C::Unsigned, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// A stripped-down state event, used for previews of rooms the user has been invited to.
 | /// A stripped-down state event, used for previews of rooms the user has been invited to.
 | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ use serde_json::value::RawValue as RawJsonValue; | |||||||
| use crate::{ | use crate::{ | ||||||
|     events::{ |     events::{ | ||||||
|         EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, |         EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, | ||||||
|         RedactedStateEventContent, StateEventContent, StateEventType, |         RedactedStateEventContent, StateEventContent, StateEventType, StateUnsigned, | ||||||
|     }, |     }, | ||||||
|     OwnedRoomAliasId, OwnedServerName, RoomVersionId, |     OwnedRoomAliasId, OwnedServerName, RoomVersionId, | ||||||
| }; | }; | ||||||
| @ -97,6 +97,8 @@ impl EventContent for RedactedRoomAliasesEventContent { | |||||||
| 
 | 
 | ||||||
| impl StateEventContent for RedactedRoomAliasesEventContent { | impl StateEventContent for RedactedRoomAliasesEventContent { | ||||||
|     type StateKey = OwnedServerName; |     type StateKey = OwnedServerName; | ||||||
|  |     // FIXME: Not actually used
 | ||||||
|  |     type Unsigned = StateUnsigned<Self>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RedactedStateEventContent for RedactedRoomAliasesEventContent {} | impl RedactedStateEventContent for RedactedRoomAliasesEventContent {} | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ use serde_json::value::RawValue as RawJsonValue; | |||||||
| use crate::{ | use crate::{ | ||||||
|     events::{ |     events::{ | ||||||
|         EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, |         EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, | ||||||
|         RedactedStateEventContent, StateEventContent, StateEventType, |         RedactedStateEventContent, StateEventContent, StateEventType, StateUnsigned, | ||||||
|     }, |     }, | ||||||
|     serde::StringEnum, |     serde::StringEnum, | ||||||
|     OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, PrivOwnedStr, |     OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, PrivOwnedStr, | ||||||
| @ -202,6 +202,8 @@ impl EventContent for RedactedRoomMemberEventContent { | |||||||
| 
 | 
 | ||||||
| impl StateEventContent for RedactedRoomMemberEventContent { | impl StateEventContent for RedactedRoomMemberEventContent { | ||||||
|     type StateKey = OwnedUserId; |     type StateKey = OwnedUserId; | ||||||
|  |     // FIXME: Not actually used
 | ||||||
|  |     type Unsigned = StateUnsigned<Self>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RedactedStateEventContent for RedactedRoomMemberEventContent {} | impl RedactedStateEventContent for RedactedRoomMemberEventContent {} | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ error: no event type attribute found, add `#[ruma_event(type = "any.room.event", | |||||||
|   | |   | | ||||||
|   = note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info) |   = note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info) | ||||||
| 
 | 
 | ||||||
| error: expected one of: `type`, `kind`, `custom_redacted`, `state_key_type`, `alias` | error: expected one of: `type`, `kind`, `custom_redacted`, `state_key_type`, `unsigned_type`, `alias` | ||||||
|   --> tests/events/ui/03-invalid-event-type.rs:11:14 |   --> tests/events/ui/03-invalid-event-type.rs:11:14 | ||||||
|    | |    | | ||||||
| 11 | #[ruma_event(event = "m.macro.test", kind = State)] | 11 | #[ruma_event(event = "m.macro.test", kind = State)] | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| //! Implementations of the EventContent derive macro.
 | //! Implementations of the EventContent derive macro.
 | ||||||
|  | #![allow(clippy::too_many_arguments)] // FIXME
 | ||||||
| 
 | 
 | ||||||
| use std::borrow::Cow; | use std::borrow::Cow; | ||||||
| 
 | 
 | ||||||
| @ -23,6 +24,8 @@ mod kw { | |||||||
|     syn::custom_keyword!(type_fragment); |     syn::custom_keyword!(type_fragment); | ||||||
|     // The type to use for a state events' `state_key` field.
 |     // The type to use for a state events' `state_key` field.
 | ||||||
|     syn::custom_keyword!(state_key_type); |     syn::custom_keyword!(state_key_type); | ||||||
|  |     // The type to use for a state events' `unsigned` field.
 | ||||||
|  |     syn::custom_keyword!(unsigned_type); | ||||||
|     // Another type string accepted for deserialization.
 |     // Another type string accepted for deserialization.
 | ||||||
|     syn::custom_keyword!(alias); |     syn::custom_keyword!(alias); | ||||||
| } | } | ||||||
| @ -42,6 +45,8 @@ enum EventStructMeta { | |||||||
| 
 | 
 | ||||||
|     StateKeyType(Box<Type>), |     StateKeyType(Box<Type>), | ||||||
| 
 | 
 | ||||||
|  |     UnsignedType(Box<Type>), | ||||||
|  | 
 | ||||||
|     /// Variant that holds alternate event type accepted for deserialization.
 |     /// Variant that holds alternate event type accepted for deserialization.
 | ||||||
|     Alias(LitStr), |     Alias(LitStr), | ||||||
| } | } | ||||||
| @ -68,6 +73,13 @@ impl EventStructMeta { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn get_unsigned_type(&self) -> Option<&Type> { | ||||||
|  |         match self { | ||||||
|  |             Self::UnsignedType(ty) => Some(ty), | ||||||
|  |             _ => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn get_alias(&self) -> Option<&LitStr> { |     fn get_alias(&self) -> Option<&LitStr> { | ||||||
|         match self { |         match self { | ||||||
|             Self::Alias(t) => Some(t), |             Self::Alias(t) => Some(t), | ||||||
| @ -94,6 +106,10 @@ impl Parse for EventStructMeta { | |||||||
|             let _: kw::state_key_type = input.parse()?; |             let _: kw::state_key_type = input.parse()?; | ||||||
|             let _: Token![=] = input.parse()?; |             let _: Token![=] = input.parse()?; | ||||||
|             input.parse().map(EventStructMeta::StateKeyType) |             input.parse().map(EventStructMeta::StateKeyType) | ||||||
|  |         } else if lookahead.peek(kw::unsigned_type) { | ||||||
|  |             let _: kw::unsigned_type = input.parse()?; | ||||||
|  |             let _: Token![=] = input.parse()?; | ||||||
|  |             input.parse().map(EventStructMeta::UnsignedType) | ||||||
|         } else if lookahead.peek(kw::alias) { |         } else if lookahead.peek(kw::alias) { | ||||||
|             let _: kw::alias = input.parse()?; |             let _: kw::alias = input.parse()?; | ||||||
|             let _: Token![=] = input.parse()?; |             let _: Token![=] = input.parse()?; | ||||||
| @ -151,6 +167,10 @@ impl MetaAttrs { | |||||||
|         self.0.iter().find_map(|a| a.get_state_key_type()) |         self.0.iter().find_map(|a| a.get_state_key_type()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn get_unsigned_type(&self) -> Option<&Type> { | ||||||
|  |         self.0.iter().find_map(|a| a.get_unsigned_type()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn get_aliases(&self) -> impl Iterator<Item = &LitStr> { |     fn get_aliases(&self) -> impl Iterator<Item = &LitStr> { | ||||||
|         self.0.iter().filter_map(|a| a.get_alias()) |         self.0.iter().filter_map(|a| a.get_alias()) | ||||||
|     } |     } | ||||||
| @ -191,7 +211,7 @@ pub fn expand_event_content( | |||||||
|         _ => { |         _ => { | ||||||
|             return Err(syn::Error::new( |             return Err(syn::Error::new( | ||||||
|                 Span::call_site(), |                 Span::call_site(), | ||||||
|                 "multiple event type attribute found, there can only be one", |                 "multiple event type attributes found, there can only be one", | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @ -204,7 +224,7 @@ pub fn expand_event_content( | |||||||
|         _ => { |         _ => { | ||||||
|             return Err(syn::Error::new( |             return Err(syn::Error::new( | ||||||
|                 Span::call_site(), |                 Span::call_site(), | ||||||
|                 "multiple event kind attribute found, there can only be one", |                 "multiple event kind attributes found, there can only be one", | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @ -234,6 +254,19 @@ pub fn expand_event_content( | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     let unsigned_types: Vec<_> = | ||||||
|  |         content_attr.iter().filter_map(|attrs| attrs.get_unsigned_type()).collect(); | ||||||
|  |     let unsigned_type = match unsigned_types.as_slice() { | ||||||
|  |         [] => None, | ||||||
|  |         [ty] => Some(quote! { #ty }), | ||||||
|  |         _ => { | ||||||
|  |             return Err(syn::Error::new( | ||||||
|  |                 Span::call_site(), | ||||||
|  |                 "multiple unsigned attributes found, there can only be one", | ||||||
|  |             )); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     let ident = &input.ident; |     let ident = &input.ident; | ||||||
|     let fields = match &input.data { |     let fields = match &input.data { | ||||||
|         syn::Data::Struct(syn::DataStruct { fields, .. }) => fields.iter(), |         syn::Data::Struct(syn::DataStruct { fields, .. }) => fields.iter(), | ||||||
| @ -280,6 +313,7 @@ pub fn expand_event_content( | |||||||
|             event_type, |             event_type, | ||||||
|             event_kind, |             event_kind, | ||||||
|             state_key_type.as_ref(), |             state_key_type.as_ref(), | ||||||
|  |             unsigned_type.clone(), | ||||||
|             &aliases, |             &aliases, | ||||||
|             ruma_common, |             ruma_common, | ||||||
|         ) |         ) | ||||||
| @ -292,6 +326,7 @@ pub fn expand_event_content( | |||||||
|         event_type, |         event_type, | ||||||
|         event_kind, |         event_kind, | ||||||
|         state_key_type.as_ref(), |         state_key_type.as_ref(), | ||||||
|  |         unsigned_type, | ||||||
|         &aliases, |         &aliases, | ||||||
|         ruma_common, |         ruma_common, | ||||||
|     ) |     ) | ||||||
| @ -317,6 +352,7 @@ fn generate_redacted_event_content<'a>( | |||||||
|     event_type: &LitStr, |     event_type: &LitStr, | ||||||
|     event_kind: Option<EventKind>, |     event_kind: Option<EventKind>, | ||||||
|     state_key_type: Option<&TokenStream>, |     state_key_type: Option<&TokenStream>, | ||||||
|  |     unsigned_type: Option<TokenStream>, | ||||||
|     aliases: &[&LitStr], |     aliases: &[&LitStr], | ||||||
|     ruma_common: &TokenStream, |     ruma_common: &TokenStream, | ||||||
| ) -> syn::Result<TokenStream> { | ) -> syn::Result<TokenStream> { | ||||||
| @ -402,6 +438,7 @@ fn generate_redacted_event_content<'a>( | |||||||
|         event_type, |         event_type, | ||||||
|         event_kind, |         event_kind, | ||||||
|         state_key_type, |         state_key_type, | ||||||
|  |         unsigned_type, | ||||||
|         aliases, |         aliases, | ||||||
|         ruma_common, |         ruma_common, | ||||||
|     ) |     ) | ||||||
| @ -536,6 +573,7 @@ fn generate_event_content_impl<'a>( | |||||||
|     event_type: &LitStr, |     event_type: &LitStr, | ||||||
|     event_kind: Option<EventKind>, |     event_kind: Option<EventKind>, | ||||||
|     state_key_type: Option<&TokenStream>, |     state_key_type: Option<&TokenStream>, | ||||||
|  |     unsigned_type: Option<TokenStream>, | ||||||
|     aliases: &[&'a LitStr], |     aliases: &[&'a LitStr], | ||||||
|     ruma_common: &TokenStream, |     ruma_common: &TokenStream, | ||||||
| ) -> syn::Result<TokenStream> { | ) -> syn::Result<TokenStream> { | ||||||
| @ -621,8 +659,12 @@ fn generate_event_content_impl<'a>( | |||||||
| 
 | 
 | ||||||
|         let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| { |         let state_event_content_impl = (event_kind == Some(EventKind::State)).then(|| { | ||||||
|             assert!(state_key_type.is_some()); |             assert!(state_key_type.is_some()); | ||||||
|  |             let unsigned_type = unsigned_type | ||||||
|  |                 .unwrap_or_else(|| quote! { #ruma_common::events::StateUnsigned<Self> }); | ||||||
|  | 
 | ||||||
|             quote! { |             quote! { | ||||||
|                 type StateKey = #state_key_type; |                 type StateKey = #state_key_type; | ||||||
|  |                 type Unsigned = #unsigned_type; | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -361,8 +361,13 @@ fn expand_content_enum( | |||||||
|     let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>(); |     let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     let sub_trait_name = format_ident!("{kind}Content"); |     let sub_trait_name = format_ident!("{kind}Content"); | ||||||
|     let state_event_content_impl = |     let state_event_content_impl = (kind == EventKind::State).then(|| { | ||||||
|         (kind == EventKind::State).then(|| quote! { type StateKey = String; }); |         quote! { | ||||||
|  |             type StateKey = String; | ||||||
|  |             // FIXME: Not actually used
 | ||||||
|  |             type Unsigned = #ruma_common::events::StateUnsigned<Self>; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     let from_impl = expand_from_impl(&ident, &content, variants); |     let from_impl = expand_from_impl(&ident, &content, variants); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user