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,
|
||||
MessageLikeEventType, RedactContent, RedactedEventContent, RedactedMessageLikeEventContent,
|
||||
RedactedStateEventContent, RoomAccountDataEventContent, RoomAccountDataEventType,
|
||||
StateEventContent, StateEventType, ToDeviceEventContent, ToDeviceEventType,
|
||||
StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent, ToDeviceEventType,
|
||||
};
|
||||
use crate::RoomVersionId;
|
||||
|
||||
@ -80,6 +80,7 @@ impl RedactedMessageLikeEventContent for CustomMessageLikeEventContent {}
|
||||
custom_room_event_content!(CustomStateEventContent, StateEventType);
|
||||
impl StateEventContent for CustomStateEventContent {
|
||||
type StateKey = String;
|
||||
type Unsigned = StateUnsigned<Self>;
|
||||
}
|
||||
impl RedactedStateEventContent for CustomStateEventContent {}
|
||||
|
||||
|
@ -3,11 +3,11 @@ use std::fmt;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
use crate::serde::Raw;
|
||||
use crate::serde::{CanBeEmpty, Raw};
|
||||
|
||||
use super::{
|
||||
EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType,
|
||||
RoomAccountDataEventType, StateEventType, ToDeviceEventType,
|
||||
RoomAccountDataEventType, StateEventType, StateUnsignedFromParts, ToDeviceEventType,
|
||||
};
|
||||
|
||||
/// The base trait that all event content types implement.
|
||||
@ -158,6 +158,9 @@ pub trait RedactedMessageLikeEventContent: MessageLikeEventContent + RedactedEve
|
||||
pub trait StateEventContent: EventContent<EventType = StateEventType> {
|
||||
/// The type of the event's `state_key` field.
|
||||
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.
|
||||
|
@ -9,7 +9,7 @@ use super::{
|
||||
GlobalAccountDataEventContent, MessageLikeEventContent, MessageLikeEventType,
|
||||
MessageLikeUnsigned, Redact, RedactContent, RedactedMessageLikeEventContent,
|
||||
RedactedStateEventContent, RedactedUnsigned, RedactionDeHelper, RoomAccountDataEventContent,
|
||||
StateEventContent, StateEventType, StateUnsigned, ToDeviceEventContent,
|
||||
StateEventContent, StateEventType, ToDeviceEventContent,
|
||||
};
|
||||
use crate::{
|
||||
serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId,
|
||||
@ -205,7 +205,7 @@ pub struct OriginalStateEvent<C: StateEventContent> {
|
||||
pub state_key: C::StateKey,
|
||||
|
||||
/// 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`.
|
||||
@ -233,7 +233,7 @@ pub struct OriginalSyncStateEvent<C: StateEventContent> {
|
||||
pub state_key: C::StateKey,
|
||||
|
||||
/// 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.
|
||||
|
@ -7,7 +7,7 @@ use serde_json::value::RawValue as RawJsonValue;
|
||||
use crate::{
|
||||
events::{
|
||||
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
|
||||
RedactedStateEventContent, StateEventContent, StateEventType,
|
||||
RedactedStateEventContent, StateEventContent, StateEventType, StateUnsigned,
|
||||
},
|
||||
OwnedRoomAliasId, OwnedServerName, RoomVersionId,
|
||||
};
|
||||
@ -97,6 +97,8 @@ impl EventContent for RedactedRoomAliasesEventContent {
|
||||
|
||||
impl StateEventContent for RedactedRoomAliasesEventContent {
|
||||
type StateKey = OwnedServerName;
|
||||
// FIXME: Not actually used
|
||||
type Unsigned = StateUnsigned<Self>;
|
||||
}
|
||||
|
||||
impl RedactedStateEventContent for RedactedRoomAliasesEventContent {}
|
||||
|
@ -11,7 +11,7 @@ use serde_json::value::RawValue as RawJsonValue;
|
||||
use crate::{
|
||||
events::{
|
||||
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
|
||||
RedactedStateEventContent, StateEventContent, StateEventType,
|
||||
RedactedStateEventContent, StateEventContent, StateEventType, StateUnsigned,
|
||||
},
|
||||
serde::StringEnum,
|
||||
OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, PrivOwnedStr,
|
||||
@ -202,6 +202,8 @@ impl EventContent for RedactedRoomMemberEventContent {
|
||||
|
||||
impl StateEventContent for RedactedRoomMemberEventContent {
|
||||
type StateKey = OwnedUserId;
|
||||
// FIXME: Not actually used
|
||||
type Unsigned = StateUnsigned<Self>;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
|
||||
11 | #[ruma_event(event = "m.macro.test", kind = State)]
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! Implementations of the EventContent derive macro.
|
||||
#![allow(clippy::too_many_arguments)] // FIXME
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
@ -23,6 +24,8 @@ mod kw {
|
||||
syn::custom_keyword!(type_fragment);
|
||||
// The type to use for a state events' `state_key` field.
|
||||
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.
|
||||
syn::custom_keyword!(alias);
|
||||
}
|
||||
@ -42,6 +45,8 @@ enum EventStructMeta {
|
||||
|
||||
StateKeyType(Box<Type>),
|
||||
|
||||
UnsignedType(Box<Type>),
|
||||
|
||||
/// Variant that holds alternate event type accepted for deserialization.
|
||||
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> {
|
||||
match self {
|
||||
Self::Alias(t) => Some(t),
|
||||
@ -94,6 +106,10 @@ impl Parse for EventStructMeta {
|
||||
let _: kw::state_key_type = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
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) {
|
||||
let _: kw::alias = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
@ -151,6 +167,10 @@ impl MetaAttrs {
|
||||
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> {
|
||||
self.0.iter().filter_map(|a| a.get_alias())
|
||||
}
|
||||
@ -191,7 +211,7 @@ pub fn expand_event_content(
|
||||
_ => {
|
||||
return Err(syn::Error::new(
|
||||
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(
|
||||
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 fields = match &input.data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields.iter(),
|
||||
@ -280,6 +313,7 @@ pub fn expand_event_content(
|
||||
event_type,
|
||||
event_kind,
|
||||
state_key_type.as_ref(),
|
||||
unsigned_type.clone(),
|
||||
&aliases,
|
||||
ruma_common,
|
||||
)
|
||||
@ -292,6 +326,7 @@ pub fn expand_event_content(
|
||||
event_type,
|
||||
event_kind,
|
||||
state_key_type.as_ref(),
|
||||
unsigned_type,
|
||||
&aliases,
|
||||
ruma_common,
|
||||
)
|
||||
@ -317,6 +352,7 @@ fn generate_redacted_event_content<'a>(
|
||||
event_type: &LitStr,
|
||||
event_kind: Option<EventKind>,
|
||||
state_key_type: Option<&TokenStream>,
|
||||
unsigned_type: Option<TokenStream>,
|
||||
aliases: &[&LitStr],
|
||||
ruma_common: &TokenStream,
|
||||
) -> syn::Result<TokenStream> {
|
||||
@ -402,6 +438,7 @@ fn generate_redacted_event_content<'a>(
|
||||
event_type,
|
||||
event_kind,
|
||||
state_key_type,
|
||||
unsigned_type,
|
||||
aliases,
|
||||
ruma_common,
|
||||
)
|
||||
@ -536,6 +573,7 @@ fn generate_event_content_impl<'a>(
|
||||
event_type: &LitStr,
|
||||
event_kind: Option<EventKind>,
|
||||
state_key_type: Option<&TokenStream>,
|
||||
unsigned_type: Option<TokenStream>,
|
||||
aliases: &[&'a LitStr],
|
||||
ruma_common: &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(|| {
|
||||
assert!(state_key_type.is_some());
|
||||
let unsigned_type = unsigned_type
|
||||
.unwrap_or_else(|| quote! { #ruma_common::events::StateUnsigned<Self> });
|
||||
|
||||
quote! {
|
||||
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 sub_trait_name = format_ident!("{kind}Content");
|
||||
let state_event_content_impl =
|
||||
(kind == EventKind::State).then(|| quote! { type StateKey = String; });
|
||||
let state_event_content_impl = (kind == EventKind::State).then(|| {
|
||||
quote! {
|
||||
type StateKey = String;
|
||||
// FIXME: Not actually used
|
||||
type Unsigned = #ruma_common::events::StateUnsigned<Self>;
|
||||
}
|
||||
});
|
||||
|
||||
let from_impl = expand_from_impl(&ident, &content, variants);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user