ruma_events/message/
historical_serde.rs
1use serde::{Deserialize, Serialize};
6
7use super::{TextContentBlock, TextRepresentation};
8
9#[derive(Clone, Default, Serialize, Deserialize)]
11#[serde(try_from = "MessageContentBlockSerDeHelper")]
12#[serde(into = "MessageContentBlockSerDeHelper")]
13pub(crate) struct MessageContentBlock(Vec<TextRepresentation>);
14
15impl From<MessageContentBlock> for TextContentBlock {
16 fn from(value: MessageContentBlock) -> Self {
17 Self(value.0)
18 }
19}
20
21impl From<TextContentBlock> for MessageContentBlock {
22 fn from(value: TextContentBlock) -> Self {
23 Self(value.0)
24 }
25}
26
27#[derive(Default, Serialize, Deserialize)]
28pub(crate) struct MessageContentBlockSerDeHelper {
29 #[serde(rename = "org.matrix.msc1767.text", skip_serializing_if = "Option::is_none")]
31 text: Option<String>,
32
33 #[serde(rename = "org.matrix.msc1767.html", skip_serializing_if = "Option::is_none")]
35 html: Option<String>,
36
37 #[serde(rename = "org.matrix.msc1767.message", skip_serializing_if = "Option::is_none")]
39 message: Option<Vec<TextRepresentation>>,
40}
41
42impl TryFrom<MessageContentBlockSerDeHelper> for Vec<TextRepresentation> {
43 type Error = &'static str;
44
45 fn try_from(value: MessageContentBlockSerDeHelper) -> Result<Self, Self::Error> {
46 let MessageContentBlockSerDeHelper { text, html, message } = value;
47
48 if let Some(message) = message {
49 Ok(message)
50 } else {
51 let message: Vec<_> = html
52 .map(TextRepresentation::html)
53 .into_iter()
54 .chain(text.map(TextRepresentation::plain))
55 .collect();
56 if !message.is_empty() {
57 Ok(message)
58 } else {
59 Err("missing at least one of fields `org.matrix.msc1767.text`, `org.matrix.msc1767.html` or `org.matrix.msc1767.message`")
60 }
61 }
62 }
63}
64
65impl TryFrom<MessageContentBlockSerDeHelper> for MessageContentBlock {
66 type Error = &'static str;
67
68 fn try_from(value: MessageContentBlockSerDeHelper) -> Result<Self, Self::Error> {
69 Ok(Self(value.try_into()?))
70 }
71}
72
73impl From<Vec<TextRepresentation>> for MessageContentBlockSerDeHelper {
74 fn from(value: Vec<TextRepresentation>) -> Self {
75 let has_shortcut =
76 |message: &TextRepresentation| matches!(&*message.mimetype, "text/plain" | "text/html");
77
78 if value.iter().all(has_shortcut) {
79 let mut helper = Self::default();
80
81 for message in value.into_iter() {
82 if message.mimetype == "text/plain" {
83 helper.text = Some(message.body);
84 } else if message.mimetype == "text/html" {
85 helper.html = Some(message.body);
86 }
87 }
88
89 helper
90 } else {
91 Self { message: Some(value), ..Default::default() }
92 }
93 }
94}
95
96impl From<MessageContentBlock> for MessageContentBlockSerDeHelper {
97 fn from(value: MessageContentBlock) -> Self {
98 value.0.into()
99 }
100}