events: Remove StateUnsignedFromParts

Replace it with a bound on DeserializeOwned
This commit is contained in:
Kévin Commaille 2023-01-06 16:44:08 +01:00 committed by Kévin Commaille
parent 97b212795a
commit dc591647f8
9 changed files with 22 additions and 97 deletions

View File

@ -51,6 +51,8 @@ Breaking changes:
* Rename `RoomEventType` to `TimelineEventType`
* Remove `SecretStorageKeyEventContent`'s implementation of `Deserialize`
* Use `EventContentFromType::from_parts` instead
* Remove `StateUnsignedFromParts`
* Replace it with a bound on `DeserializeOwned`
Improvements:

View File

@ -173,10 +173,7 @@ pub use self::{
kinds::*,
relation::BundledRelations,
state_key::EmptyStateKey,
unsigned::{
MessageLikeUnsigned, RedactedUnsigned, StateUnsigned, StateUnsignedFromParts,
UnsignedRoomRedactionEvent,
},
unsigned::{MessageLikeUnsigned, RedactedUnsigned, StateUnsigned, UnsignedRoomRedactionEvent},
};
/// Trait to define the behavior of redact an event's content object.

View File

@ -4,9 +4,9 @@ use serde_json::value::RawValue as RawJsonValue;
use super::{
EphemeralRoomEventContent, EphemeralRoomEventType, EventContent, EventContentFromType,
GlobalAccountDataEventContent, GlobalAccountDataEventType, MessageLikeEventContent,
MessageLikeEventType, OriginalStateEventContent, RedactContent, RedactedEventContent,
RedactedMessageLikeEventContent, RedactedStateEventContent, RoomAccountDataEventContent,
RoomAccountDataEventType, StateEventContent, StateEventType, StateUnsigned,
MessageLikeEventType, MessageLikeUnsigned, OriginalStateEventContent, RedactContent,
RedactedEventContent, RedactedMessageLikeEventContent, RedactedStateEventContent,
RoomAccountDataEventContent, RoomAccountDataEventType, StateEventContent, StateEventType,
ToDeviceEventContent, ToDeviceEventType,
};
use crate::RoomVersionId;
@ -77,7 +77,10 @@ impl StateEventContent for CustomStateEventContent {
type StateKey = String;
}
impl OriginalStateEventContent for CustomStateEventContent {
type Unsigned = StateUnsigned<Self>;
// 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 PossiblyRedacted = Self;
}
impl RedactedStateEventContent for CustomStateEventContent {}

View File

