Implement MSC3925
… without a feature flag because it is a breaking change, so the feature would have to be non-additive, which is a no-go. Limited support for the previous replacement format is kept.
This commit is contained in:
parent
19d44489c3
commit
e61e0ccf6b
@ -74,7 +74,7 @@ impl StaticStateEventContent for CustomStateEventContent {
|
||||
// Like `StateUnsigned`, but without `prev_content`.
|
||||
// We don't care about `prev_content` since we'd only store the event type that is the same
|
||||
// as in the content.
|
||||
type Unsigned = MessageLikeUnsigned;
|
||||
type Unsigned = MessageLikeUnsigned<CustomMessageLikeEventContent>;
|
||||
type PossiblyRedacted = Self;
|
||||
}
|
||||
impl PossiblyRedactedStateEventContent for CustomStateEventContent {
|
||||
|
@ -119,7 +119,7 @@ pub struct OriginalMessageLikeEvent<C: MessageLikeEventContent> {
|
||||
pub room_id: OwnedRoomId,
|
||||
|
||||
/// Additional key-value pairs not signed by the homeserver.
|
||||
pub unsigned: MessageLikeUnsigned,
|
||||
pub unsigned: MessageLikeUnsigned<C>,
|
||||
}
|
||||
|
||||
/// An unredacted message-like event without a `room_id`.
|
||||
@ -141,7 +141,7 @@ pub struct OriginalSyncMessageLikeEvent<C: MessageLikeEventContent> {
|
||||
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
|
||||
|
||||
/// Additional key-value pairs not signed by the homeserver.
|
||||
pub unsigned: MessageLikeUnsigned,
|
||||
pub unsigned: MessageLikeUnsigned<C>,
|
||||
}
|
||||
|
||||
/// A redacted message-like event.
|
||||
|
@ -10,9 +10,11 @@ use serde::{Deserialize, Serialize};
|
||||
use super::AnyMessageLikeEvent;
|
||||
use crate::{
|
||||
serde::{Raw, StringEnum},
|
||||
MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId, PrivOwnedStr,
|
||||
OwnedEventId, PrivOwnedStr,
|
||||
};
|
||||
|
||||
mod rel_serde;
|
||||
|
||||
/// Information about the event a [rich reply] is replying to.
|
||||
///
|
||||
/// [rich reply]: https://spec.matrix.org/latest/client-server-api/#rich-replies
|
||||
@ -58,31 +60,6 @@ impl Annotation {
|
||||
}
|
||||
}
|
||||
|
||||
/// A bundled replacement.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct BundledReplacement {
|
||||
/// The ID of the replacing event.
|
||||
pub event_id: OwnedEventId,
|
||||
|
||||
/// The user ID of the sender of the latest replacement.
|
||||
pub sender: OwnedUserId,
|
||||
|
||||
/// Timestamp in milliseconds on originating homeserver when the latest replacement was sent.
|
||||
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
|
||||
}
|
||||
|
||||
impl BundledReplacement {
|
||||
/// Creates a new `BundledReplacement` with the given event ID, sender and timestamp.
|
||||
pub fn new(
|
||||
event_id: OwnedEventId,
|
||||
sender: OwnedUserId,
|
||||
origin_server_ts: MilliSecondsSinceUnixEpoch,
|
||||
) -> Self {
|
||||
Self { event_id, sender, origin_server_ts }
|
||||
}
|
||||
}
|
||||
|
||||
/// The content of a [replacement] relation.
|
||||
///
|
||||
/// [replacement]: https://spec.matrix.org/latest/client-server-api/#event-replacements
|
||||
@ -221,12 +198,18 @@ impl ReferenceChunk {
|
||||
/// [Bundled aggregations] of related child events of a message-like event.
|
||||
///
|
||||
/// [Bundled aggregations]: https://spec.matrix.org/latest/client-server-api/#aggregations
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct BundledMessageLikeRelations {
|
||||
pub struct BundledMessageLikeRelations<E> {
|
||||
/// Replacement relation.
|
||||
#[serde(rename = "m.replace", skip_serializing_if = "Option::is_none")]
|
||||
pub replace: Option<Box<BundledReplacement>>,
|
||||
pub replace: Option<Box<E>>,
|
||||
|
||||
/// Set when the above fails to deserialize.
|
||||
///
|
||||
/// Intentionally *not* public.
|
||||
#[serde(skip_serializing)]
|
||||
has_invalid_replacement: bool,
|
||||
|
||||
/// Thread relation.
|
||||
#[serde(rename = "m.thread", skip_serializing_if = "Option::is_none")]
|
||||
@ -237,10 +220,20 @@ pub struct BundledMessageLikeRelations {
|
||||
pub reference: Option<Box<ReferenceChunk>>,
|
||||
}
|
||||
|
||||
impl BundledMessageLikeRelations {
|
||||
impl<E> BundledMessageLikeRelations<E> {
|
||||
/// Creates a new empty `BundledMessageLikeRelations`.
|
||||
pub const fn new() -> Self {
|
||||
Self { replace: None, thread: None, reference: None }
|
||||
Self { replace: None, has_invalid_replacement: false, thread: None, reference: None }
|
||||
}
|
||||
|
||||
/// Whether this bundle contains a replacement relation.
|
||||
///
|
||||
/// This may be `true` even if the `replace` field is `None`, because Matrix versions prior to
|
||||
/// 1.7 had a different incompatible format for bundled replacements. Use this method to check
|
||||
/// whether an event was replaced. If this returns `true` but `replace` is `None`, use one of
|
||||
/// the endpoints from `ruma::api::client::relations` to fetch the relation details.
|
||||
pub fn has_replacement(&self) -> bool {
|
||||
self.replace.is_some() || self.has_invalid_replacement
|
||||
}
|
||||
|
||||
/// Returns `true` if all fields are empty.
|
||||
@ -249,6 +242,12 @@ impl BundledMessageLikeRelations {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Default for BundledMessageLikeRelations<E> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// [Bundled aggregations] of related child events of a state event.
|
||||
///
|
||||
/// [Bundled aggregations]: https://spec.matrix.org/latest/client-server-api/#aggregations
|
||||
|
35
crates/ruma-common/src/events/relation/rel_serde.rs
Normal file
35
crates/ruma-common/src/events/relation/rel_serde.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
|
||||
|
||||
use super::{BundledMessageLikeRelations, BundledThread, ReferenceChunk};
|
||||
use crate::serde::Raw;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BundledMessageLikeRelationsJsonRepr<E> {
|
||||
#[serde(rename = "m.replace")]
|
||||
replace: Option<Raw<Box<E>>>,
|
||||
#[serde(rename = "m.thread")]
|
||||
thread: Option<Box<BundledThread>>,
|
||||
#[serde(rename = "m.reference")]
|
||||
reference: Option<Box<ReferenceChunk>>,
|
||||
}
|
||||
|
||||
impl<'de, E> Deserialize<'de> for BundledMessageLikeRelations<E>
|
||||
where
|
||||
E: DeserializeOwned,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let BundledMessageLikeRelationsJsonRepr { replace, thread, reference } =
|
||||
BundledMessageLikeRelationsJsonRepr::deserialize(deserializer)?;
|
||||
|
||||
let (replace, has_invalid_replacement) =
|
||||
match replace.as_ref().map(Raw::deserialize).transpose() {
|
||||
Ok(replace) => (replace, false),
|
||||
Err(_) => (None, true),
|
||||
};
|
||||
|
||||
Ok(BundledMessageLikeRelations { replace, has_invalid_replacement, thread, reference })
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ pub struct OriginalRoomRedactionEvent {
|
||||
pub room_id: OwnedRoomId,
|
||||
|
||||
/// Additional key-value pairs not signed by the homeserver.
|
||||
pub unsigned: MessageLikeUnsigned,
|
||||
pub unsigned: MessageLikeUnsigned<RoomRedactionEventContent>,
|
||||
}
|
||||
|
||||
/// Redacted redaction event.
|
||||
@ -106,7 +106,7 @@ pub struct OriginalSyncRoomRedactionEvent {
|
||||
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
|
||||
|
||||
/// Additional key-value pairs not signed by the homeserver.
|
||||
pub unsigned: MessageLikeUnsigned,
|
||||
pub unsigned: MessageLikeUnsigned<RoomRedactionEventContent>,
|
||||
}
|
||||
|
||||
/// Redacted redaction event without a `room_id`.
|
||||
|
@ -1,19 +1,20 @@
|
||||
use js_int::Int;
|
||||
use serde::Deserialize;
|
||||
use serde::{de::DeserializeOwned, Deserialize};
|
||||
|
||||
use super::{
|
||||
relation::{BundledMessageLikeRelations, BundledStateRelations},
|
||||
room::redaction::RoomRedactionEventContent,
|
||||
PossiblyRedactedStateEventContent,
|
||||
MessageLikeEventContent, OriginalSyncMessageLikeEvent, PossiblyRedactedStateEventContent,
|
||||
};
|
||||
use crate::{
|
||||
serde::CanBeEmpty, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
|
||||
};
|
||||
|
||||
/// Extra information about a message event that is not incorporated into the event's hash.
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(bound = "OriginalSyncMessageLikeEvent<C>: DeserializeOwned")]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct MessageLikeUnsigned {
|
||||
pub struct MessageLikeUnsigned<C: MessageLikeEventContent> {
|
||||
/// The time in milliseconds that has elapsed since the event was sent.
|
||||
///
|
||||
/// This field is generated by the local homeserver, and may be incorrect if the local time on
|
||||
@ -29,17 +30,23 @@ pub struct MessageLikeUnsigned {
|
||||
///
|
||||
/// [Bundled aggregations]: https://spec.matrix.org/latest/client-server-api/#aggregations
|
||||
#[serde(rename = "m.relations", default)]
|
||||
pub relations: BundledMessageLikeRelations,
|
||||
pub relations: BundledMessageLikeRelations<OriginalSyncMessageLikeEvent<C>>,
|
||||
}
|
||||
|
||||
impl MessageLikeUnsigned {
|
||||
impl<C: MessageLikeEventContent> MessageLikeUnsigned<C> {
|
||||
/// Create a new `Unsigned` with fields set to `None`.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
Self { age: None, transaction_id: None, relations: BundledMessageLikeRelations::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl CanBeEmpty for MessageLikeUnsigned {
|
||||
impl<C: MessageLikeEventContent> Default for MessageLikeUnsigned<C> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: MessageLikeEventContent> CanBeEmpty for MessageLikeUnsigned<C> {
|
||||
/// Whether this unsigned data is empty (all fields are `None`).
|
||||
///
|
||||
/// This method is used to determine whether to skip serializing the `unsigned` field in room
|
||||
@ -142,5 +149,5 @@ pub struct UnsignedRoomRedactionEvent {
|
||||
|
||||
/// Additional key-value pairs not signed by the homeserver.
|
||||
#[serde(default)]
|
||||
pub unsigned: MessageLikeUnsigned,
|
||||
pub unsigned: MessageLikeUnsigned<RoomRedactionEventContent>,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user