ruma_events/room/message/
gallery.rs1use std::borrow::Cow;
2
3use ruma_common::serde::JsonObject;
4use serde::{Deserialize, Serialize, de::DeserializeOwned};
5use serde_json::Value as JsonValue;
6
7use super::{
8 AudioMessageEventContent, FileMessageEventContent, FormattedBody, ImageMessageEventContent,
9 VideoMessageEventContent,
10};
11
12#[derive(Clone, Debug, Deserialize, Serialize)]
14#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
15pub struct GalleryMessageEventContent {
16 pub body: String,
18
19 #[serde(flatten)]
21 pub formatted: Option<FormattedBody>,
22
23 pub itemtypes: Vec<GalleryItemType>,
25}
26
27impl GalleryMessageEventContent {
28 pub fn new(
30 body: String,
31 formatted: Option<FormattedBody>,
32 itemtypes: Vec<GalleryItemType>,
33 ) -> Self {
34 Self { body, formatted, itemtypes }
35 }
36}
37
38#[derive(Clone, Debug, Serialize)]
40#[serde(tag = "itemtype")]
41#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
42pub enum GalleryItemType {
43 #[serde(rename = "m.audio")]
45 Audio(AudioMessageEventContent),
46
47 #[serde(rename = "m.file")]
49 File(FileMessageEventContent),
50
51 #[serde(rename = "m.image")]
53 Image(ImageMessageEventContent),
54
55 #[serde(rename = "m.video")]
57 Video(VideoMessageEventContent),
58
59 #[doc(hidden)]
61 #[serde(untagged)]
62 _Custom(CustomGalleryItemContent),
63}
64
65impl GalleryItemType {
66 pub fn new(itemtype: &str, body: String, data: JsonObject) -> serde_json::Result<Self> {
81 fn deserialize_variant<T: DeserializeOwned>(
82 body: String,
83 mut obj: JsonObject,
84 ) -> serde_json::Result<T> {
85 obj.insert("body".into(), body.into());
86 serde_json::from_value(JsonValue::Object(obj))
87 }
88
89 Ok(match itemtype {
90 "m.audio" => Self::Audio(deserialize_variant(body, data)?),
91 "m.file" => Self::File(deserialize_variant(body, data)?),
92 "m.image" => Self::Image(deserialize_variant(body, data)?),
93 "m.video" => Self::Video(deserialize_variant(body, data)?),
94 _ => Self::_Custom(CustomGalleryItemContent {
95 itemtype: itemtype.to_owned(),
96 body,
97 data,
98 }),
99 })
100 }
101
102 pub fn itemtype(&self) -> &str {
104 match self {
105 Self::Audio(_) => "m.audio",
106 Self::File(_) => "m.file",
107 Self::Image(_) => "m.image",
108 Self::Video(_) => "m.video",
109 Self::_Custom(c) => &c.itemtype,
110 }
111 }
112
113 pub fn body(&self) -> &str {
115 match self {
116 GalleryItemType::Audio(m) => &m.body,
117 GalleryItemType::File(m) => &m.body,
118 GalleryItemType::Image(m) => &m.body,
119 GalleryItemType::Video(m) => &m.body,
120 GalleryItemType::_Custom(m) => &m.body,
121 }
122 }
123
124 pub fn data(&self) -> Cow<'_, JsonObject> {
132 fn serialize<T: Serialize>(obj: &T) -> JsonObject {
133 match serde_json::to_value(obj).expect("item type serialization to succeed") {
134 JsonValue::Object(mut obj) => {
135 obj.remove("body");
136 obj
137 }
138 _ => panic!("all item types must serialize to objects"),
139 }
140 }
141
142 match self {
143 Self::Audio(d) => Cow::Owned(serialize(d)),
144 Self::File(d) => Cow::Owned(serialize(d)),
145 Self::Image(d) => Cow::Owned(serialize(d)),
146 Self::Video(d) => Cow::Owned(serialize(d)),
147 Self::_Custom(c) => Cow::Borrowed(&c.data),
148 }
149 }
150}
151
152#[doc(hidden)]
154#[derive(Clone, Debug, Serialize)]
155pub struct CustomGalleryItemContent {
156 pub(super) itemtype: String,
158
159 pub(super) body: String,
161
162 #[serde(flatten)]
164 pub(super) data: JsonObject,
165}