diff --git a/crates/ruma-common/src/events/enums.rs b/crates/ruma-common/src/events/enums.rs index 0d82416f..31711791 100644 --- a/crates/ruma-common/src/events/enums.rs +++ b/crates/ruma-common/src/events/enums.rs @@ -177,8 +177,8 @@ impl AnyTimelineEvent { /// Returns this event's `transaction_id` from inside `unsigned`, if there is one. pub fn transaction_id(&self) -> Option<&TransactionId>; - /// Returns this event's `relations` from inside `unsigned`, if that field exists. - pub fn relations(&self) -> Option<&BundledRelations>; + /// Returns this event's `relations` from inside `unsigned`. + pub fn relations(&self) -> &BundledRelations; } } @@ -210,7 +210,7 @@ impl AnySyncTimelineEvent { pub fn transaction_id(&self) -> Option<&TransactionId>; /// Returns this event's `relations` from inside `unsigned`, if that field exists. - pub fn relations(&self) -> Option<&BundledRelations>; + pub fn relations(&self) -> &BundledRelations; } /// Converts `self` to an `AnyTimelineEvent` by adding the given a room ID. diff --git a/crates/ruma-common/src/events/relation.rs b/crates/ruma-common/src/events/relation.rs index d4bd349a..67fe2f51 100644 --- a/crates/ruma-common/src/events/relation.rs +++ b/crates/ruma-common/src/events/relation.rs @@ -308,8 +308,26 @@ pub struct BundledRelations { impl BundledRelations { /// Creates a new empty `BundledRelations`. - pub fn new() -> Self { - Self::default() + pub const fn new() -> Self { + Self { + #[cfg(feature = "unstable-msc2677")] + annotation: None, + replace: None, + thread: None, + reference: None, + } + } + + /// Returns `true` if all fields are empty. + pub fn is_empty(&self) -> bool { + #[cfg(not(feature = "unstable-msc2677"))] + return self.replace.is_none() && self.thread.is_none() && self.reference.is_none(); + + #[cfg(feature = "unstable-msc2677")] + return self.annotation.is_none() + && self.replace.is_none() + && self.thread.is_none() + && self.reference.is_none(); } } diff --git a/crates/ruma-common/src/events/room/member.rs b/crates/ruma-common/src/events/room/member.rs index 0fd5ad7c..26bd032c 100644 --- a/crates/ruma-common/src/events/room/member.rs +++ b/crates/ruma-common/src/events/room/member.rs @@ -480,8 +480,8 @@ pub struct RoomMemberUnsigned { /// [Bundled aggregations] of related child events. /// /// [Bundled aggregations]: https://spec.matrix.org/v1.4/client-server-api/#aggregations - #[serde(rename = "m.relations", skip_serializing_if = "Option::is_none")] - pub relations: Option, + #[serde(rename = "m.relations", default, skip_serializing_if = "BundledRelations::is_empty")] + pub relations: BundledRelations, } impl RoomMemberUnsigned { @@ -502,7 +502,7 @@ impl CanBeEmpty for RoomMemberUnsigned { && self.transaction_id.is_none() && self.prev_content.is_none() && self.invite_room_state.is_empty() - && self.relations.is_none() + && self.relations.is_empty() } } diff --git a/crates/ruma-common/src/events/unsigned.rs b/crates/ruma-common/src/events/unsigned.rs index 905b1b56..ff20b843 100644 --- a/crates/ruma-common/src/events/unsigned.rs +++ b/crates/ruma-common/src/events/unsigned.rs @@ -30,8 +30,8 @@ pub struct MessageLikeUnsigned { /// [Bundled aggregations] of related child events. /// /// [Bundled aggregations]: https://spec.matrix.org/v1.4/client-server-api/#aggregations - #[serde(rename = "m.relations", skip_serializing_if = "Option::is_none")] - pub relations: Option, + #[serde(rename = "m.relations", default, skip_serializing_if = "BundledRelations::is_empty")] + pub relations: BundledRelations, } impl MessageLikeUnsigned { @@ -48,7 +48,7 @@ impl CanBeEmpty for MessageLikeUnsigned { /// events. Do not use it to determine whether an incoming `unsigned` field was present - it /// could still have been present but contained none of the known fields. fn is_empty(&self) -> bool { - self.age.is_none() && self.transaction_id.is_none() && self.relations.is_none() + self.age.is_none() && self.transaction_id.is_none() && self.relations.is_empty() } } @@ -76,14 +76,14 @@ pub struct StateUnsigned { /// [Bundled aggregations] of related child events. /// /// [Bundled aggregations]: https://spec.matrix.org/v1.4/client-server-api/#aggregations - #[serde(rename = "m.relations", skip_serializing_if = "Option::is_none")] - pub relations: Option, + #[serde(rename = "m.relations", default, skip_serializing_if = "BundledRelations::is_empty")] + pub relations: BundledRelations, } impl StateUnsigned { /// Create a new `Unsigned` with fields set to `None`. pub fn new() -> Self { - Self { age: None, transaction_id: None, prev_content: None, relations: None } + Self { age: None, transaction_id: None, prev_content: None, relations: Default::default() } } } @@ -97,7 +97,7 @@ impl CanBeEmpty for StateUnsigned { self.age.is_none() && self.transaction_id.is_none() && self.prev_content.is_none() - && self.relations.is_none() + && self.relations.is_empty() } } @@ -119,8 +119,12 @@ impl StateUnsignedFromParts for StateUnsigned { #[serde(skip_serializing_if = "Option::is_none")] transaction_id: Option, prev_content: Option>, - #[serde(rename = "m.relations", skip_serializing_if = "Option::is_none")] - relations: Option, + #[serde( + rename = "m.relations", + default, + skip_serializing_if = "BundledRelations::is_empty" + )] + relations: BundledRelations, } let raw: WithRawPrevContent = from_json_str(object.get())?; diff --git a/crates/ruma-macros/src/events/event_enum.rs b/crates/ruma-macros/src/events/event_enum.rs index be91e378..1d92eb76 100644 --- a/crates/ruma-macros/src/events/event_enum.rs +++ b/crates/ruma-macros/src/events/event_enum.rs @@ -550,16 +550,24 @@ fn expand_accessor_methods( } } - /// Returns this event's `relations` from inside `unsigned`, if that field exists. - pub fn relations(&self) -> Option<&#ruma_common::events::BundledRelations> { + /// Returns this event's `relations` from inside `unsigned`. + pub fn relations(&self) -> &#ruma_common::events::BundledRelations { + static DEFAULT_BUNDLED_RELATIONS: #ruma_common::events::BundledRelations = + #ruma_common::events::BundledRelations::new(); match self { #( #variants2(event) => { - event.as_original().and_then(|ev| ev.unsigned.relations.as_ref()) + event.as_original().map_or_else( + || &DEFAULT_BUNDLED_RELATIONS, + |ev| &ev.unsigned.relations, + ) } )* Self::_Custom(event) => { - event.as_original().and_then(|ev| ev.unsigned.relations.as_ref()) + event.as_original().map_or_else( + || &DEFAULT_BUNDLED_RELATIONS, + |ev| &ev.unsigned.relations, + ) } } }