events: Update state key types for all state events

… and make it mandatory to specify for state events.
This commit is contained in:
Jonas Platte 2022-04-20 16:11:14 +02:00 committed by Jonas Platte
parent d8b7886382
commit ae7461622c
30 changed files with 174 additions and 135 deletions

View File

@ -28,7 +28,7 @@
//! use serde::{Deserialize, Serialize}; //! use serde::{Deserialize, Serialize};
//! //!
//! #[derive(Clone, Debug, Deserialize, Serialize, EventContent)] //! #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
//! #[ruma_event(type = "org.example.event", kind = State)] //! #[ruma_event(type = "org.example.event", kind = State, state_key_type = String)]
//! pub struct ExampleContent { //! pub struct ExampleContent {
//! field: String, //! field: String,
//! } //! }
@ -113,6 +113,7 @@ pub mod _custom;
mod content; mod content;
mod enums; mod enums;
mod kinds; mod kinds;
mod state_key;
mod unsigned; mod unsigned;
/// Re-export of all the derives needed to create your own event types. /// Re-export of all the derives needed to create your own event types.
@ -170,6 +171,7 @@ pub use self::{
content::*, content::*,
enums::*, enums::*,
kinds::*, kinds::*,
state_key::EmptyStateKey,
unsigned::{MessageLikeUnsigned, RedactedUnsigned, StateUnsigned}, unsigned::{MessageLikeUnsigned, RedactedUnsigned, StateUnsigned},
}; };

View File

@ -12,7 +12,7 @@ use super::PolicyRuleEventContent;
/// This event type is used to apply rules to room entities. /// This event type is used to apply rules to room entities.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)] #[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.room", kind = State)] #[ruma_event(type = "m.policy.rule.room", kind = State, state_key_type = String)]
pub struct PolicyRuleRoomEventContent(pub PolicyRuleEventContent); pub struct PolicyRuleRoomEventContent(pub PolicyRuleEventContent);
#[cfg(test)] #[cfg(test)]

View File

@ -12,5 +12,5 @@ use super::PolicyRuleEventContent;
/// This event type is used to apply rules to server entities. /// This event type is used to apply rules to server entities.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)] #[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.server", kind = State)] #[ruma_event(type = "m.policy.rule.server", kind = State, state_key_type = String)]
pub struct PolicyRuleServerEventContent(pub PolicyRuleEventContent); pub struct PolicyRuleServerEventContent(pub PolicyRuleEventContent);

View File

@ -12,5 +12,5 @@ use super::PolicyRuleEventContent;
/// This event type is used to apply rules to user entities. /// This event type is used to apply rules to user entities.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)] #[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.user", kind = State)] #[ruma_event(type = "m.policy.rule.user", kind = State, state_key_type = String)]
pub struct PolicyRuleUserEventContent(pub PolicyRuleEventContent); pub struct PolicyRuleUserEventContent(pub PolicyRuleEventContent);

View File

