events: Move EventContent trait and related items into new module

This commit is contained in:
Jonas Platte 2022-03-29 21:43:49 +02:00 committed by Jonas Platte
parent 36aa0cb3cf
commit 6279a2fa6f
No known key found for this signature in database
GPG Key ID: BBA95679259D342F
2 changed files with 137 additions and 132 deletions

View File

@ -126,17 +126,15 @@
//! type alias), allowing content to be converted to and from JSON independently of the surrounding
//! event structure, if needed.
use std::fmt;
use serde::{de::IgnoredAny, Deserialize, Serialize, Serializer};
use serde_json::value::RawValue as RawJsonValue;
use serde::{de::IgnoredAny, Deserialize, Serializer};
use self::room::redaction::SyncRoomRedactionEvent;
use crate::{serde::Raw, EventEncryptionAlgorithm, RoomVersionId};
use crate::{EventEncryptionAlgorithm, RoomVersionId};
// Needs to be public for trybuild tests
#[doc(hidden)]
pub mod _custom;
mod content;
mod enums;
mod event_kinds;
mod unsigned;
@ -193,26 +191,12 @@ pub mod voice;
#[cfg(feature = "unstable-msc2675")]
pub use self::relation::Relations;
pub use self::{
content::*,
enums::*,
event_kinds::*,
unsigned::{MessageLikeUnsigned, RedactedUnsigned, StateUnsigned},
};
/// The base trait that all event content types implement.
///
/// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually.
pub trait EventContent: Sized + Serialize {
/// The Rust enum for the event kind's known types.
type EventType;
/// Get the event's type, like `m.room.message`.
fn event_type(&self) -> Self::EventType;
/// Constructs the given event content.
#[doc(hidden)]
fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self>;
}
/// Trait to define the behavior of redacting an event.
pub trait Redact {
/// The redacted form of the event.
@ -239,118 +223,6 @@ pub trait RedactContent {
fn redact(self, version: &RoomVersionId) -> Self::Redacted;
}
impl<T> Raw<T>
where
T: EventContent,
T::EventType: fmt::Display,
{
/// Try to deserialize the JSON as an event's content.
pub fn deserialize_content(&self, event_type: T::EventType) -> serde_json::Result<T> {
T::from_parts(&event_type.to_string(), self.json())
}
}
/// The base trait that all redacted event content types implement.
///
/// This trait's associated functions and methods should not be used to build
/// redacted events, prefer the `redact` method on `AnyStateEvent` and
/// `AnyMessageLikeEvent` and their "sync" and "stripped" counterparts. The
/// `RedactedEventContent` trait is an implementation detail, ruma makes no
/// API guarantees.
pub trait RedactedEventContent: EventContent {
/// Constructs the redacted event content.
///
/// If called for anything but "empty" redacted content this will error.
#[doc(hidden)]
fn empty(_event_type: &str) -> serde_json::Result<Self> {
Err(serde::de::Error::custom("this event is not redacted"))
}
/// Determines if the redacted event content needs to serialize fields.
#[doc(hidden)]
fn has_serialize_fields(&self) -> bool;
/// Determines if the redacted event content needs to deserialize fields.
#[doc(hidden)]
fn has_deserialize_fields() -> HasDeserializeFields;
}
/// Trait for abstracting over event content structs.
///
/// … but *not* enums which don't always have an event type and kind (e.g. message vs state) that's
/// fixed / known at compile time.
pub trait StaticEventContent: EventContent {
/// The event's "kind".
///
/// See the type's documentation.
const KIND: EventKind;
/// The event type.
const TYPE: &'static str;
}
/// The "kind" of an event.
///
/// This corresponds directly to the event content marker traits.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum EventKind {
/// Global account data event kind.
GlobalAccountData,
/// Room account data event kind.
RoomAccountData,
/// Ephemeral room event kind.
EphemeralRoomData,
/// Message-like event kind.
///
/// Since redacted / non-redacted message-like events are used in the same places but have
/// different sets of fields, these two variations are treated as two closely-related event
/// kinds.
MessageLike {
/// Redacted variation?
redacted: bool,
},
/// State event kind.
///
/// Since redacted / non-redacted state events are used in the same places but have different
/// sets of fields, these two variations are treated as two closely-related event kinds.
State {
/// Redacted variation?
redacted: bool,
},
/// To-device event kind.
ToDevice,
/// Presence event kind.
Presence,
/// Hierarchy space child kind.
HierarchySpaceChild,
}
/// `HasDeserializeFields` is used in the code generated by the `Event` derive
/// to aid in deserializing redacted events.
#[doc(hidden)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub enum HasDeserializeFields {
/// Deserialize the event's content, failing if invalid.
True,
/// Return the redacted version of this event's content.
False,
/// `Optional` is used for `RedactedAliasesEventContent` since it has
/// an empty version and one with content left after redaction that
/// must be supported together.
Optional,
}
/// Helper struct to determine the event kind from a `serde_json::value::RawValue`.
#[doc(hidden)]
#[derive(Deserialize)]

