Update room::message

* Derive Deserialize for raw::MessageEventContent
* Remove MessageType
This commit is contained in:
Jonas Platte 2020-05-02 23:25:46 +02:00
parent 2f706d9a85
commit b8eafc3f59
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
2 changed files with 26 additions and 107 deletions

View File

@ -15,6 +15,8 @@ Breaking changes:
* To access any additional fields of the `unsigned` property of an event, * To access any additional fields of the `unsigned` property of an event,
deserialize the `EventJson` to another type that captures the field(s) you deserialize the `EventJson` to another type that captures the field(s) you
are interested in. are interested in.
* Remove `room::message::MessageType`
* Remove `room::message::MessageEventContent::Encrypted` (which only existed by mistake)
Improvements: Improvements:

View File

@ -13,7 +13,6 @@ pub mod feedback;
/// A message sent to a room. /// A message sent to a room.
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
#[serde(rename = "m.room.message", tag = "type")]
pub struct MessageEvent { pub struct MessageEvent {
/// The event's content. /// The event's content.
pub content: MessageEventContent, pub content: MessageEventContent,
@ -40,33 +39,42 @@ pub struct MessageEvent {
/// The payload for `MessageEvent`. /// The payload for `MessageEvent`.
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
#[serde(untagged)] #[serde(tag = "msgtype")]
pub enum MessageEventContent { pub enum MessageEventContent {
/// An audio message. /// An audio message.
#[serde(rename = "m.audio")]
Audio(AudioMessageEventContent), Audio(AudioMessageEventContent),
/// An emote message. /// An emote message.
#[serde(rename = "m.emote")]
Emote(EmoteMessageEventContent), Emote(EmoteMessageEventContent),
/// A file message. /// A file message.
#[serde(rename = "m.file")]
File(FileMessageEventContent), File(FileMessageEventContent),
/// An image message. /// An image message.
#[serde(rename = "m.image")]
Image(ImageMessageEventContent), Image(ImageMessageEventContent),
/// A location message. /// A location message.
#[serde(rename = "m.location")]
Location(LocationMessageEventContent), Location(LocationMessageEventContent),
/// A notice message. /// A notice message.
#[serde(rename = "m.notice")]
Notice(NoticeMessageEventContent), Notice(NoticeMessageEventContent),
/// A server notice message. /// A server notice message.
#[serde(rename = "m.server_notice")]
ServerNotice(ServerNoticeMessageEventContent), ServerNotice(ServerNoticeMessageEventContent),
/// A text message. /// A text message.
#[serde(rename = "m.text")]
Text(TextMessageEventContent), Text(TextMessageEventContent),
/// A video message. /// A video message.
#[serde(rename = "m.video")]
Video(VideoMessageEventContent), Video(VideoMessageEventContent),
} }
@ -111,14 +119,12 @@ pub(crate) mod raw {
use std::time::SystemTime; use std::time::SystemTime;
use ruma_identifiers::{EventId, RoomId, UserId}; use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{de::DeserializeOwned, Deserialize, Deserializer}; use serde::Deserialize;
use serde_json::{from_value as from_json_value, Value as JsonValue};
use super::{ use super::{
AudioMessageEventContent, EmoteMessageEventContent, FileMessageEventContent, AudioMessageEventContent, EmoteMessageEventContent, FileMessageEventContent,
ImageMessageEventContent, LocationMessageEventContent, MessageType, ImageMessageEventContent, LocationMessageEventContent, NoticeMessageEventContent,
NoticeMessageEventContent, ServerNoticeMessageEventContent, TextMessageEventContent, ServerNoticeMessageEventContent, TextMessageEventContent, VideoMessageEventContent,
VideoMessageEventContent,
}; };
use crate::UnsignedData; use crate::UnsignedData;
@ -148,119 +154,45 @@ pub(crate) mod raw {
/// The payload for `MessageEvent`. /// The payload for `MessageEvent`.
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)] #[derive(Clone, Debug, Deserialize)]
#[serde(tag = "msgtype")]
pub enum MessageEventContent { pub enum MessageEventContent {
/// An audio message. /// An audio message.
#[serde(rename = "m.audio")]
Audio(AudioMessageEventContent), Audio(AudioMessageEventContent),
/// An emote message. /// An emote message.
#[serde(rename = "m.emote")]
Emote(EmoteMessageEventContent), Emote(EmoteMessageEventContent),
/// A file message. /// A file message.
#[serde(rename = "m.file")]
File(FileMessageEventContent), File(FileMessageEventContent),
/// An image message. /// An image message.
#[serde(rename = "m.image")]
Image(ImageMessageEventContent), Image(ImageMessageEventContent),
/// A location message. /// A location message.
#[serde(rename = "m.location")]
Location(LocationMessageEventContent), Location(LocationMessageEventContent),
/// A notice message. /// A notice message.
#[serde(rename = "m.notice")]
Notice(NoticeMessageEventContent), Notice(NoticeMessageEventContent),
/// A server notice message. /// A server notice message.
#[serde(rename = "m.server_notice")]
ServerNotice(ServerNoticeMessageEventContent), ServerNotice(ServerNoticeMessageEventContent),
/// An text message. /// An text message.
#[serde(rename = "m.text")]
Text(TextMessageEventContent), Text(TextMessageEventContent),
/// A video message. /// A video message.
#[serde(rename = "m.video")]
Video(VideoMessageEventContent), Video(VideoMessageEventContent),
} }
impl<'de> Deserialize<'de> for MessageEventContent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error as _;
fn deserialize_content<T>(
c: JsonValue,
v: fn(T) -> MessageEventContent,
) -> Result<MessageEventContent, serde_json::Error>
where
T: DeserializeOwned,
{
from_json_value::<T>(c).map(v)
}
let content: JsonValue = Deserialize::deserialize(deserializer)?;
let message_type_value = match content.get("msgtype") {
Some(value) => value.clone(),
None => return Err(D::Error::missing_field("msgtype")),
};
let message_type = match from_json_value::<MessageType>(message_type_value) {
Ok(message_type) => message_type,
Err(error) => return Err(D::Error::custom(error)),
};
match message_type {
MessageType::Audio => deserialize_content(content, Self::Audio),
MessageType::Emote => deserialize_content(content, Self::Emote),
MessageType::File => deserialize_content(content, Self::File),
MessageType::Image => deserialize_content(content, Self::Image),
MessageType::Location => deserialize_content(content, Self::Location),
MessageType::Notice => deserialize_content(content, Self::Notice),
MessageType::ServerNotice => deserialize_content(content, Self::ServerNotice),
MessageType::Text => deserialize_content(content, Self::Text),
MessageType::Video => deserialize_content(content, Self::Video),
}
.map_err(D::Error::custom)
}
}
}
/// The message type of message event, e.g. `m.image` or `m.text`.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
pub enum MessageType {
/// An audio message.
#[serde(rename = "m.audio")]
Audio,
/// An emote message.
#[serde(rename = "m.emote")]
Emote,
/// A file message.
#[serde(rename = "m.file")]
File,
/// An image message.
#[serde(rename = "m.image")]
Image,
/// A location message.
#[serde(rename = "m.location")]
Location,
/// A notice message.
#[serde(rename = "m.notice")]
Notice,
/// A server notice.
#[serde(rename = "m.server_notice")]
ServerNotice,
/// A text message.
#[serde(rename = "m.text")]
Text,
/// A video message.
#[serde(rename = "m.video")]
Video,
} }
/// The payload for an audio message. /// The payload for an audio message.
@ -302,7 +234,6 @@ pub struct AudioInfo {
/// The payload for an emote message. /// The payload for an emote message.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "msgtype", rename = "m.emote")]
pub struct EmoteMessageEventContent { pub struct EmoteMessageEventContent {
/// The emote action to perform. /// The emote action to perform.
pub body: String, pub body: String,
@ -586,20 +517,6 @@ pub struct InReplyTo {
pub event_id: EventId, pub event_id: EventId,
} }
impl_enum! {
MessageType {
Audio => "m.audio",
Emote => "m.emote",
File => "m.file",
Image => "m.image",
Location => "m.location",
Notice => "m.notice",
ServerNotice => "m.server_notice",
Text => "m.text",
Video => "m.video",
}
}
impl TextMessageEventContent { impl TextMessageEventContent {
/// A convenience constructor to create a plain text message /// A convenience constructor to create a plain text message
pub fn new_plain(body: impl Into<String>) -> TextMessageEventContent { pub fn new_plain(body: impl Into<String>) -> TextMessageEventContent {