@ -9,7 +9,7 @@ use crate::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventContent, EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, StateEventContent,
StateEventType, StateEventType,
}, },
OwnedRoomAliasId, RoomVersionId, OwnedRoomAliasId, OwnedServerName, RoomVersionId,
}; };
/// The content of an `m.room.aliases` event. /// The content of an `m.room.aliases` event.
@ -17,7 +17,7 @@ use crate::{
/// Informs the room about what room aliases it has been given. /// Informs the room about what room aliases it has been given.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.aliases", kind = State, custom_redacted)] #[ruma_event(type = "m.room.aliases", kind = State, state_key_type = OwnedServerName, custom_redacted)]
pub struct RoomAliasesEventContent { pub struct RoomAliasesEventContent {
/// A list of room aliases. /// A list of room aliases.
pub aliases: Vec<OwnedRoomAliasId>, pub aliases: Vec<OwnedRoomAliasId>,
@ -96,7 +96,7 @@ impl EventContent for RedactedRoomAliasesEventContent {
} }
impl StateEventContent for RedactedRoomAliasesEventContent { impl StateEventContent for RedactedRoomAliasesEventContent {
type StateKey = String; // Box<ServerName> type StateKey = OwnedServerName;
} }
// Since this redacted event has fields we leave the default `empty` method // Since this redacted event has fields we leave the default `empty` method

View File

@ -7,7 +7,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::ThumbnailInfo; use super::ThumbnailInfo;
use crate::MxcUri; use crate::{events::EmptyStateKey, MxcUri};
/// The content of an `m.room.avatar` event. /// The content of an `m.room.avatar` event.
/// ///
@ -16,7 +16,7 @@ use crate::MxcUri;
/// This can be displayed alongside the room information. /// This can be displayed alongside the room information.
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.avatar", kind = State)] #[ruma_event(type = "m.room.avatar", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomAvatarEventContent { pub struct RoomAvatarEventContent {
/// Information about the avatar image. /// Information about the avatar image.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]

View File

@ -5,14 +5,14 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::OwnedRoomAliasId; use crate::{events::EmptyStateKey, OwnedRoomAliasId};
/// The content of an `m.room.canonical_alias` event. /// The content of an `m.room.canonical_alias` event.
/// ///
/// Informs the room as to which alias is the canonical one. /// Informs the room as to which alias is the canonical one.
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.canonical_alias", kind = State)] #[ruma_event(type = "m.room.canonical_alias", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomCanonicalAliasEventContent { pub struct RoomCanonicalAliasEventContent {
/// The canonical alias. /// The canonical alias.
/// ///
@ -39,12 +39,15 @@ impl RoomCanonicalAliasEventContent {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{event_id, room_alias_id, room_id, user_id, MilliSecondsSinceUnixEpoch};
use js_int::uint; use js_int::uint;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::RoomCanonicalAliasEventContent; use super::RoomCanonicalAliasEventContent;
use crate::events::{OriginalStateEvent, StateUnsigned}; use crate::{
event_id,
events::{EmptyStateKey, OriginalStateEvent, StateUnsigned},
room_alias_id, room_id, user_id, MilliSecondsSinceUnixEpoch,
};
#[test] #[test]
fn serialization_with_optional_fields_as_none() { fn serialization_with_optional_fields_as_none() {
@ -57,7 +60,7 @@ mod tests {
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
room_id: room_id!("!dummy:example.com").to_owned(), room_id: room_id!("!dummy:example.com").to_owned(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: EmptyStateKey,
unsigned: StateUnsigned::default(), unsigned: StateUnsigned::default(),
}; };

View File

@ -5,7 +5,9 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{room::RoomType, OwnedEventId, OwnedRoomId, OwnedUserId, RoomVersionId}; use crate::{
events::EmptyStateKey, room::RoomType, OwnedEventId, OwnedRoomId, OwnedUserId, RoomVersionId,
};
/// The content of an `m.room.create` event. /// The content of an `m.room.create` event.
/// ///
@ -14,7 +16,7 @@ use crate::{room::RoomType, OwnedEventId, OwnedRoomId, OwnedUserId, RoomVersionI
/// It acts as the root of all other events. /// It acts as the root of all other events.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.create", kind = State)] #[ruma_event(type = "m.room.create", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomCreateEventContent { pub struct RoomCreateEventContent {
/// The `user_id` of the room creator. /// The `user_id` of the room creator.
/// ///
@ -85,11 +87,11 @@ fn default_room_version_id() -> RoomVersionId {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{user_id, RoomVersionId};
use matches::assert_matches; use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{RoomCreateEventContent, RoomType}; use super::{RoomCreateEventContent, RoomType};
use crate::{user_id, RoomVersionId};
#[test] #[test]
fn serialization() { fn serialization() {

View File

@ -6,14 +6,14 @@ use js_int::UInt;
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::events::EventEncryptionAlgorithm; use crate::events::{EmptyStateKey, EventEncryptionAlgorithm};
/// The content of an `m.room.encryption` event. /// The content of an `m.room.encryption` event.
/// ///
/// Defines how messages sent in this room should be encrypted. /// Defines how messages sent in this room should be encrypted.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.encryption", kind = State)] #[ruma_event(type = "m.room.encryption", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomEncryptionEventContent { pub struct RoomEncryptionEventContent {
/// The encryption algorithm to be used to encrypt messages sent in this room. /// The encryption algorithm to be used to encrypt messages sent in this room.
/// ///

View File

@ -5,7 +5,7 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{serde::StringEnum, PrivOwnedStr}; use crate::{events::EmptyStateKey, serde::StringEnum, PrivOwnedStr};
/// The content of an `m.room.guest_access` event. /// The content of an `m.room.guest_access` event.
/// ///
@ -15,7 +15,7 @@ use crate::{serde::StringEnum, PrivOwnedStr};
/// servers should act as if it is present and has the value `GuestAccess::Forbidden`. /// servers should act as if it is present and has the value `GuestAccess::Forbidden`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.guest_access", kind = State)] #[ruma_event(type = "m.room.guest_access", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomGuestAccessEventContent { pub struct RoomGuestAccessEventContent {
/// A policy for guest user access to a room. /// A policy for guest user access to a room.
pub guest_access: GuestAccess, pub guest_access: GuestAccess,

View File

@ -5,7 +5,7 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{serde::StringEnum, PrivOwnedStr}; use crate::{events::EmptyStateKey, serde::StringEnum, PrivOwnedStr};
/// The content of an `m.room.history_visibility` event. /// The content of an `m.room.history_visibility` event.
/// ///
@ -13,7 +13,7 @@ use crate::{serde::StringEnum, PrivOwnedStr};
/// before they joined. /// before they joined.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.history_visibility", kind = State)] #[ruma_event(type = "m.room.history_visibility", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomHistoryVisibilityEventContent { pub struct RoomHistoryVisibilityEventContent {
/// Who can see the room history. /// Who can see the room history.
#[ruma_event(skip_redaction)] #[ruma_event(skip_redaction)]

View File

@ -11,14 +11,14 @@ use serde::{
}; };
use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue}; use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
use crate::{serde::from_raw_json_value, OwnedRoomId, PrivOwnedStr}; use crate::{events::EmptyStateKey, serde::from_raw_json_value, OwnedRoomId, PrivOwnedStr};
/// The content of an `m.room.join_rules` event. /// The content of an `m.room.join_rules` event.
/// ///
/// Describes how users are allowed to join the room. /// Describes how users are allowed to join the room.
#[derive(Clone, Debug, Serialize, EventContent)] #[derive(Clone, Debug, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.join_rules", kind = State)] #[ruma_event(type = "m.room.join_rules", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomJoinRulesEventContent { pub struct RoomJoinRulesEventContent {
/// The type of rules used for users wishing to join this room. /// The type of rules used for users wishing to join this room.
#[ruma_event(skip_redaction)] #[ruma_event(skip_redaction)]
@ -238,10 +238,10 @@ impl<'de> Deserialize<'de> for AllowRule {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::room_id;
use matches::assert_matches; use matches::assert_matches;
use super::{AllowRule, JoinRule, OriginalSyncRoomJoinRulesEvent, RoomJoinRulesEventContent}; use super::{AllowRule, JoinRule, OriginalSyncRoomJoinRulesEvent, RoomJoinRulesEventContent};
use crate::room_id;
#[test] #[test]
fn deserialize() { fn deserialize() {

View File

@ -40,7 +40,7 @@ use crate::{
/// must be assumed as leave. /// must be assumed as leave.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.member", kind = State, custom_redacted)] #[ruma_event(type = "m.room.member", kind = State, state_key_type = OwnedUserId, custom_redacted)]
pub struct RoomMemberEventContent { pub struct RoomMemberEventContent {
/// The avatar URL for this user, if any. /// The avatar URL for this user, if any.
/// ///
@ -176,7 +176,7 @@ impl EventContent for RedactedRoomMemberEventContent {
} }
impl StateEventContent for RedactedRoomMemberEventContent { impl StateEventContent for RedactedRoomMemberEventContent {
type StateKey = String; // Box<UserId> type StateKey = OwnedUserId;
} }
// Since this redacted event has fields we leave the default `empty` method // Since this redacted event has fields we leave the default `empty` method
@ -329,7 +329,7 @@ fn membership_change(
content: &RoomMemberEventContent, content: &RoomMemberEventContent,
prev_content: Option<&RoomMemberEventContent>, prev_content: Option<&RoomMemberEventContent>,
sender: &UserId, sender: &UserId,
state_key: &str, state_key: &UserId,
) -> MembershipChange { ) -> MembershipChange {
use MembershipChange as Ch; use MembershipChange as Ch;
use MembershipState as St; use MembershipState as St;
@ -425,14 +425,16 @@ impl StrippedStateEvent<RoomMemberEventContent> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{server_name, server_signing_key_id, MilliSecondsSinceUnixEpoch};
use js_int::uint; use js_int::uint;
use maplit::btreemap; use maplit::btreemap;
use matches::assert_matches; use matches::assert_matches;
use serde_json::{from_value as from_json_value, json}; use serde_json::{from_value as from_json_value, json};
use super::{MembershipState, RoomMemberEventContent, SignedContent, ThirdPartyInvite}; use super::{MembershipState, RoomMemberEventContent, SignedContent, ThirdPartyInvite};
use crate::events::{OriginalStateEvent, StateUnsigned}; use crate::{
events::{OriginalStateEvent, StateUnsigned},
server_name, server_signing_key_id, MilliSecondsSinceUnixEpoch,
};
#[test] #[test]
fn serde_with_no_prev_content() { fn serde_with_no_prev_content() {
@ -445,7 +447,7 @@ mod tests {
"origin_server_ts": 1, "origin_server_ts": 1,
"room_id": "!n8f893n9:example.com", "room_id": "!n8f893n9:example.com",
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "example.com" "state_key": "@carl:example.com"
}); });
assert_matches!( assert_matches!(
@ -469,7 +471,7 @@ mod tests {
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1)) && origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1))
&& room_id == "!n8f893n9:example.com" && room_id == "!n8f893n9:example.com"
&& sender == "@carl:example.com" && sender == "@carl:example.com"
&& state_key == "example.com" && state_key == "@carl:example.com"
&& unsigned.is_empty() && unsigned.is_empty()
); );
} }
@ -485,7 +487,7 @@ mod tests {
"origin_server_ts": 1, "origin_server_ts": 1,
"room_id": "!n8f893n9:example.com", "room_id": "!n8f893n9:example.com",
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "example.com", "state_key": "@carl:example.com",
"unsigned": { "unsigned": {
"prev_content": { "prev_content": {
"membership": "join" "membership": "join"
@ -511,7 +513,7 @@ mod tests {
assert_eq!(ev.origin_server_ts, MilliSecondsSinceUnixEpoch(uint!(1))); assert_eq!(ev.origin_server_ts, MilliSecondsSinceUnixEpoch(uint!(1)));
assert_eq!(ev.room_id, "!n8f893n9:example.com"); assert_eq!(ev.room_id, "!n8f893n9:example.com");
assert_eq!(ev.sender, "@carl:example.com"); assert_eq!(ev.sender, "@carl:example.com");
assert_eq!(ev.state_key, "example.com"); assert_eq!(ev.state_key, "@carl:example.com");
assert_matches!( assert_matches!(
ev.unsigned, ev.unsigned,
@ -691,7 +693,7 @@ mod tests {
"origin_server_ts": 1, "origin_server_ts": 1,
"room_id": "!n8f893n9:example.com", "room_id": "!n8f893n9:example.com",
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "example.com" "state_key": "@carl:example.com"
}); });
assert_matches!( assert_matches!(
@ -717,7 +719,7 @@ mod tests {
&& room_id == "!n8f893n9:example.com" && room_id == "!n8f893n9:example.com"
&& sender == "@carl:example.com" && sender == "@carl:example.com"
&& authed == "@notcarl:example.com" && authed == "@notcarl:example.com"
&& state_key == "example.com" && state_key == "@carl:example.com"
&& unsigned.is_empty() && unsigned.is_empty()
); );
} }

View File

@ -5,14 +5,14 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::RoomName; use crate::{events::EmptyStateKey, RoomName};
/// The content of an `m.room.name` event. /// The content of an `m.room.name` event.
/// ///
/// The room name is a human-friendly string designed to be displayed to the end-user. /// The room name is a human-friendly string designed to be displayed to the end-user.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.room.name", kind = State)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.name", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomNameEventContent { pub struct RoomNameEventContent {
/// The name of the room. /// The name of the room.
#[serde(default, deserialize_with = "crate::serde::empty_string_as_none")] #[serde(default, deserialize_with = "crate::serde::empty_string_as_none")]
@ -30,13 +30,18 @@ impl RoomNameEventContent {
mod tests { mod tests {
use std::convert::TryInto; use std::convert::TryInto;
use crate::{event_id, room_id, serde::Raw, user_id, MilliSecondsSinceUnixEpoch};
use js_int::{int, uint}; use js_int::{int, uint};
use matches::assert_matches; use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::RoomNameEventContent; use super::RoomNameEventContent;
use crate::events::{OriginalStateEvent, StateUnsigned}; use crate::{
event_id,
events::{EmptyStateKey, OriginalStateEvent, StateUnsigned},
room_id,
serde::Raw,
user_id, MilliSecondsSinceUnixEpoch,
};
#[test] #[test]
fn serialization_with_optional_fields_as_none() { fn serialization_with_optional_fields_as_none() {
@ -46,7 +51,7 @@ mod tests {
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
room_id: room_id!("!n8f893n9:example.com").to_owned(), room_id: room_id!("!n8f893n9:example.com").to_owned(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: EmptyStateKey,
unsigned: StateUnsigned::default(), unsigned: StateUnsigned::default(),
}; };
@ -74,7 +79,7 @@ mod tests {
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
room_id: room_id!("!n8f893n9:example.com").to_owned(), room_id: room_id!("!n8f893n9:example.com").to_owned(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: EmptyStateKey,
unsigned: StateUnsigned { unsigned: StateUnsigned {
age: Some(int!(100)), age: Some(int!(100)),
prev_content: Some(RoomNameEventContent { name: "The old name".try_into().ok() }), prev_content: Some(RoomNameEventContent { name: "The old name".try_into().ok() }),

View File

@ -5,14 +5,14 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::OwnedEventId; use crate::{events::EmptyStateKey, OwnedEventId};
/// The content of an `m.room.pinned_events` event. /// The content of an `m.room.pinned_events` event.
/// ///
/// Used to "pin" particular events in a room for other participants to review later. /// Used to "pin" particular events in a room for other participants to review later.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.pinned_events", kind = State)] #[ruma_event(type = "m.room.pinned_events", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomPinnedEventsEventContent { pub struct RoomPinnedEventsEventContent {
/// An ordered list of event IDs to pin. /// An ordered list of event IDs to pin.
pub pinned: Vec<OwnedEventId>, pub pinned: Vec<OwnedEventId>,
@ -29,10 +29,11 @@ impl RoomPinnedEventsEventContent {
mod tests { mod tests {
use std::convert::TryInto; use std::convert::TryInto;
use crate::{server_name, EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId};
use super::RoomPinnedEventsEventContent; use super::RoomPinnedEventsEventContent;
use crate::events::{OriginalStateEvent, StateUnsigned}; use crate::{
events::{EmptyStateKey, OriginalStateEvent, StateUnsigned},
server_name, EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId,
};
#[test] #[test]
fn serialization_deserialization() { fn serialization_deserialization() {
@ -49,7 +50,7 @@ mod tests {
origin_server_ts: MilliSecondsSinceUnixEpoch(1_432_804_485_886_u64.try_into().unwrap()), origin_server_ts: MilliSecondsSinceUnixEpoch(1_432_804_485_886_u64.try_into().unwrap()),
room_id: RoomId::new(server_name), room_id: RoomId::new(server_name),
sender: UserId::new(server_name), sender: UserId::new(server_name),
state_key: "".into(), state_key: EmptyStateKey,
unsigned: StateUnsigned::default(), unsigned: StateUnsigned::default(),
}; };

View File

@ -9,7 +9,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
events::RoomEventType, events::{EmptyStateKey, RoomEventType},
power_levels::{default_power_level, NotificationPowerLevels}, power_levels::{default_power_level, NotificationPowerLevels},
OwnedUserId, UserId, OwnedUserId, UserId,
}; };
@ -19,7 +19,7 @@ use crate::{
/// Defines the power levels (privileges) of users in the room. /// Defines the power levels (privileges) of users in the room.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.power_levels", kind = State)] #[ruma_event(type = "m.room.power_levels", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomPowerLevelsEventContent { pub struct RoomPowerLevelsEventContent {
/// The level required to ban a user. /// The level required to ban a user.
/// ///
@ -288,14 +288,17 @@ impl From<RedactedRoomPowerLevelsEventContent> for RoomPowerLevels {
mod tests { mod tests {
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::{event_id, room_id, user_id, MilliSecondsSinceUnixEpoch};
use assign::assign; use assign::assign;
use js_int::{int, uint}; use js_int::{int, uint};
use maplit::btreemap; use maplit::btreemap;
use serde_json::{json, to_value as to_json_value}; use serde_json::{json, to_value as to_json_value};
use super::{default_power_level, NotificationPowerLevels, RoomPowerLevelsEventContent}; use super::{default_power_level, NotificationPowerLevels, RoomPowerLevelsEventContent};
use crate::events::{OriginalStateEvent, StateUnsigned}; use crate::{
event_id,
events::{EmptyStateKey, OriginalStateEvent, StateUnsigned},
room_id, user_id, MilliSecondsSinceUnixEpoch,
};
#[test] #[test]
fn serialization_with_optional_fields_as_none() { fn serialization_with_optional_fields_as_none() {
@ -319,7 +322,7 @@ mod tests {
room_id: room_id!("!n8f893n9:example.com").to_owned(), room_id: room_id!("!n8f893n9:example.com").to_owned(),
unsigned: StateUnsigned::default(), unsigned: StateUnsigned::default(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: EmptyStateKey,
}; };
let actual = to_json_value(&power_levels_event).unwrap(); let actual = to_json_value(&power_levels_event).unwrap();
@ -382,7 +385,7 @@ mod tests {
..StateUnsigned::default() ..StateUnsigned::default()
}, },
sender: user.to_owned(), sender: user.to_owned(),
state_key: "".into(), state_key: EmptyStateKey,
}; };
let actual = to_json_value(&power_levels_event).unwrap(); let actual = to_json_value(&power_levels_event).unwrap();

View File

@ -6,14 +6,14 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use wildmatch::WildMatch; use wildmatch::WildMatch;
use crate::ServerName; use crate::{events::EmptyStateKey, ServerName};
/// The content of an `m.room.server_acl` event. /// The content of an `m.room.server_acl` event.
/// ///
/// An event to indicate which servers are permitted to participate in the room. /// An event to indicate which servers are permitted to participate in the room.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.server_acl", kind = State)] #[ruma_event(type = "m.room.server_acl", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomServerAclEventContent { pub struct RoomServerAclEventContent {
/// Whether to allow server names that are IP address literals. /// Whether to allow server names that are IP address literals.
/// ///
@ -64,11 +64,10 @@ impl RoomServerAclEventContent {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::server_name;
use serde_json::{from_value as from_json_value, json}; use serde_json::{from_value as from_json_value, json};
use super::RoomServerAclEventContent; use super::RoomServerAclEventContent;
use crate::events::OriginalStateEvent; use crate::{events::OriginalStateEvent, server_name};
#[test] #[test]
fn default_values() { fn default_values() {

View File

@ -16,7 +16,7 @@ use crate::serde::Base64;
/// Any user who can present that signature may use this invitation to join the target room. /// Any user who can present that signature may use this invitation to join the target room.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.third_party_invite", kind = State)] #[ruma_event(type = "m.room.third_party_invite", kind = State, state_key_type = String)]
pub struct RoomThirdPartyInviteEventContent { pub struct RoomThirdPartyInviteEventContent {
/// A user-readable string which represents the user who has been invited. /// A user-readable string which represents the user who has been invited.
/// ///

View File

@ -5,14 +5,14 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::OwnedRoomId; use crate::{events::EmptyStateKey, OwnedRoomId};
/// The content of an `m.room.tombstone` event. /// The content of an `m.room.tombstone` event.
/// ///
/// A state event signifying that a room has been upgraded to a different room version, and that /// A state event signifying that a room has been upgraded to a different room version, and that
/// clients should go there. /// clients should go there.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.room.tombstone", kind = State)] #[ruma_event(type = "m.room.tombstone", kind = State, state_key_type = EmptyStateKey)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct RoomTombstoneEventContent { pub struct RoomTombstoneEventContent {
/// A server-defined message. /// A server-defined message.

View File

@ -5,12 +5,14 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::events::EmptyStateKey;
/// The content of an `m.room.topic` event. /// The content of an `m.room.topic` event.
/// ///
/// A topic is a short message detailing what is currently being discussed in the room. /// A topic is a short message detailing what is currently being discussed in the room.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.room.topic", kind = State)] #[ruma_event(type = "m.room.topic", kind = State, state_key_type = EmptyStateKey)]
pub struct RoomTopicEventContent { pub struct RoomTopicEventContent {
/// The topic text. /// The topic text.
pub topic: String, pub topic: String,

View File

@ -5,7 +5,7 @@
use ruma_macros::{Event, EventContent}; use ruma_macros::{Event, EventContent};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{MilliSecondsSinceUnixEpoch, OwnedServerName, OwnedUserId}; use crate::{MilliSecondsSinceUnixEpoch, OwnedRoomId, OwnedServerName, OwnedUserId};
/// The content of an `m.space.child` event. /// The content of an `m.space.child` event.
/// ///
@ -16,7 +16,7 @@ use crate::{MilliSecondsSinceUnixEpoch, OwnedServerName, OwnedUserId};
/// which gives a list of candidate servers that can be used to join the room. /// which gives a list of candidate servers that can be used to join the room.
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.space.child", kind = State)] #[ruma_event(type = "m.space.child", kind = State, state_key_type = OwnedRoomId)]
pub struct SpaceChildEventContent { pub struct SpaceChildEventContent {
/// List of candidate servers that can be used to join the room. /// List of candidate servers that can be used to join the room.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -71,12 +71,12 @@ pub struct HierarchySpaceChildEvent {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{server_name, user_id, MilliSecondsSinceUnixEpoch};
use js_int::uint; use js_int::uint;
use matches::assert_matches; use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{HierarchySpaceChildEvent, SpaceChildEventContent}; use super::{HierarchySpaceChildEvent, SpaceChildEventContent};
use crate::{server_name, user_id, MilliSecondsSinceUnixEpoch};
#[test] #[test]
fn space_child_serialization() { fn space_child_serialization() {

View File

@ -5,7 +5,7 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::OwnedServerName; use crate::{OwnedRoomId, OwnedServerName};
/// The content of an `m.space.parent` event. /// The content of an `m.space.parent` event.
/// ///
@ -16,7 +16,7 @@ use crate::OwnedServerName;
/// parent. /// parent.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.space.parent", kind = State)] #[ruma_event(type = "m.space.parent", kind = State, state_key_type = OwnedRoomId)]
pub struct SpaceParentEventContent { pub struct SpaceParentEventContent {
/// List of candidate servers that can be used to join the room. /// List of candidate servers that can be used to join the room.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -41,10 +41,10 @@ impl SpaceParentEventContent {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::server_name;
use serde_json::{json, to_value as to_json_value}; use serde_json::{json, to_value as to_json_value};
use super::SpaceParentEventContent; use super::SpaceParentEventContent;
use crate::server_name;
#[test] #[test]
fn space_parent_serialization() { fn space_parent_serialization() {

View File

@ -0,0 +1,38 @@
use serde::{
de::{self, Deserialize, Deserializer, Unexpected},
Serialize, Serializer,
};
/// A type that can be used as the `state_key` for event types where that field is always empty.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(clippy::exhaustive_structs)]
pub struct EmptyStateKey;
impl AsRef<str> for EmptyStateKey {
fn as_ref(&self) -> &str {
""
}
}
impl<'de> Deserialize<'de> for EmptyStateKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = crate::serde::deserialize_cow_str(deserializer)?;
if s.is_empty() {
Ok(EmptyStateKey)
} else {
Err(de::Error::invalid_value(Unexpected::Str(&s), &"an empty string"))
}
}
}
impl Serialize for EmptyStateKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str("")
}
}

View File

@ -70,7 +70,7 @@ fn aliases_event() -> JsonValue {
"event_id": "$152037280074GZeOm:localhost", "event_id": "$152037280074GZeOm:localhost",
"origin_server_ts": 1, "origin_server_ts": 1,
"sender": "@example:localhost", "sender": "@example:localhost",
"state_key": "", "state_key": "room.com",
"room_id": "!room:room.com", "room_id": "!room:room.com",
"type": "m.room.aliases", "type": "m.room.aliases",
"unsigned": { "unsigned": {
@ -87,7 +87,7 @@ fn aliases_event_sync() -> JsonValue {
"event_id": "$152037280074GZeOm:localhost", "event_id": "$152037280074GZeOm:localhost",
"origin_server_ts": 1, "origin_server_ts": 1,
"sender": "@example:localhost", "sender": "@example:localhost",
"state_key": "", "state_key": "example.com",
"type": "m.room.aliases", "type": "m.room.aliases",
"unsigned": { "unsigned": {
"age": 1 "age": 1
@ -172,21 +172,14 @@ fn message_event_sync_deserialization() {
fn aliases_event_sync_deserialization() { fn aliases_event_sync_deserialization() {
let json_data = aliases_event_sync(); let json_data = aliases_event_sync();
assert_matches!( let ev = match from_json_value::<AnySyncRoomEvent>(json_data) {
from_json_value::<AnySyncRoomEvent>(json_data), Ok(AnySyncRoomEvent::State(AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(
Ok(AnySyncRoomEvent::State( ev,
AnySyncStateEvent::RoomAliases(SyncStateEvent::Original( )))) => ev,
OriginalSyncStateEvent { res => panic!("unexpected result: {:?}", res),
content: RoomAliasesEventContent { };
aliases,
.. assert_eq!(ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
},
..
},
))
))
if aliases == vec![ room_alias_id!("#somewhere:localhost") ]
);
} }
#[test] #[test]
@ -253,7 +246,7 @@ fn alias_room_event_deserialization() {
.. ..
})) }))
)) ))
if aliases == vec![ room_alias_id!("#somewhere:localhost") ] if aliases == vec![room_alias_id!("#somewhere:localhost")]
); );
} }
@ -295,7 +288,7 @@ fn alias_event_deserialization() {
.. ..
})) }))
)) ))
if aliases == vec![ room_alias_id!("#somewhere:localhost") ] if aliases == vec![room_alias_id!("#somewhere:localhost")]
); );
} }
@ -306,7 +299,7 @@ fn alias_event_field_access() {
assert_matches!( assert_matches!(
from_json_value::<AnyRoomEvent>(json_data.clone()), from_json_value::<AnyRoomEvent>(json_data.clone()),
Ok(AnyRoomEvent::State(state_event)) Ok(AnyRoomEvent::State(state_event))
if state_event.state_key() == "" if state_event.state_key() == "room.com"
&& state_event.room_id() == room_id!("!room:room.com") && state_event.room_id() == room_id!("!room:room.com")
&& state_event.event_id() == event_id!("$152037280074GZeOm:localhost") && state_event.event_id() == event_id!("$152037280074GZeOm:localhost")
&& state_event.sender() == user_id!("@example:localhost") && state_event.sender() == user_id!("@example:localhost")

View File

@ -15,8 +15,7 @@ fn deserialize_initial_state_event() {
"content": { "name": "foo" } "content": { "name": "foo" }
})) }))
.unwrap(), .unwrap(),
AnyInitialStateEvent::RoomName(InitialStateEvent { content, state_key}) AnyInitialStateEvent::RoomName(InitialStateEvent { content, .. })
if content.name == Some(Box::<RoomName>::try_from("foo").unwrap()) if content.name == Some(Box::<RoomName>::try_from("foo").unwrap())
&& state_key.is_empty()
); );
} }

View File

@ -16,7 +16,7 @@ use ruma_common::{
RedactedMessageLikeEvent, RedactedSyncMessageLikeEvent, RedactedSyncStateEvent, RedactedMessageLikeEvent, RedactedSyncMessageLikeEvent, RedactedSyncStateEvent,
RedactedUnsigned, SyncMessageLikeEvent, SyncStateEvent, RedactedUnsigned, SyncMessageLikeEvent, SyncStateEvent,
}, },
room_id, user_id, MilliSecondsSinceUnixEpoch, RoomVersionId, room_id, server_name, user_id, MilliSecondsSinceUnixEpoch, RoomVersionId,
}; };
use serde_json::{ use serde_json::{
from_value as from_json_value, json, to_value as to_json_value, from_value as from_json_value, json, to_value as to_json_value,
@ -64,7 +64,7 @@ fn redacted_aliases_event_serialize_no_content() {
let redacted = RedactedSyncStateEvent { let redacted = RedactedSyncStateEvent {
content: RedactedRoomAliasesEventContent::default(), content: RedactedRoomAliasesEventContent::default(),
event_id: event_id!("$h29iv0s8:example.com").to_owned(), event_id: event_id!("$h29iv0s8:example.com").to_owned(),
state_key: "".into(), state_key: server_name!("example.com").to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
unsigned: RedactedUnsigned::default(), unsigned: RedactedUnsigned::default(),
@ -72,7 +72,7 @@ fn redacted_aliases_event_serialize_no_content() {
let expected = json!({ let expected = json!({
"event_id": "$h29iv0s8:example.com", "event_id": "$h29iv0s8:example.com",
"state_key": "", "state_key": "example.com",
"origin_server_ts": 1, "origin_server_ts": 1,
"sender": "@carl:example.com", "sender": "@carl:example.com",
"type": "m.room.aliases", "type": "m.room.aliases",
@ -87,7 +87,7 @@ fn redacted_aliases_event_serialize_with_content() {
let redacted = RedactedSyncStateEvent { let redacted = RedactedSyncStateEvent {
content: RedactedRoomAliasesEventContent::new_v1(vec![]), content: RedactedRoomAliasesEventContent::new_v1(vec![]),
event_id: event_id!("$h29iv0s8:example.com").to_owned(), event_id: event_id!("$h29iv0s8:example.com").to_owned(),
state_key: "".to_owned(), state_key: server_name!("example.com").to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
unsigned: RedactedUnsigned::default(), unsigned: RedactedUnsigned::default(),
@ -98,7 +98,7 @@ fn redacted_aliases_event_serialize_with_content() {
"aliases": [] "aliases": []
}, },
"event_id": "$h29iv0s8:example.com", "event_id": "$h29iv0s8:example.com",
"state_key": "", "state_key": "example.com",
"origin_server_ts": 1, "origin_server_ts": 1,
"sender": "@carl:example.com", "sender": "@carl:example.com",
"type": "m.room.aliases", "type": "m.room.aliases",
@ -206,7 +206,7 @@ fn redacted_state_event_deserialize() {
"event_id": "$h29iv0s8:example.com", "event_id": "$h29iv0s8:example.com",
"origin_server_ts": 1, "origin_server_ts": 1,
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "hello there", "state_key": "",
"unsigned": unsigned(), "unsigned": unsigned(),
"type": "m.room.create", "type": "m.room.create",
}); });
@ -220,13 +220,11 @@ fn redacted_state_event_deserialize() {
creator, .. creator, ..
}, },
event_id, event_id,
state_key,
unsigned, unsigned,
.. ..
}), }),
)) if event_id == event_id!("$h29iv0s8:example.com") )) if event_id == event_id!("$h29iv0s8:example.com")
&& unsigned.redacted_because.is_some() && unsigned.redacted_because.is_some()
&& state_key == "hello there"
&& creator == user_id!("@carl:example.com") && creator == user_id!("@carl:example.com")
) )
} }

View File

@ -14,7 +14,7 @@ use ruma_common::{
}, },
mxc_uri, room_alias_id, room_id, mxc_uri, room_alias_id, room_id,
serde::Raw, serde::Raw,
user_id, MilliSecondsSinceUnixEpoch, server_name, user_id, MilliSecondsSinceUnixEpoch,
}; };
use serde_json::{ use serde_json::{
from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue, from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
@ -29,7 +29,7 @@ fn aliases_event_with_prev_content() -> JsonValue {
"origin_server_ts": 1, "origin_server_ts": 1,
"room_id": "!roomid:room.com", "room_id": "!roomid:room.com",
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "", "state_key": "room.com",
"type": "m.room.aliases", "type": "m.room.aliases",
"unsigned": { "unsigned": {
"prev_content": { "prev_content": {
@ -49,7 +49,7 @@ fn serialize_aliases_with_prev_content() {
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
room_id: room_id!("!roomid:room.com").to_owned(), room_id: room_id!("!roomid:room.com").to_owned(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: server_name!("room.com").to_owned(),
unsigned: assign!(StateUnsigned::default(), { unsigned: assign!(StateUnsigned::default(), {
prev_content: Some(RoomAliasesEventContent::new(vec![room_alias_id!( prev_content: Some(RoomAliasesEventContent::new(vec![room_alias_id!(
"#inner:localhost" "#inner:localhost"
@ -74,7 +74,7 @@ fn serialize_aliases_without_prev_content() {
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
room_id: room_id!("!roomid:room.com").to_owned(), room_id: room_id!("!roomid:room.com").to_owned(),
sender: user_id!("@carl:example.com").to_owned(), sender: user_id!("@carl:example.com").to_owned(),
state_key: "".into(), state_key: server_name!("example.com").to_owned(),
unsigned: StateUnsigned::default(), unsigned: StateUnsigned::default(),
}; };
@ -87,7 +87,7 @@ fn serialize_aliases_without_prev_content() {
"origin_server_ts": 1, "origin_server_ts": 1,
"room_id": "!roomid:room.com", "room_id": "!roomid:room.com",
"sender": "@carl:example.com", "sender": "@carl:example.com",
"state_key": "", "state_key": "example.com",
"type": "m.room.aliases", "type": "m.room.aliases",
}); });
@ -122,18 +122,17 @@ fn deserialize_aliases_with_prev_content() {
origin_server_ts, origin_server_ts,
room_id, room_id,
sender, sender,
state_key,
unsigned: StateUnsigned { unsigned: StateUnsigned {
prev_content: Some(prev_content), prev_content: Some(prev_content),
.. ..
}, },
..
})) if content.aliases == vec![room_alias_id!("#somewhere:localhost")] })) if content.aliases == vec![room_alias_id!("#somewhere:localhost")]
&& event_id == event_id!("$h29iv0s8:example.com") && event_id == event_id!("$h29iv0s8:example.com")
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1)) && origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1))
&& prev_content.aliases == vec![room_alias_id!("#inner:localhost")] && prev_content.aliases == vec![room_alias_id!("#inner:localhost")]
&& room_id == room_id!("!roomid:room.com") && room_id == room_id!("!roomid:room.com")
&& sender == user_id!("@carl:example.com") && sender == user_id!("@carl:example.com")
&& state_key.is_empty()
); );
} }
@ -150,17 +149,16 @@ fn deserialize_aliases_sync_with_room_id() {
event_id, event_id,
origin_server_ts, origin_server_ts,
sender, sender,
state_key,
unsigned: StateUnsigned { unsigned: StateUnsigned {
prev_content: Some(prev_content), prev_content: Some(prev_content),
.. ..
}, },
..
})) if content.aliases == vec![room_alias_id!("#somewhere:localhost")] })) if content.aliases == vec![room_alias_id!("#somewhere:localhost")]
&& event_id == event_id!("$h29iv0s8:example.com") && event_id == event_id!("$h29iv0s8:example.com")
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1)) && origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1))
&& prev_content.aliases == vec![room_alias_id!("#inner:localhost")] && prev_content.aliases == vec![room_alias_id!("#inner:localhost")]
&& sender == user_id!("@carl:example.com") && sender == user_id!("@carl:example.com")
&& state_key.is_empty()
); );
} }
@ -204,13 +202,12 @@ fn deserialize_avatar_without_prev_content() {
origin_server_ts, origin_server_ts,
room_id, room_id,
sender, sender,
state_key,
unsigned, unsigned,
..
})) if event_id == event_id!("$h29iv0s8:example.com") })) if event_id == event_id!("$h29iv0s8:example.com")
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1)) && origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1))
&& room_id == room_id!("!roomid:room.com") && room_id == room_id!("!roomid:room.com")
&& sender == user_id!("@carl:example.com") && sender == user_id!("@carl:example.com")
&& state_key.is_empty()
&& matches!( && matches!(
info.as_ref(), info.as_ref(),
ImageInfo { ImageInfo {
@ -288,24 +285,17 @@ fn deserialize_full_event_convert_to_sync() {
let json_data = aliases_event_with_prev_content(); let json_data = aliases_event_with_prev_content();
let full_ev: AnyStateEvent = from_json_value(json_data).unwrap(); let full_ev: AnyStateEvent = from_json_value(json_data).unwrap();
let sync_ev = match AnySyncStateEvent::from(full_ev) {
AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(ev)) => ev,
ev => panic!("unexpected variant for event {:?}", ev),
};
assert_matches!( assert_eq!(sync_ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
AnySyncStateEvent::from(full_ev), assert_eq!(sync_ev.event_id, "$h29iv0s8:example.com");
AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(OriginalSyncStateEvent { assert_eq!(sync_ev.origin_server_ts, MilliSecondsSinceUnixEpoch(uint!(1)));
content, assert_eq!(
event_id, sync_ev.unsigned.prev_content.unwrap().aliases,
origin_server_ts, vec![room_alias_id!("#inner:localhost")]
sender,
state_key,
unsigned: StateUnsigned {
prev_content: Some(prev_content),
..
}
})) if content.aliases == vec![room_alias_id!("#somewhere:localhost")]
&& event_id == "$h29iv0s8:example.com"
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(1))
&& prev_content.aliases == vec![room_alias_id!("#inner:localhost")]
&& sender == "@carl:example.com"
&& state_key.is_empty()
); );
assert_eq!(sync_ev.sender, "@carl:example.com");
} }

View File

@ -4,7 +4,7 @@ use js_int::uint;
use ruma_common::{ use ruma_common::{
events::{ events::{
room::{join_rules::JoinRule, topic::RoomTopicEventContent}, room::{join_rules::JoinRule, topic::RoomTopicEventContent},
AnyStrippedStateEvent, StrippedStateEvent, AnyStrippedStateEvent, EmptyStateKey, StrippedStateEvent,
}, },
mxc_uri, user_id, RoomName, mxc_uri, user_id, RoomName,
}; };
@ -14,7 +14,7 @@ use serde_json::{from_value as from_json_value, json, to_value as to_json_value}
fn serialize_stripped_state_event_any_content() { fn serialize_stripped_state_event_any_content() {
let event = StrippedStateEvent { let event = StrippedStateEvent {
content: RoomTopicEventContent::new("Testing room".into()), content: RoomTopicEventContent::new("Testing room".into()),
state_key: "".into(), state_key: EmptyStateKey,
sender: user_id!("@example:localhost").to_owned(), sender: user_id!("@example:localhost").to_owned(),
}; };
@ -79,7 +79,6 @@ fn deserialize_stripped_state_events() {
match event { match event {
AnyStrippedStateEvent::RoomName(event) => { AnyStrippedStateEvent::RoomName(event) => {
assert_eq!(event.content.name, Some(Box::<RoomName>::try_from("Ruma").unwrap())); assert_eq!(event.content.name, Some(Box::<RoomName>::try_from("Ruma").unwrap()));
assert_eq!(event.state_key, "");
assert_eq!(event.sender.to_string(), "@example:localhost"); assert_eq!(event.sender.to_string(), "@example:localhost");
} }
_ => unreachable!(), _ => unreachable!(),
@ -89,7 +88,6 @@ fn deserialize_stripped_state_events() {
match event { match event {
AnyStrippedStateEvent::RoomJoinRules(event) => { AnyStrippedStateEvent::RoomJoinRules(event) => {
assert_eq!(event.content.join_rule, JoinRule::Public); assert_eq!(event.content.join_rule, JoinRule::Public);
assert_eq!(event.state_key, "");
assert_eq!(event.sender.to_string(), "@example:localhost"); assert_eq!(event.sender.to_string(), "@example:localhost");
} }
_ => unreachable!(), _ => unreachable!(),
@ -106,7 +104,6 @@ fn deserialize_stripped_state_events() {
assert_eq!(image_info.size.unwrap(), uint!(1024)); assert_eq!(image_info.size.unwrap(), uint!(1024));
assert_eq!(image_info.thumbnail_info.unwrap().size.unwrap(), uint!(32)); assert_eq!(image_info.thumbnail_info.unwrap().size.unwrap(), uint!(32));
assert_eq!(event.content.url.unwrap(), mxc_uri!("mxc://example.com/iMag3")); assert_eq!(event.content.url.unwrap(), mxc_uri!("mxc://example.com/iMag3"));
assert_eq!(event.state_key, "");
assert_eq!(event.sender.to_string(), "@example:localhost"); assert_eq!(event.sender.to_string(), "@example:localhost");
} }
_ => unreachable!(), _ => unreachable!(),

View File

@ -2,7 +2,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.macro.test", kind = State)] #[ruma_event(type = "m.macro.test", kind = State, state_key_type = String)]
pub struct MacroTestContent { pub struct MacroTestContent {
pub url: String, pub url: String,
} }

View File

@ -177,7 +177,12 @@ pub fn expand_event_content(
let state_key_types: Vec<_> = let state_key_types: Vec<_> =
content_attr.iter().filter_map(|attrs| attrs.get_state_key_type()).collect(); content_attr.iter().filter_map(|attrs| attrs.get_state_key_type()).collect();
let state_key_type = match (event_kind, state_key_types.as_slice()) { let state_key_type = match (event_kind, state_key_types.as_slice()) {
(Some(EventKind::State), []) => Some(quote! { ::std::string::String }), (Some(EventKind::State), []) => {
return Err(syn::Error::new(
Span::call_site(),
"no state_key_type attribute found, please specify one",
));
}
(Some(EventKind::State), [ty]) => Some(quote! { #ty }), (Some(EventKind::State), [ty]) => Some(quote! { #ty }),
(Some(EventKind::State), _) => { (Some(EventKind::State), _) => {
return Err(syn::Error::new( return Err(syn::Error::new(