Generate stub/stripped Any*Event enums in event_enum! macro
* Conditionally emit tokens for content enum in event_enum! and the path for each Any*Event variant contents. * Add tests for redaction events now that they are part of Any*Event enums. * Fix any tests that used Any*EventContent.
This commit is contained in:
parent
75ea42961f
commit
fdf87a38a2
@ -9,71 +9,56 @@ use syn::{
|
||||
|
||||
/// Create a content enum from `EventEnumInput`.
|
||||
pub fn expand_event_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
||||
let attrs = &input.attrs;
|
||||
let ident = &input.name;
|
||||
let event_type_str = &input.events;
|
||||
let event_struct = Ident::new(&ident.to_string().trim_start_matches("Any"), ident.span());
|
||||
|
||||
let variants = input.events.iter().map(to_camel_case).collect::<syn::Result<Vec<_>>>()?;
|
||||
let content = input.events.iter().map(to_event_path).collect::<Vec<_>>();
|
||||
let event_enum = expand_any_enum_with_deserialize(&input, ident)?;
|
||||
|
||||
let event_enum = quote! {
|
||||
#( #attrs )*
|
||||
#[derive(Clone, Debug, ::serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum #ident {
|
||||
#(
|
||||
#[doc = #event_type_str]
|
||||
#variants(#content),
|
||||
)*
|
||||
/// An event not defined by the Matrix specification
|
||||
Custom(::ruma_events::#event_struct<::ruma_events::custom::CustomEventContent>),
|
||||
}
|
||||
};
|
||||
let needs_event_content = ident == "AnyStateEvent"
|
||||
|| ident == "AnyMessageEvent"
|
||||
|| ident == "AnyToDeviceEvent"
|
||||
|| ident == "AnyEphemeralRoomEvent"
|
||||
|| ident == "AnyBasicEvent";
|
||||
|
||||
let event_deserialize_impl = quote! {
|
||||
impl<'de> ::serde::de::Deserialize<'de> for #ident {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::de::Deserializer<'de>,
|
||||
{
|
||||
use ::serde::de::Error as _;
|
||||
let needs_event_stub = ident == "AnyStateEvent" || ident == "AnyMessageEvent";
|
||||
|
||||
let json = Box::<::serde_json::value::RawValue>::deserialize(deserializer)?;
|
||||
let ::ruma_events::EventDeHelper { ev_type } = ::ruma_events::from_raw_json_value(&json)?;
|
||||
match ev_type.as_str() {
|
||||
#(
|
||||
#event_type_str => {
|
||||
let event = ::serde_json::from_str::<#content>(json.get()).map_err(D::Error::custom)?;
|
||||
Ok(#ident::#variants(event))
|
||||
},
|
||||
)*
|
||||
event => {
|
||||
let event =
|
||||
::serde_json::from_str::<::ruma_events::#event_struct<::ruma_events::custom::CustomEventContent>>(json.get())
|
||||
.map_err(D::Error::custom)?;
|
||||
let needs_stripped_event = ident == "AnyStateEvent";
|
||||
|
||||
Ok(Self::Custom(event))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let event_stub_enum =
|
||||
if needs_event_stub { expand_stub_enum(&input)? } else { TokenStream::new() };
|
||||
|
||||
let event_content_enum = expand_content_enum(input)?;
|
||||
let event_stripped_enum =
|
||||
if needs_stripped_event { expand_stripped_enum(&input)? } else { TokenStream::new() };
|
||||
|
||||
let event_content_enum =
|
||||
if needs_event_content { expand_content_enum(&input)? } else { TokenStream::new() };
|
||||
|
||||
Ok(quote! {
|
||||
#event_enum
|
||||
|
||||
#event_deserialize_impl
|
||||
#event_stub_enum
|
||||
|
||||
#event_stripped_enum
|
||||
|
||||
#event_content_enum
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a "stub" enum from `EventEnumInput`.
|
||||
pub fn expand_stub_enum(input: &EventEnumInput) -> syn::Result<TokenStream> {
|
||||
let ident = Ident::new(&format!("{}Stub", input.name.to_string()), input.name.span());
|
||||
|
||||
expand_any_enum_with_deserialize(input, &ident)
|
||||
}
|
||||
|
||||
/// Create a "stripped" enum from `EventEnumInput`.
|
||||
pub fn expand_stripped_enum(input: &EventEnumInput) -> syn::Result<TokenStream> {
|
||||
let ident = Ident::new("AnyStrippedStateEventStub", input.name.span());
|
||||
|
||||
expand_any_enum_with_deserialize(input, &ident)
|
||||
}
|
||||
|
||||
/// Create a content enum from `EventEnumInput`.
|
||||
pub fn expand_content_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
||||
pub fn expand_content_enum(input: &EventEnumInput) -> syn::Result<TokenStream> {
|
||||
let attrs = &input.attrs;
|
||||
let ident = Ident::new(&format!("{}Content", input.name.to_string()), input.name.span());
|
||||
let event_type_str = &input.events;
|
||||
@ -122,30 +107,80 @@ pub fn expand_content_enum(input: EventEnumInput) -> syn::Result<TokenStream> {
|
||||
}
|
||||
};
|
||||
|
||||
let any_event_variant_impl = quote! {
|
||||
impl #ident {
|
||||
fn is_compatible(event_type: &str) -> bool {
|
||||
match event_type {
|
||||
#( #event_type_str => true, )*
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let marker_trait_impls = marker_traits(&ident);
|
||||
|
||||
Ok(quote! {
|
||||
#content_enum
|
||||
|
||||
#any_event_variant_impl
|
||||
|
||||
#event_content_impl
|
||||
|
||||
#marker_trait_impls
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_any_enum_with_deserialize(
|
||||
input: &EventEnumInput,
|
||||
ident: &Ident,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let attrs = &input.attrs;
|
||||
let event_type_str = &input.events;
|
||||
let event_struct = Ident::new(&ident.to_string().trim_start_matches("Any"), ident.span());
|
||||
|
||||
let variants = input.events.iter().map(to_camel_case).collect::<syn::Result<Vec<_>>>()?;
|
||||
let content =
|
||||
input.events.iter().map(|event| to_event_path(event, &event_struct)).collect::<Vec<_>>();
|
||||
|
||||
let any_enum = quote! {
|
||||
#( #attrs )*
|
||||
#[derive(Clone, Debug, ::serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum #ident {
|
||||
#(
|
||||
#[doc = #event_type_str]
|
||||
#variants(#content),
|
||||
)*
|
||||
/// An event not defined by the Matrix specification
|
||||
Custom(::ruma_events::#event_struct<::ruma_events::custom::CustomEventContent>),
|
||||
}
|
||||
};
|
||||
|
||||
let event_deserialize_impl = quote! {
|
||||
impl<'de> ::serde::de::Deserialize<'de> for #ident {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::de::Deserializer<'de>,
|
||||
{
|
||||
use ::serde::de::Error as _;
|
||||
|
||||
let json = Box::<::serde_json::value::RawValue>::deserialize(deserializer)?;
|
||||
let ::ruma_events::EventDeHelper { ev_type, .. } = ::ruma_events::from_raw_json_value(&json)?;
|
||||
match ev_type.as_str() {
|
||||
#(
|
||||
#event_type_str => {
|
||||
let event = ::serde_json::from_str::<#content>(json.get()).map_err(D::Error::custom)?;
|
||||
Ok(#ident::#variants(event))
|
||||
},
|
||||
)*
|
||||
event => {
|
||||
let event =
|
||||
::serde_json::from_str::<::ruma_events::#event_struct<::ruma_events::custom::CustomEventContent>>(json.get())
|
||||
.map_err(D::Error::custom)?;
|
||||
|
||||
Ok(Self::Custom(event))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
#any_enum
|
||||
|
||||
#event_deserialize_impl
|
||||
})
|
||||
}
|
||||
|
||||
fn marker_traits(ident: &Ident) -> TokenStream {
|
||||
match ident.to_string().as_str() {
|
||||
"AnyStateEventContent" => quote! {
|
||||
@ -166,7 +201,7 @@ fn marker_traits(ident: &Ident) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_event_path(name: &LitStr) -> TokenStream {
|
||||
fn to_event_path(name: &LitStr, struct_name: &Ident) -> TokenStream {
|
||||
let span = name.span();
|
||||
let name = name.value();
|
||||
|
||||
@ -180,10 +215,25 @@ fn to_event_path(name: &LitStr) -> TokenStream {
|
||||
.map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..])
|
||||
.collect::<String>();
|
||||
|
||||
let content_str = Ident::new(&format!("{}Event", event), span);
|
||||
let path = path.iter().map(|s| Ident::new(s, span));
|
||||
quote! {
|
||||
::ruma_events::#( #path )::*::#content_str
|
||||
|
||||
match struct_name.to_string().as_str() {
|
||||
"MessageEvent" | "MessageEventStub" if *event_str == "m.room.redaction" => {
|
||||
let redaction = if struct_name == "MessageEvent" {
|
||||
quote! { RedactionEvent }
|
||||
} else {
|
||||
quote! { RedactionEventStub }
|
||||
};
|
||||
quote! { ::ruma_events::room::redaction::#redaction }
|
||||
}
|
||||
"ToDeviceEvent" | "StateEventStub" | "StrippedStateEventStub" | "MessageEventStub" => {
|
||||
let content = Ident::new(&format!("{}EventContent", event), span);
|
||||
quote! { ::ruma_events::#struct_name<::ruma_events::#( #path )::*::#content> }
|
||||
}
|
||||
_ => {
|
||||
let event_name = Ident::new(&format!("{}Event", event), span);
|
||||
quote! { ::ruma_events::#( #path )::*::#event_name }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,18 +303,19 @@ pub struct EventEnumInput {
|
||||
impl Parse for EventEnumInput {
|
||||
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
// name field
|
||||
// "name" field
|
||||
input.parse::<kw::name>()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
|
||||
// the name of our event enum
|
||||
let name: Ident = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
// events field
|
||||
// "events" field
|
||||
input.parse::<kw::events>()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
|
||||
// an array of event names `["m.room.whatever"]`
|
||||
// an array of event names `["m.room.whatever", ...]`
|
||||
let ev_array = input.parse::<syn::ExprArray>()?;
|
||||
let events = ev_array
|
||||
.elems
|
||||
|
@ -1,14 +1,8 @@
|
||||
use ruma_events_macros::event_enum;
|
||||
use serde::{
|
||||
de::{self, Error},
|
||||
Serialize,
|
||||
};
|
||||
use serde::{de, Serialize};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
use crate::{
|
||||
event_kinds::{MessageEventStub, StateEventStub, StrippedStateEventStub},
|
||||
from_raw_json_value, EventDeHelper,
|
||||
};
|
||||
use crate::{from_raw_json_value, EventDeHelper};
|
||||
|
||||
event_enum! {
|
||||
/// Any basic event.
|
||||
@ -46,7 +40,6 @@ event_enum! {
|
||||
"m.room.message.feedback",
|
||||
"m.room.redaction",
|
||||
"m.sticker",
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
@ -66,7 +59,6 @@ event_enum! {
|
||||
"m.room.name",
|
||||
"m.room.pinned_events",
|
||||
"m.room.power_levels",
|
||||
"m.room.redaction",
|
||||
"m.room.server_acl",
|
||||
"m.room.third_party_invite",
|
||||
"m.room.tombstone",
|
||||
@ -92,16 +84,6 @@ event_enum! {
|
||||
]
|
||||
}
|
||||
|
||||
/// Any message event stub (message event without a `room_id`, as returned in `/sync` responses)
|
||||
pub type AnyMessageEventStub = MessageEventStub<AnyMessageEventContent>;
|
||||
|
||||
/// Any state event stub (state event without a `room_id`, as returned in `/sync` responses)
|
||||
pub type AnyStateEventStub = StateEventStub<AnyStateEventContent>;
|
||||
|
||||
/// Any stripped state event stub (stripped-down state event, as returned for rooms the user has
|
||||
/// been invited to in `/sync` responses)
|
||||
pub type AnyStrippedStateEventStub = StrippedStateEventStub<AnyStateEventContent>;
|
||||
|
||||
/// Any event.
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(untagged)]
|
||||
@ -144,22 +126,18 @@ impl<'de> de::Deserialize<'de> for AnyEvent {
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||
let EventDeHelper { ev_type } = from_raw_json_value(&json)?;
|
||||
let EventDeHelper { state_key, event_id, room_id, .. } = from_raw_json_value(&json)?;
|
||||
|
||||
match ev_type.as_str() {
|
||||
ev_type if AnyBasicEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyEvent::Basic(from_raw_json_value(&json)?))
|
||||
}
|
||||
ev_type if AnyEphemeralRoomEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyEvent::Ephemeral(from_raw_json_value(&json)?))
|
||||
}
|
||||
ev_type if AnyMessageEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyEvent::Message(from_raw_json_value(&json)?))
|
||||
}
|
||||
ev_type if AnyStateEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyEvent::State(from_raw_json_value(&json)?))
|
||||
}
|
||||
_ => Err(D::Error::custom(format!("event type `{}` is not a valid event", ev_type))),
|
||||
// Determine whether the event is a state, message, ephemeral, or basic event
|
||||
// based on the fields present.
|
||||
if state_key.is_some() {
|
||||
Ok(AnyEvent::State(from_raw_json_value(&json)?))
|
||||
} else if event_id.is_some() {
|
||||
Ok(AnyEvent::Message(from_raw_json_value(&json)?))
|
||||
} else if room_id.is_some() {
|
||||
Ok(AnyEvent::Ephemeral(from_raw_json_value(&json)?))
|
||||
} else {
|
||||
Ok(AnyEvent::Basic(from_raw_json_value(&json)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,16 +148,12 @@ impl<'de> de::Deserialize<'de> for AnyRoomEvent {
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||
let EventDeHelper { ev_type } = from_raw_json_value(&json)?;
|
||||
let EventDeHelper { state_key, .. } = from_raw_json_value(&json)?;
|
||||
|
||||
match ev_type.as_str() {
|
||||
ev_type if AnyMessageEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyRoomEvent::Message(from_raw_json_value(&json)?))
|
||||
}
|
||||
ev_type if AnyStateEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyRoomEvent::State(from_raw_json_value(&json)?))
|
||||
}
|
||||
_ => Err(D::Error::custom(format!("event type `{}` is not a valid event", ev_type))),
|
||||
if state_key.is_some() {
|
||||
Ok(AnyRoomEvent::State(from_raw_json_value(&json)?))
|
||||
} else {
|
||||
Ok(AnyRoomEvent::Message(from_raw_json_value(&json)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,16 +164,12 @@ impl<'de> de::Deserialize<'de> for AnyRoomEventStub {
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||
let EventDeHelper { ev_type } = from_raw_json_value(&json)?;
|
||||
let EventDeHelper { state_key, .. } = from_raw_json_value(&json)?;
|
||||
|
||||
match ev_type.as_str() {
|
||||
ev_type if AnyMessageEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyRoomEventStub::Message(from_raw_json_value(&json)?))
|
||||
}
|
||||
ev_type if AnyStateEventContent::is_compatible(ev_type) => {
|
||||
Ok(AnyRoomEventStub::State(from_raw_json_value(&json)?))
|
||||
}
|
||||
_ => Err(D::Error::custom(format!("event type `{}` is not a valid event", ev_type))),
|
||||
if state_key.is_some() {
|
||||
Ok(AnyRoomEventStub::State(from_raw_json_value(&json)?))
|
||||
} else {
|
||||
Ok(AnyRoomEventStub::Message(from_raw_json_value(&json)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,10 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use js_int::Int;
|
||||
use serde::{de, Deserialize, Serialize};
|
||||
use serde::{
|
||||
de::{self, IgnoredAny},
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
use self::room::redaction::RedactionEvent;
|
||||
@ -234,12 +237,24 @@ pub trait MessageEventContent: RoomEventContent {}
|
||||
/// Marker trait for the content of a state event.
|
||||
pub trait StateEventContent: RoomEventContent {}
|
||||
|
||||
/// Helper struct to obtain the event type from a serde_json::value::RawValue.
|
||||
/// Helper struct to determine the event kind from a serde_json::value::RawValue.
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct EventDeHelper {
|
||||
/// the Matrix event type string "m.room.whatever".
|
||||
#[serde(rename = "type")]
|
||||
pub ev_type: String,
|
||||
|
||||
/// If `state_key` is present the event will be deserialized as a state event.
|
||||
pub state_key: Option<IgnoredAny>,
|
||||
|
||||
/// If no `state_key` is found but an `event_id` is present the event
|
||||
/// will be deserialized as a message event.
|
||||
pub event_id: Option<IgnoredAny>,
|
||||
|
||||
/// If no `event_id` or `state_key` are found but a `room_id` is present
|
||||
/// the event will be deserialized as a ephemeral event.
|
||||
pub room_id: Option<IgnoredAny>,
|
||||
}
|
||||
|
||||
/// Helper function for serde_json::value::RawValue deserialization.
|
||||
|
@ -64,6 +64,10 @@ pub struct RedactionEventContent {
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
impl ruma_events::RoomEventContent for RedactionEventContent {}
|
||||
|
||||
impl ruma_events::MessageEventContent for RedactionEventContent {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
|
@ -5,8 +5,9 @@ use std::{
|
||||
|
||||
use matches::assert_matches;
|
||||
use ruma_events::{
|
||||
custom::CustomEventContent, AnyMessageEvent, AnyStateEvent, AnyStateEventContent, EventJson,
|
||||
MessageEvent, StateEvent, StateEventStub, UnsignedData,
|
||||
custom::CustomEventContent, AnyMessageEvent, AnyMessageEventStub, AnyRoomEventStub,
|
||||
AnyStateEvent, AnyStateEventContent, EventJson, MessageEvent, MessageEventStub, StateEvent,
|
||||
StateEventStub, UnsignedData,
|
||||
};
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use serde_json::{
|
||||
@ -188,3 +189,50 @@ fn deserialize_custom_state_stub_event() {
|
||||
&& !unsigned.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_custom_message_stub_event() {
|
||||
let json_data = json!({
|
||||
"content": {
|
||||
"m.relates_to": {
|
||||
"event_id": "$MDitXXXXXX",
|
||||
"key": "👍",
|
||||
"rel_type": "m.annotation"
|
||||
}
|
||||
},
|
||||
"event_id": "$h29iv0s8:example.com",
|
||||
"origin_server_ts": 10,
|
||||
"room_id": "!room:room.com",
|
||||
"sender": "@carl:example.com",
|
||||
"type": "m.reaction",
|
||||
"unsigned": {
|
||||
"age": 85
|
||||
}
|
||||
});
|
||||
|
||||
let expected_content = json!({
|
||||
"m.relates_to": {
|
||||
"event_id": "$MDitXXXXXX",
|
||||
"key": "👍",
|
||||
"rel_type": "m.annotation"
|
||||
}
|
||||
});
|
||||
|
||||
assert_matches!(
|
||||
from_json_value::<AnyRoomEventStub>(json_data)
|
||||
.unwrap(),
|
||||
AnyRoomEventStub::Message(AnyMessageEventStub::Custom(MessageEventStub {
|
||||
content: CustomEventContent {
|
||||
json, event_type,
|
||||
},
|
||||
event_id,
|
||||
origin_server_ts,
|
||||
sender,
|
||||
unsigned,
|
||||
})) if json == expected_content && event_type == "m.reaction"
|
||||
&& event_id == EventId::try_from("$h29iv0s8:example.com").unwrap()
|
||||
&& origin_server_ts == UNIX_EPOCH + Duration::from_millis(10)
|
||||
&& sender == UserId::try_from("@carl:example.com").unwrap()
|
||||
&& !unsigned.is_empty()
|
||||
);
|
||||
}
|
||||
|
@ -10,9 +10,8 @@ use ruma_events::{
|
||||
message::{MessageEventContent, TextMessageEventContent},
|
||||
power_levels::PowerLevelsEventContent,
|
||||
},
|
||||
AnyEvent, AnyMessageEvent, AnyMessageEventContent, AnyRoomEvent, AnyRoomEventStub,
|
||||
AnyStateEvent, AnyStateEventContent, MessageEvent, MessageEventStub, StateEvent,
|
||||
StateEventStub,
|
||||
AnyEvent, AnyMessageEvent, AnyMessageEventStub, AnyRoomEvent, AnyRoomEventStub, AnyStateEvent,
|
||||
AnyStateEventStub, MessageEvent, MessageEventStub, StateEvent, StateEventStub,
|
||||
};
|
||||
|
||||
fn message_event() -> JsonValue {
|
||||
@ -120,12 +119,12 @@ fn power_event_stub_deserialization() {
|
||||
assert_matches!(
|
||||
from_json_value::<AnyRoomEventStub>(json_data),
|
||||
Ok(AnyRoomEventStub::State(
|
||||
StateEventStub {
|
||||
content: AnyStateEventContent::RoomPowerLevels(PowerLevelsEventContent {
|
||||
AnyStateEventStub::RoomPowerLevels(StateEventStub {
|
||||
content: PowerLevelsEventContent {
|
||||
ban, ..
|
||||
}),
|
||||
},
|
||||
..
|
||||
}
|
||||
})
|
||||
))
|
||||
if ban == js_int::Int::new(50).unwrap()
|
||||
);
|
||||
@ -138,14 +137,14 @@ fn message_event_stub_deserialization() {
|
||||
assert_matches!(
|
||||
from_json_value::<AnyRoomEventStub>(json_data),
|
||||
Ok(AnyRoomEventStub::Message(
|
||||
MessageEventStub {
|
||||
content: AnyMessageEventContent::RoomMessage(MessageEventContent::Text(TextMessageEventContent {
|
||||
AnyMessageEventStub::RoomMessage(MessageEventStub {
|
||||
content: MessageEventContent::Text(TextMessageEventContent {
|
||||
body,
|
||||
formatted: Some(formatted),
|
||||
relates_to: None,
|
||||
})),
|
||||
}),
|
||||
..
|
||||
}
|
||||
})
|
||||
))
|
||||
if body == "baba" && formatted.body == "<strong>baba</strong>"
|
||||
);
|
||||
@ -158,12 +157,12 @@ fn aliases_event_stub_deserialization() {
|
||||
assert_matches!(
|
||||
from_json_value::<AnyRoomEventStub>(json_data),
|
||||
Ok(AnyRoomEventStub::State(
|
||||
StateEventStub {
|
||||
content: AnyStateEventContent::RoomAliases(AliasesEventContent {
|
||||
AnyStateEventStub::RoomAliases(StateEventStub {
|
||||
content: AliasesEventContent {
|
||||
aliases,
|
||||
}),
|
||||
},
|
||||
..
|
||||
}
|
||||
})
|
||||
))
|
||||
if aliases == vec![ RoomAliasId::try_from("#somewhere:localhost").unwrap() ]
|
||||
);
|
||||
|
73
ruma-events/tests/redaction.rs
Normal file
73
ruma-events/tests/redaction.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
time::{Duration, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use matches::assert_matches;
|
||||
use ruma_events::{
|
||||
room::redaction::{RedactionEvent, RedactionEventContent},
|
||||
AnyMessageEvent, EventJson, UnsignedData,
|
||||
};
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use serde_json::{
|
||||
from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
|
||||
};
|
||||
|
||||
fn redaction() -> JsonValue {
|
||||
json!({
|
||||
"content": {
|
||||
"reason": "being a turd"
|
||||
},
|
||||
"redacts": "$nomore:example.com",
|
||||
"event_id": "$h29iv0s8:example.com",
|
||||
"sender": "@carl:example.com",
|
||||
"origin_server_ts": 1,
|
||||
"room_id": "!roomid:room.com",
|
||||
"type": "m.room.redaction"
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_redaction() {
|
||||
let aliases_event = RedactionEvent {
|
||||
content: RedactionEventContent { reason: Some("being a turd".to_string()) },
|
||||
redacts: EventId::try_from("$nomore:example.com").unwrap(),
|
||||
event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(),
|
||||
origin_server_ts: UNIX_EPOCH + Duration::from_millis(1),
|
||||
room_id: RoomId::try_from("!roomid:room.com").unwrap(),
|
||||
sender: UserId::try_from("@carl:example.com").unwrap(),
|
||||
unsigned: UnsignedData::default(),
|
||||
};
|
||||
|
||||
let actual = to_json_value(&aliases_event).unwrap();
|
||||
let expected = redaction();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_redaction() {
|
||||
let json_data = redaction();
|
||||
|
||||
assert_matches!(
|
||||
from_json_value::<EventJson<AnyMessageEvent>>(json_data)
|
||||
.unwrap()
|
||||
.deserialize()
|
||||
.unwrap(),
|
||||
AnyMessageEvent::RoomRedaction(RedactionEvent {
|
||||
content: RedactionEventContent { reason: Some(reas) },
|
||||
redacts,
|
||||
event_id,
|
||||
origin_server_ts,
|
||||
room_id,
|
||||
sender,
|
||||
unsigned,
|
||||
}) if reas == "being a turd"
|
||||
&& event_id == EventId::try_from("$h29iv0s8:example.com").unwrap()
|
||||
&& redacts == EventId::try_from("$nomore:example.com").unwrap()
|
||||
&& origin_server_ts == UNIX_EPOCH + Duration::from_millis(1)
|
||||
&& room_id == RoomId::try_from("!roomid:room.com").unwrap()
|
||||
&& sender == UserId::try_from("@carl:example.com").unwrap()
|
||||
&& unsigned.is_empty()
|
||||
);
|
||||
}
|
@ -3,14 +3,14 @@ use std::convert::TryFrom;
|
||||
use js_int::uint;
|
||||
use ruma_events::{
|
||||
room::{join_rules::JoinRule, topic::TopicEventContent},
|
||||
AnyStateEventContent, AnyStrippedStateEventStub,
|
||||
AnyStateEventContent, AnyStrippedStateEventStub, StrippedStateEventStub,
|
||||
};
|
||||
use ruma_identifiers::UserId;
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
#[test]
|
||||
fn serialize_stripped_state_event() {
|
||||
let event = AnyStrippedStateEventStub {
|
||||
fn serialize_stripped_state_event_any_content() {
|
||||
let event = StrippedStateEventStub {
|
||||
content: AnyStateEventContent::RoomTopic(TopicEventContent {
|
||||
topic: "Testing room".to_string(),
|
||||
}),
|
||||
@ -30,6 +30,26 @@ fn serialize_stripped_state_event() {
|
||||
assert_eq!(to_json_value(&event).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_stripped_state_event_any_event() {
|
||||
let event = AnyStrippedStateEventStub::RoomTopic(StrippedStateEventStub {
|
||||
content: TopicEventContent { topic: "Testing room".to_string() },
|
||||
state_key: "".to_string(),
|
||||
sender: UserId::try_from("@example:localhost").unwrap(),
|
||||
});
|
||||
|
||||
let json_data = json!({
|
||||
"content": {
|
||||
"topic": "Testing room"
|
||||
},
|
||||
"type": "m.room.topic",
|
||||
"state_key": "",
|
||||
"sender": "@example:localhost"
|
||||
});
|
||||
|
||||
assert_eq!(to_json_value(&event).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_stripped_state_events() {
|
||||
let name_event = json!({
|
||||
@ -76,9 +96,9 @@ fn deserialize_stripped_state_events() {
|
||||
});
|
||||
|
||||
let event = from_json_value::<AnyStrippedStateEventStub>(name_event).unwrap();
|
||||
match event.content {
|
||||
AnyStateEventContent::RoomName(content) => {
|
||||
assert_eq!(content.name(), Some("Ruma"));
|
||||
match event {
|
||||
AnyStrippedStateEventStub::RoomName(event) => {
|
||||
assert_eq!(event.content.name(), Some("Ruma"));
|
||||
assert_eq!(event.state_key, "");
|
||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||
}
|
||||
@ -86,9 +106,9 @@ fn deserialize_stripped_state_events() {
|
||||
}
|
||||
|
||||
let event = from_json_value::<AnyStrippedStateEventStub>(join_rules_event).unwrap();
|
||||
match event.content {
|
||||
AnyStateEventContent::RoomJoinRules(content) => {
|
||||
assert_eq!(content.join_rule, JoinRule::Public);
|
||||
match event {
|
||||
AnyStrippedStateEventStub::RoomJoinRules(event) => {
|
||||
assert_eq!(event.content.join_rule, JoinRule::Public);
|
||||
assert_eq!(event.state_key, "");
|
||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||
}
|
||||
@ -96,16 +116,16 @@ fn deserialize_stripped_state_events() {
|
||||
}
|
||||
|
||||
let event = from_json_value::<AnyStrippedStateEventStub>(avatar_event).unwrap();
|
||||
match event.content {
|
||||
AnyStateEventContent::RoomAvatar(content) => {
|
||||
let image_info = content.info.unwrap();
|
||||
match event {
|
||||
AnyStrippedStateEventStub::RoomAvatar(event) => {
|
||||
let image_info = event.content.info.unwrap();
|
||||
|
||||
assert_eq!(image_info.height.unwrap(), uint!(128));
|
||||
assert_eq!(image_info.width.unwrap(), uint!(128));
|
||||
assert_eq!(image_info.mimetype.unwrap(), "image/jpeg");
|
||||
assert_eq!(image_info.size.unwrap(), uint!(1024));
|
||||
assert_eq!(image_info.thumbnail_info.unwrap().size.unwrap(), uint!(32));
|
||||
assert_eq!(content.url, "https://example.com/image.jpg");
|
||||
assert_eq!(event.content.url, "https://example.com/image.jpg");
|
||||
assert_eq!(event.state_key, "");
|
||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user