events: Fix deserialization without relation
This commit is contained in:
parent
0feb39298a
commit
dc18b12506
@ -6,6 +6,8 @@ Bug fixes:
|
|||||||
during creation of the rich reply
|
during creation of the rich reply
|
||||||
* Don't include sensitive information in `Debug`-format of types from the `events::key`
|
* Don't include sensitive information in `Debug`-format of types from the `events::key`
|
||||||
and `events::secret` modules
|
and `events::secret` modules
|
||||||
|
* Fix deserialization of `RoomMessageEventContent` and `RoomEncryptedEventContent` when there
|
||||||
|
is no relation
|
||||||
|
|
||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
||||||
|
@ -39,7 +39,11 @@ pub struct AudioEventContent {
|
|||||||
pub audio: AudioContent,
|
pub audio: AudioContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<AudioEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<AudioEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,11 @@ pub struct EmoteEventContent {
|
|||||||
pub message: MessageContent,
|
pub message: MessageContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<EmoteEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<EmoteEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,11 @@ pub struct FileEventContent {
|
|||||||
pub file: FileContent,
|
pub file: FileContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<FileEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<FileEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,11 @@ pub struct ImageEventContent {
|
|||||||
pub caption: Option<MessageContent>,
|
pub caption: Option<MessageContent>,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<ImageEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<ImageEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,11 @@ pub struct LocationEventContent {
|
|||||||
pub ts: Option<MilliSecondsSinceUnixEpoch>,
|
pub ts: Option<MilliSecondsSinceUnixEpoch>,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<LocationEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<LocationEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,11 @@ pub struct MessageEventContent {
|
|||||||
pub message: MessageContent,
|
pub message: MessageContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<MessageEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<MessageEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,11 @@ pub struct NoticeEventContent {
|
|||||||
pub message: MessageContent,
|
pub message: MessageContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<NoticeEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<NoticeEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,11 @@ pub struct RoomEncryptedEventContent {
|
|||||||
pub scheme: EncryptedEventScheme,
|
pub scheme: EncryptedEventScheme,
|
||||||
|
|
||||||
/// Information about related events.
|
/// Information about related events.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation>,
|
pub relates_to: Option<Relation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,6 +404,8 @@ mod tests {
|
|||||||
assert_eq!(c.ciphertext.len(), 1);
|
assert_eq!(c.ciphertext.len(), 1);
|
||||||
assert_eq!(c.ciphertext["test_curve_key"].body, "encrypted_body");
|
assert_eq!(c.ciphertext["test_curve_key"].body, "encrypted_body");
|
||||||
assert_eq!(c.ciphertext["test_curve_key"].message_type, uint!(1));
|
assert_eq!(c.ciphertext["test_curve_key"].message_type, uint!(1));
|
||||||
|
|
||||||
|
assert_matches!(content.relates_to, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -5,47 +5,43 @@ use super::Annotation;
|
|||||||
use super::{InReplyTo, Reference, Relation, Replacement, Thread};
|
use super::{InReplyTo, Reference, Relation, Replacement, Thread};
|
||||||
use crate::OwnedEventId;
|
use crate::OwnedEventId;
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Relation {
|
pub(super) fn deserialize_relation<'de, D>(deserializer: D) -> Result<Option<Relation>, D::Error>
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
where
|
||||||
where
|
D: Deserializer<'de>,
|
||||||
D: Deserializer<'de>,
|
{
|
||||||
|
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
if let Some(
|
||||||
|
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
|
||||||
|
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
|
||||||
|
) = ev.relates_to.relation
|
||||||
{
|
{
|
||||||
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
|
let in_reply_to = ev
|
||||||
|
.relates_to
|
||||||
if let Some(
|
.in_reply_to
|
||||||
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
|
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
|
||||||
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
|
return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back })));
|
||||||
) = ev.relates_to.relation
|
|
||||||
{
|
|
||||||
let in_reply_to = ev
|
|
||||||
.relates_to
|
|
||||||
.in_reply_to
|
|
||||||
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
|
|
||||||
return Ok(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }));
|
|
||||||
}
|
|
||||||
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to {
|
|
||||||
Relation::Reply { in_reply_to }
|
|
||||||
} else if let Some(relation) = ev.relates_to.relation {
|
|
||||||
match relation {
|
|
||||||
#[cfg(feature = "unstable-msc2677")]
|
|
||||||
RelationJsonRepr::Annotation(a) => Relation::Annotation(a),
|
|
||||||
RelationJsonRepr::Reference(r) => Relation::Reference(r),
|
|
||||||
RelationJsonRepr::Replacement(Replacement { event_id }) => {
|
|
||||||
Relation::Replacement(Replacement { event_id })
|
|
||||||
}
|
|
||||||
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
// FIXME: Maybe we should log this, though at this point we don't even have
|
|
||||||
// access to the rel_type of the unknown relation.
|
|
||||||
RelationJsonRepr::Unknown => Relation::_Custom,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Relation::_Custom
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(rel)
|
|
||||||
}
|
}
|
||||||
|
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to {
|
||||||
|
Some(Relation::Reply { in_reply_to })
|
||||||
|
} else {
|
||||||
|
ev.relates_to.relation.map(|relation| match relation {
|
||||||
|
#[cfg(feature = "unstable-msc2677")]
|
||||||
|
RelationJsonRepr::Annotation(a) => Relation::Annotation(a),
|
||||||
|
RelationJsonRepr::Reference(r) => Relation::Reference(r),
|
||||||
|
RelationJsonRepr::Replacement(Replacement { event_id }) => {
|
||||||
|
Relation::Replacement(Replacement { event_id })
|
||||||
|
}
|
||||||
|
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
// FIXME: Maybe we should log this, though at this point we don't even have
|
||||||
|
// access to the rel_type of the unknown relation.
|
||||||
|
RelationJsonRepr::Unknown => Relation::_Custom,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(rel)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for Relation {
|
impl Serialize for Relation {
|
||||||
|
@ -21,7 +21,7 @@ mod image;
|
|||||||
mod key_verification_request;
|
mod key_verification_request;
|
||||||
mod location;
|
mod location;
|
||||||
mod notice;
|
mod notice;
|
||||||
mod relation_serde;
|
pub(crate) mod relation_serde;
|
||||||
mod reply;
|
mod reply;
|
||||||
pub mod sanitize;
|
pub mod sanitize;
|
||||||
mod server_notice;
|
mod server_notice;
|
||||||
|
@ -5,13 +5,13 @@ use serde_json::value::RawValue as RawJsonValue;
|
|||||||
|
|
||||||
#[cfg(feature = "unstable-msc3552")]
|
#[cfg(feature = "unstable-msc3552")]
|
||||||
use super::ImageMessageEventContent;
|
use super::ImageMessageEventContent;
|
||||||
|
use super::{relation_serde::deserialize_relation, MessageType, RoomMessageEventContent};
|
||||||
#[cfg(feature = "unstable-msc3246")]
|
#[cfg(feature = "unstable-msc3246")]
|
||||||
use super::{AudioInfo, AudioMessageEventContent};
|
use super::{AudioInfo, AudioMessageEventContent};
|
||||||
#[cfg(feature = "unstable-msc3551")]
|
#[cfg(feature = "unstable-msc3551")]
|
||||||
use super::{FileInfo, FileMessageEventContent};
|
use super::{FileInfo, FileMessageEventContent};
|
||||||
#[cfg(feature = "unstable-msc3488")]
|
#[cfg(feature = "unstable-msc3488")]
|
||||||
use super::{LocationInfo, LocationMessageEventContent};
|
use super::{LocationInfo, LocationMessageEventContent};
|
||||||
use super::{MessageType, Relation, RoomMessageEventContent};
|
|
||||||
#[cfg(feature = "unstable-msc3553")]
|
#[cfg(feature = "unstable-msc3553")]
|
||||||
use super::{VideoInfo, VideoMessageEventContent};
|
use super::{VideoInfo, VideoMessageEventContent};
|
||||||
#[cfg(feature = "unstable-msc3246")]
|
#[cfg(feature = "unstable-msc3246")]
|
||||||
@ -47,8 +47,7 @@ impl<'de> Deserialize<'de> for RoomMessageEventContent {
|
|||||||
{
|
{
|
||||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||||
let mut deserializer = serde_json::Deserializer::from_str(json.get());
|
let mut deserializer = serde_json::Deserializer::from_str(json.get());
|
||||||
let relates_to = Option::<Relation<MessageType>>::deserialize(&mut deserializer)
|
let relates_to = deserialize_relation(&mut deserializer).map_err(de::Error::custom)?;
|
||||||
.map_err(de::Error::custom)?;
|
|
||||||
|
|
||||||
Ok(Self { msgtype: from_raw_json_value(&json)?, relates_to })
|
Ok(Self { msgtype: from_raw_json_value(&json)?, relates_to })
|
||||||
}
|
}
|
||||||
|
@ -3,51 +3,49 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|||||||
use super::{InReplyTo, Relation, Replacement, Thread};
|
use super::{InReplyTo, Relation, Replacement, Thread};
|
||||||
use crate::OwnedEventId;
|
use crate::OwnedEventId;
|
||||||
|
|
||||||
impl<'de, C> Deserialize<'de> for Relation<C>
|
pub(crate) fn deserialize_relation<'de, D, C>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<Option<Relation<C>>, D::Error>
|
||||||
where
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
C: Deserialize<'de>,
|
C: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
if let Some(
|
||||||
|
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
|
||||||
|
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
|
||||||
|
) = ev.relates_to.relation
|
||||||
{
|
{
|
||||||
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
|
let in_reply_to = ev
|
||||||
|
.relates_to
|
||||||
if let Some(
|
.in_reply_to
|
||||||
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
|
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
|
||||||
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
|
return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back })));
|
||||||
) = ev.relates_to.relation
|
|
||||||
{
|
|
||||||
let in_reply_to = ev
|
|
||||||
.relates_to
|
|
||||||
.in_reply_to
|
|
||||||
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
|
|
||||||
return Ok(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }));
|
|
||||||
}
|
|
||||||
|
|
||||||
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to {
|
|
||||||
Relation::Reply { in_reply_to }
|
|
||||||
} else if let Some(relation) = ev.relates_to.relation {
|
|
||||||
match relation {
|
|
||||||
RelationJsonRepr::Replacement(ReplacementJsonRepr { event_id }) => {
|
|
||||||
let new_content = ev
|
|
||||||
.new_content
|
|
||||||
.ok_or_else(|| serde::de::Error::missing_field("m.new_content"))?;
|
|
||||||
Relation::Replacement(Replacement { event_id, new_content })
|
|
||||||
}
|
|
||||||
// FIXME: Maybe we should log this, though at this point we don't even have
|
|
||||||
// access to the rel_type of the unknown relation.
|
|
||||||
RelationJsonRepr::Unknown => Relation::_Custom,
|
|
||||||
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Relation::_Custom
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(rel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to {
|
||||||
|
Some(Relation::Reply { in_reply_to })
|
||||||
|
} else if let Some(relation) = ev.relates_to.relation {
|
||||||
|
match relation {
|
||||||
|
RelationJsonRepr::Replacement(ReplacementJsonRepr { event_id }) => {
|
||||||
|
let new_content = ev
|
||||||
|
.new_content
|
||||||
|
.ok_or_else(|| serde::de::Error::missing_field("m.new_content"))?;
|
||||||
|
Some(Relation::Replacement(Replacement { event_id, new_content }))
|
||||||
|
}
|
||||||
|
// FIXME: Maybe we should log this, though at this point we don't even have
|
||||||
|
// access to the rel_type of the unknown relation.
|
||||||
|
RelationJsonRepr::Unknown => Some(Relation::_Custom),
|
||||||
|
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(rel)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Serialize for Relation<C>
|
impl<C> Serialize for Relation<C>
|
||||||
|
@ -49,7 +49,11 @@ pub struct VideoEventContent {
|
|||||||
pub caption: Option<MessageContent>,
|
pub caption: Option<MessageContent>,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<VideoEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<VideoEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,11 @@ pub struct VoiceEventContent {
|
|||||||
pub voice: VoiceContent,
|
pub voice: VoiceContent,
|
||||||
|
|
||||||
/// Information about related messages.
|
/// Information about related messages.
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(
|
||||||
|
flatten,
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
deserialize_with = "crate::events::room::message::relation_serde::deserialize_relation"
|
||||||
|
)]
|
||||||
pub relates_to: Option<Relation<VoiceEventContentWithoutRelation>>,
|
pub relates_to: Option<Relation<VoiceEventContentWithoutRelation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,18 +367,19 @@ fn verification_request_deserialization() {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
|
||||||
|
|
||||||
let verification = assert_matches!(
|
let verification = assert_matches!(
|
||||||
from_json_value::<RoomMessageEventContent>(json_data),
|
content.msgtype,
|
||||||
Ok(RoomMessageEventContent {
|
MessageType::VerificationRequest(verification) => verification
|
||||||
msgtype: MessageType::VerificationRequest(verification),
|
|
||||||
..
|
|
||||||
}) => verification
|
|
||||||
);
|
);
|
||||||
assert_eq!(verification.body, "@example:localhost is requesting to verify your key, ...");
|
assert_eq!(verification.body, "@example:localhost is requesting to verify your key, ...");
|
||||||
assert_eq!(verification.to, user_id);
|
assert_eq!(verification.to, user_id);
|
||||||
assert_eq!(verification.from_device, device_id);
|
assert_eq!(verification.from_device, device_id);
|
||||||
assert_eq!(verification.methods.len(), 3);
|
assert_eq!(verification.methods.len(), 3);
|
||||||
assert!(verification.methods.contains(&VerificationMethod::SasV1));
|
assert!(verification.methods.contains(&VerificationMethod::SasV1));
|
||||||
|
|
||||||
|
assert_matches!(content.relates_to, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -413,17 +414,17 @@ fn content_deserialization() {
|
|||||||
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd"
|
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
|
||||||
let audio = assert_matches!(
|
let audio = assert_matches!(
|
||||||
from_json_value::<RoomMessageEventContent>(json_data),
|
content.msgtype,
|
||||||
Ok(RoomMessageEventContent {
|
MessageType::Audio(audio) => audio
|
||||||
msgtype: MessageType::Audio(audio),
|
|
||||||
..
|
|
||||||
}) => audio
|
|
||||||
);
|
);
|
||||||
assert_eq!(audio.body, "test");
|
assert_eq!(audio.body, "test");
|
||||||
assert_matches!(audio.info, None);
|
assert_matches!(audio.info, None);
|
||||||
let url = assert_matches!(audio.source, MediaSource::Plain(url) => url);
|
let url = assert_matches!(audio.source, MediaSource::Plain(url) => url);
|
||||||
assert_eq!(url, "mxc://example.org/ffed755USFFxlgbQYZGtryd");
|
assert_eq!(url, "mxc://example.org/ffed755USFFxlgbQYZGtryd");
|
||||||
|
|
||||||
|
assert_matches!(content.relates_to, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user