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