@ -7,7 +7,7 @@ use crate::serde::{CanBeEmpty, Raw};
use super::{
EphemeralRoomEventType, GlobalAccountDataEventType, MessageLikeEventType, RedactContent,
RoomAccountDataEventType, StateEventType, StateUnsignedFromParts, ToDeviceEventType,
RoomAccountDataEventType, StateEventType, ToDeviceEventType,
};
/// The base trait that all event content types implement.
@ -129,7 +129,7 @@ pub trait StateEventContent: EventContent<EventType = StateEventType> {
/// Content of a non-redacted state event.
pub trait OriginalStateEventContent: StateEventContent + RedactContent {
/// The type of the event's `unsigned` field.
type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + StateUnsignedFromParts;
type Unsigned: Clone + fmt::Debug + Default + CanBeEmpty + DeserializeOwned;
/// The possibly redacted form of the event's content.
type PossiblyRedacted: StateEventContent;

View File

@ -7,13 +7,12 @@ use std::collections::BTreeMap;
use js_int::Int;
use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};
use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
use serde_json::value::RawValue as RawJsonValue;
use crate::{
events::{
AnyStrippedStateEvent, BundledRelations, EventContent, RedactContent, RedactedEventContent,
RedactedStateEventContent, StateEventContent, StateEventType, StateUnsignedFromParts,
StaticEventContent,
RedactedStateEventContent, StateEventContent, StateEventType,
},
serde::{CanBeEmpty, Raw, StringEnum},
OwnedMxcUri, OwnedServerName, OwnedServerSigningKeyId, OwnedTransactionId, OwnedUserId,
@ -550,20 +549,6 @@ impl CanBeEmpty for RoomMemberUnsigned {
}
}
impl StateUnsignedFromParts for RoomMemberUnsigned {
fn _from_parts(event_type: &str, object: &RawJsonValue) -> serde_json::Result<Self> {
const EVENT_TYPE: &str = <RoomMemberEventContent as StaticEventContent>::TYPE;
if event_type != EVENT_TYPE {
return Err(serde::de::Error::custom(format!(
"expected event type of `{EVENT_TYPE}`, found `{event_type}`",
)));
}
from_json_str(object.get())
}
}
#[cfg(test)]
mod tests {
use assert_matches::assert_matches;

View File

@ -1,13 +1,11 @@
use js_int::Int;
use serde::Deserialize;
use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
use super::{
relation::BundledRelations, room::redaction::RoomRedactionEventContent, StateEventContent,
};
use crate::{
serde::{CanBeEmpty, Raw},
MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
serde::CanBeEmpty, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
};
/// Extra information about a message event that is not incorporated into the event's hash.
@ -96,45 +94,6 @@ impl<C: StateEventContent> CanBeEmpty for StateUnsigned<C> {
}
}
/// Helper functions for proc-macro code.
///
/// Needs to be public for state events defined outside ruma-common.
#[doc(hidden)]
pub trait StateUnsignedFromParts: Sized {
fn _from_parts(event_type: &str, object: &RawJsonValue) -> serde_json::Result<Self>;
}
impl<C: StateEventContent> StateUnsignedFromParts for StateUnsigned<C> {
fn _from_parts(event_type: &str, object: &RawJsonValue) -> serde_json::Result<Self> {
#[derive(Deserialize)]
#[serde(bound = "")] // Disable default C: Deserialize bound
struct WithRawPrevContent<C> {
#[serde(skip_serializing_if = "Option::is_none")]
age: Option<Int>,
#[serde(skip_serializing_if = "Option::is_none")]
transaction_id: Option<OwnedTransactionId>,
prev_content: Option<Raw<C>>,
#[serde(
rename = "m.relations",
default,
skip_serializing_if = "BundledRelations::is_empty"
)]
relations: BundledRelations,
}
let raw: WithRawPrevContent<C> = from_json_str(object.get())?;
let prev_content =
raw.prev_content.map(|r| r.deserialize_content(event_type.into())).transpose()?;
Ok(Self {
age: raw.age,
transaction_id: raw.transaction_id,
relations: raw.relations,
prev_content,
})
}
}
impl<C: StateEventContent> Default for StateUnsigned<C> {
fn default() -> Self {
Self::new()

View File

@ -1,17 +1,13 @@
// Required, probably until Rust 1.57
// https://github.com/rust-lang/rust/issues/55779
#[allow(unused_extern_crates)]
extern crate serde;
use ruma_common::{
events::{StateEventContent, StateUnsigned},
MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId,
};
use ruma_macros::Event;
use serde::de::DeserializeOwned;
/// State event.
#[derive(Clone, Debug, Event)]
pub struct OriginalStateEvent<C: StateEventContent> {
pub struct OriginalStateEvent<C: StateEventContent + DeserializeOwned> {
pub content: C,
pub event_id: OwnedEventId,
pub sender: OwnedUserId,

View File

@ -6,7 +6,7 @@ use syn::{Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed};
use super::{
event_parse::{to_kind_variation, EventKind, EventKindVariation},
util::{has_prev_content, is_non_stripped_room_event},
util::is_non_stripped_room_event,
};
use crate::{import_ruma_common, util::to_camel_case};
@ -42,7 +42,7 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> {
let mut res = TokenStream::new();
res.extend(
expand_deserialize_event(&input, kind, var, &fields, &ruma_common)
expand_deserialize_event(&input, var, &fields, &ruma_common)
.unwrap_or_else(syn::Error::into_compile_error),
);
@ -59,7 +59,6 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> {
fn expand_deserialize_event(
input: &DeriveInput,
kind: EventKind,
var: EventKindVariation,
fields: &[Field],
ruma_common: &TokenStream,
@ -91,7 +90,7 @@ fn expand_deserialize_event(
.iter()
.map(|field| {
let name = field.ident.as_ref().unwrap();
if name == "content" || (name == "unsigned" && has_prev_content(kind, var)) {
if name == "content" {
if is_generic {
quote! { ::std::boxed::Box<#serde_json::value::RawValue> }
} else {
@ -137,19 +136,8 @@ fn expand_deserialize_event(
}
}
} else if name == "unsigned" && !var.is_redacted() {
if has_prev_content(kind, var) {
quote! {
let unsigned = unsigned.map(|json| {
#ruma_common::events::StateUnsignedFromParts::_from_parts(
&event_type,
&json,
).map_err(#serde::de::Error::custom)
}).transpose()?.unwrap_or_default();
}
} else {
quote! {
let unsigned = unsigned.unwrap_or_default();
}
quote! {
let unsigned = unsigned.unwrap_or_default();
}
} else if name == "state_key" && var == EventKindVariation::Initial {
let ty = &field.ty;

View File

@ -10,8 +10,3 @@ pub(crate) fn is_non_stripped_room_event(kind: EventKind, var: EventKindVariatio
| EventKindVariation::RedactedSync
)
}
pub(crate) fn has_prev_content(kind: EventKind, var: EventKindVariation) -> bool {
matches!(kind, EventKind::State)
&& matches!(var, EventKindVariation::Original | EventKindVariation::OriginalSync)
}