ruma_events/room/message/
content_serde.rs1use as_variant::as_variant;
4use ruma_common::serde::{JsonObject, from_raw_json_value};
5use serde::{Deserialize, de};
6use serde_json::{Value as JsonValue, value::RawValue as RawJsonValue};
7
8#[cfg(feature = "unstable-msc4274")]
9use super::gallery::{CustomGalleryItemContent, GalleryItemType};
10use super::{
11 MessageType, RoomMessageEventContent, RoomMessageEventContentWithoutRelation,
12 relation_serde::deserialize_relation,
13};
14use crate::{Mentions, room::message::CustomMessageContent};
15
16impl<'de> Deserialize<'de> for RoomMessageEventContent {
17 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
18 where
19 D: de::Deserializer<'de>,
20 {
21 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
22
23 let mut deserializer = serde_json::Deserializer::from_str(json.get());
24 let relates_to = deserialize_relation(&mut deserializer).map_err(de::Error::custom)?;
25
26 let MentionsDeHelper { mentions } = from_raw_json_value(&json)?;
27
28 Ok(Self { msgtype: from_raw_json_value(&json)?, relates_to, mentions })
29 }
30}
31
32impl<'de> Deserialize<'de> for RoomMessageEventContentWithoutRelation {
33 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
34 where
35 D: de::Deserializer<'de>,
36 {
37 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
38
39 let MentionsDeHelper { mentions } = from_raw_json_value(&json)?;
40
41 Ok(Self { msgtype: from_raw_json_value(&json)?, mentions })
42 }
43}
44
45#[derive(Deserialize)]
46struct MentionsDeHelper {
47 #[serde(rename = "m.mentions")]
48 mentions: Option<Mentions>,
49}
50
51#[derive(Debug, Deserialize)]
53struct MessageTypeDeHelper {
54 msgtype: String,
56}
57
58impl<'de> Deserialize<'de> for MessageType {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: de::Deserializer<'de>,
62 {
63 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
64 let MessageTypeDeHelper { msgtype } = from_raw_json_value(&json)?;
65
66 Ok(match msgtype.as_ref() {
67 "m.audio" => Self::Audio(from_raw_json_value(&json)?),
68 "m.emote" => Self::Emote(from_raw_json_value(&json)?),
69 "m.file" => Self::File(from_raw_json_value(&json)?),
70 #[cfg(feature = "unstable-msc4274")]
71 "dm.filament.gallery" => Self::Gallery(from_raw_json_value(&json)?),
72 "m.image" => Self::Image(from_raw_json_value(&json)?),
73 "m.location" => Self::Location(from_raw_json_value(&json)?),
74 "m.notice" => Self::Notice(from_raw_json_value(&json)?),
75 "m.server_notice" => Self::ServerNotice(from_raw_json_value(&json)?),
76 "m.text" => Self::Text(from_raw_json_value(&json)?),
77 "m.video" => Self::Video(from_raw_json_value(&json)?),
78 "m.key.verification.request" => Self::VerificationRequest(from_raw_json_value(&json)?),
79 _ => {
80 let mut data = from_raw_json_value::<JsonObject, _>(&json)?;
81 data.remove("msgtype");
82 let body = data
83 .remove("body")
84 .and_then(|value| as_variant!(value, JsonValue::String))
85 .ok_or_else(|| de::Error::missing_field("body"))?;
86
87 Self::_Custom(CustomMessageContent { msgtype, body, data })
88 }
89 })
90 }
91}
92
93#[derive(Debug, Deserialize)]
95#[cfg(feature = "unstable-msc4274")]
96struct ItemTypeDeHelper {
97 itemtype: String,
99}
100
101#[cfg(feature = "unstable-msc4274")]
102impl<'de> Deserialize<'de> for GalleryItemType {
103 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
104 where
105 D: de::Deserializer<'de>,
106 {
107 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
108 let ItemTypeDeHelper { itemtype } = from_raw_json_value(&json)?;
109
110 Ok(match itemtype.as_ref() {
111 "m.audio" => Self::Audio(from_raw_json_value(&json)?),
112 "m.file" => Self::File(from_raw_json_value(&json)?),
113 "m.image" => Self::Image(from_raw_json_value(&json)?),
114 "m.video" => Self::Video(from_raw_json_value(&json)?),
115 _ => {
116 let mut data = from_raw_json_value::<JsonObject, _>(&json)?;
117 data.remove("itemtype");
118 let body = data
119 .remove("body")
120 .and_then(|value| as_variant!(value, JsonValue::String))
121 .ok_or_else(|| de::Error::missing_field("body"))?;
122
123 Self::_Custom(CustomGalleryItemContent { itemtype, body, data })
124 }
125 })
126 }
127}
128
129#[allow(unreachable_pub)] #[cfg(feature = "unstable-msc3488")]
131pub(in super::super) mod msc3488 {
132 use ruma_common::MilliSecondsSinceUnixEpoch;
133 use serde::{Deserialize, Serialize};
134
135 use crate::{
136 location::{AssetContent, LocationContent},
137 message::historical_serde::MessageContentBlock,
138 room::message::{LocationInfo, LocationMessageEventContent},
139 };
140
141 #[derive(Serialize, Deserialize)]
143 pub(in super::super) struct LocationMessageEventContentSerDeHelper {
144 pub body: String,
145
146 pub geo_uri: String,
147
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub info: Option<Box<LocationInfo>>,
150
151 #[serde(flatten)]
152 pub message: Option<MessageContentBlock>,
153
154 #[serde(rename = "org.matrix.msc3488.location", skip_serializing_if = "Option::is_none")]
155 pub location: Option<LocationContent>,
156
157 #[serde(rename = "org.matrix.msc3488.asset", skip_serializing_if = "Option::is_none")]
158 pub asset: Option<AssetContent>,
159
160 #[serde(rename = "org.matrix.msc3488.ts", skip_serializing_if = "Option::is_none")]
161 pub ts: Option<MilliSecondsSinceUnixEpoch>,
162 }
163
164 impl From<LocationMessageEventContent> for LocationMessageEventContentSerDeHelper {
165 fn from(value: LocationMessageEventContent) -> Self {
166 let LocationMessageEventContent { body, geo_uri, info, message, location, asset, ts } =
167 value;
168
169 Self { body, geo_uri, info, message: message.map(Into::into), location, asset, ts }
170 }
171 }
172
173 impl From<LocationMessageEventContentSerDeHelper> for LocationMessageEventContent {
174 fn from(value: LocationMessageEventContentSerDeHelper) -> Self {
175 let LocationMessageEventContentSerDeHelper {
176 body,
177 geo_uri,
178 info,
179 message,
180 location,
181 asset,
182 ts,
183 } = value;
184
185 LocationMessageEventContent {
186 body,
187 geo_uri,
188 info,
189 message: message.map(Into::into),
190 location,
191 asset,
192 ts,
193 }
194 }
195 }
196}