View File

@ -0,0 +1,133 @@
use std::fmt;
use serde::Serialize;
use serde_json::value::RawValue as RawJsonValue;
use crate::serde::Raw;
/// The base trait that all event content types implement.
///
/// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually.
pub trait EventContent: Sized + Serialize {
/// The Rust enum for the event kind's known types.
type EventType;
/// Get the event's type, like `m.room.message`.
fn event_type(&self) -> Self::EventType;
/// Constructs the given event content.
#[doc(hidden)]
fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self>;
}
impl<T> Raw<T>
where
T: EventContent,
T::EventType: fmt::Display,
{
/// Try to deserialize the JSON as an event's content.
pub fn deserialize_content(&self, event_type: T::EventType) -> serde_json::Result<T> {
T::from_parts(&event_type.to_string(), self.json())
}
}
/// The base trait that all redacted event content types implement.
///
/// This trait's associated functions and methods should not be used to build
/// redacted events, prefer the `redact` method on `AnyStateEvent` and
/// `AnyMessageLikeEvent` and their "sync" and "stripped" counterparts. The
/// `RedactedEventContent` trait is an implementation detail, ruma makes no
/// API guarantees.
pub trait RedactedEventContent: EventContent {
/// Constructs the redacted event content.
///
/// If called for anything but "empty" redacted content this will error.
#[doc(hidden)]
fn empty(_event_type: &str) -> serde_json::Result<Self> {
Err(serde::de::Error::custom("this event is not redacted"))
}
/// Determines if the redacted event content needs to serialize fields.
#[doc(hidden)]
fn has_serialize_fields(&self) -> bool;
/// Determines if the redacted event content needs to deserialize fields.
#[doc(hidden)]
fn has_deserialize_fields() -> HasDeserializeFields;
}
/// `HasDeserializeFields` is used in the code generated by the `Event` derive
/// to aid in deserializing redacted events.
#[doc(hidden)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub enum HasDeserializeFields {
/// Deserialize the event's content, failing if invalid.
True,
/// Return the redacted version of this event's content.
False,
/// `Optional` is used for `RedactedAliasesEventContent` since it has
/// an empty version and one with content left after redaction that
/// must be supported together.
Optional,
}
/// Trait for abstracting over event content structs.
///
/// … but *not* enums which don't always have an event type and kind (e.g. message vs state) that's
/// fixed / known at compile time.
pub trait StaticEventContent: EventContent {
/// The event's "kind".
///
/// See the type's documentation.
const KIND: EventKind;
/// The event type.
const TYPE: &'static str;
}
/// The "kind" of an event.
///
/// This corresponds directly to the event content marker traits.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum EventKind {
/// Global account data event kind.
GlobalAccountData,
/// Room account data event kind.
RoomAccountData,
/// Ephemeral room event kind.
EphemeralRoomData,
/// Message-like event kind.
///
/// Since redacted / non-redacted message-like events are used in the same places but have
/// different sets of fields, these two variations are treated as two closely-related event
/// kinds.
MessageLike {
/// Redacted variation?
redacted: bool,
},
/// State event kind.
///
/// Since redacted / non-redacted state events are used in the same places but have different
/// sets of fields, these two variations are treated as two closely-related event kinds.
State {
/// Redacted variation?
redacted: bool,
},
/// To-device event kind.
ToDevice,
/// Presence event kind.
Presence,
/// Hierarchy space child kind.
HierarchySpaceChild,
}