events: Make more types non-exhaustive in room::message

This commit is contained in:
Jonas Platte 2021-05-15 22:20:48 +02:00
parent da6b513788
commit f77b49d4b8
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
2 changed files with 61 additions and 17 deletions

View File

@ -343,27 +343,42 @@ impl From<RelatesToJsonRepr> for Relation {
/// The payload for an audio message. /// The payload for an audio message.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.audio")] #[serde(tag = "msgtype", rename = "m.audio")]
pub struct AudioMessageEventContent { pub struct AudioMessageEventContent {
/// The textual representation of this message. /// The textual representation of this message.
pub body: String, pub body: String,
/// Metadata for the audio clip referred to in `url`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<AudioInfo>>,
/// The URL to the audio clip. Required if the file is unencrypted. The URL (typically /// The URL to the audio clip. Required if the file is unencrypted. The URL (typically
/// [MXC URI](https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri)) to the audio clip. /// [MXC URI](https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri)) to the audio clip.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<MxcUri>, pub url: Option<MxcUri>,
/// Metadata for the audio clip referred to in `url`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<AudioInfo>>,
/// Required if the audio clip is encrypted. Information on the encrypted audio clip. /// Required if the audio clip is encrypted. Information on the encrypted audio clip.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<Box<EncryptedFile>>, pub file: Option<Box<EncryptedFile>>,
} }
impl AudioMessageEventContent {
/// Creates a new non-encrypted `AudioMessageEventContent` with the given body, url and optional
/// extra info.
pub fn plain(body: String, url: MxcUri, info: Option<Box<AudioInfo>>) -> Self {
Self { body, url: Some(url), info, file: None }
}
/// Creates a new encrypted `AudioMessageEventContent` with the given body and encrypted file.
pub fn encrypted(body: String, file: EncryptedFile) -> Self {
Self { body, url: None, info: None, file: Some(Box::new(file)) }
}
}
/// Metadata about an audio clip. /// Metadata about an audio clip.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct AudioInfo { pub struct AudioInfo {
/// The duration of the audio in milliseconds. /// The duration of the audio in milliseconds.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -378,8 +393,16 @@ pub struct AudioInfo {
pub size: Option<UInt>, pub size: Option<UInt>,
} }
impl AudioInfo {
/// Creates an empty `AudioInfo`.
pub fn new() -> Self {
Self::default()
}
}
/// The payload for an emote message. /// The payload for an emote message.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.emote")] #[serde(tag = "msgtype", rename = "m.emote")]
pub struct EmoteMessageEventContent { pub struct EmoteMessageEventContent {
/// The emote action to perform. /// The emote action to perform.
@ -390,6 +413,28 @@ pub struct EmoteMessageEventContent {
pub formatted: Option<FormattedBody>, pub formatted: Option<FormattedBody>,
} }
impl EmoteMessageEventContent {
/// A convenience constructor to create a plain-text emote.
pub fn plain(body: impl Into<String>) -> Self {
Self { body: body.into(), formatted: None }
}
/// A convenience constructor to create an html emote message.
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
Self { formatted: Some(FormattedBody::html(html_body)), ..Self::plain(body) }
}
/// A convenience constructor to create a markdown emote.
#[cfg(feature = "markdown")]
#[cfg_attr(docsrs, doc(cfg(feature = "markdown")))]
pub fn markdown(body: impl Into<String>) -> Self {
let body = body.into();
let mut html_body = String::new();
pulldown_cmark::html::push_html(&mut html_body, pulldown_cmark::Parser::new(&body));
Self::html(body, html_body)
}
}
/// The payload for a file message. /// The payload for a file message.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "msgtype", rename = "m.file")] #[serde(tag = "msgtype", rename = "m.file")]

View File

@ -37,12 +37,11 @@ macro_rules! json_object {
#[test] #[test]
fn serialization() { fn serialization() {
let ev = MessageEvent { let ev = MessageEvent {
content: MessageEventContent::new(MessageType::Audio(AudioMessageEventContent { content: MessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain(
body: "test".into(), "test".into(),
info: None, mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd"),
url: Some(mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd")), None,
file: None, ))),
})),
event_id: event_id!("$143273582443PhrSn:example.org"), event_id: event_id!("$143273582443PhrSn:example.org"),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)),
room_id: room_id!("!testroomid:example.org"), room_id: room_id!("!testroomid:example.org"),
@ -70,12 +69,11 @@ fn serialization() {
#[test] #[test]
fn content_serialization() { fn content_serialization() {
let message_event_content = let message_event_content =
MessageEventContent::new(MessageType::Audio(AudioMessageEventContent { MessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain(
body: "test".into(), "test".into(),
info: None, mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd"),
url: Some(mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd")), None,
file: None, )));
}));
assert_eq!( assert_eq!(
to_json_value(&message_event_content).unwrap(), to_json_value(&message_event_content).unwrap(),
@ -346,6 +344,7 @@ fn content_deserialization() {
info: None, info: None,
url: Some(url), url: Some(url),
file: None, file: None,
..
}), }),
.. ..
} if body == "test" && url.to_string() == "mxc://example.org/ffed755USFFxlgbQYZGtryd" } if body == "test" && url.to_string() == "mxc://example.org/ffed755USFFxlgbQYZGtryd"