events: Provide type for historical m.message content block instead of serde helper

This commit is contained in:
Kévin Commaille 2023-06-25 14:07:25 +02:00 committed by Kévin Commaille
parent 201f0027d4
commit df11c6d46a
2 changed files with 43 additions and 19 deletions

View File

@ -6,6 +6,24 @@ use serde::{Deserialize, Serialize};
use super::{TextContentBlock, TextRepresentation}; use super::{TextContentBlock, TextRepresentation};
/// Historical `m.message` text content block from MSC1767.
#[derive(Clone, Default, Serialize, Deserialize)]
#[serde(try_from = "MessageContentBlockSerDeHelper")]
#[serde(into = "MessageContentBlockSerDeHelper")]
pub(in crate::events) struct MessageContentBlock(Vec<TextRepresentation>);
impl From<MessageContentBlock> for TextContentBlock {
fn from(value: MessageContentBlock) -> Self {
Self(value.0)
}
}
impl From<TextContentBlock> for MessageContentBlock {
fn from(value: TextContentBlock) -> Self {
Self(value.0)
}
}
#[derive(Default, Serialize, Deserialize)] #[derive(Default, Serialize, Deserialize)]
pub(in crate::events) struct MessageContentBlockSerDeHelper { pub(in crate::events) struct MessageContentBlockSerDeHelper {
/// Plain text short form. /// Plain text short form.
@ -21,14 +39,14 @@ pub(in crate::events) struct MessageContentBlockSerDeHelper {
message: Option<Vec<TextRepresentation>>, message: Option<Vec<TextRepresentation>>,
} }
impl TryFrom<MessageContentBlockSerDeHelper> for TextContentBlock { impl TryFrom<MessageContentBlockSerDeHelper> for Vec<TextRepresentation> {
type Error = &'static str; type Error = &'static str;
fn try_from(value: MessageContentBlockSerDeHelper) -> Result<Self, Self::Error> { fn try_from(value: MessageContentBlockSerDeHelper) -> Result<Self, Self::Error> {
let MessageContentBlockSerDeHelper { text, html, message } = value; let MessageContentBlockSerDeHelper { text, html, message } = value;
if let Some(message) = message { if let Some(message) = message {
Ok(Self(message)) Ok(message)
} else { } else {
let message: Vec<_> = html let message: Vec<_> = html
.map(TextRepresentation::html) .map(TextRepresentation::html)
@ -36,7 +54,7 @@ impl TryFrom<MessageContentBlockSerDeHelper> for TextContentBlock {
.chain(text.map(TextRepresentation::plain)) .chain(text.map(TextRepresentation::plain))
.collect(); .collect();
if !message.is_empty() { if !message.is_empty() {
Ok(Self(message)) Ok(message)
} else { } else {
Err("missing at least one of fields `org.matrix.msc1767.text`, `org.matrix.msc1767.html` or `org.matrix.msc1767.message`") Err("missing at least one of fields `org.matrix.msc1767.text`, `org.matrix.msc1767.html` or `org.matrix.msc1767.message`")
} }
@ -44,15 +62,23 @@ impl TryFrom<MessageContentBlockSerDeHelper> for TextContentBlock {
} }
} }
impl From<TextContentBlock> for MessageContentBlockSerDeHelper { impl TryFrom<MessageContentBlockSerDeHelper> for MessageContentBlock {
fn from(value: TextContentBlock) -> Self { type Error = &'static str;
fn try_from(value: MessageContentBlockSerDeHelper) -> Result<Self, Self::Error> {
Ok(Self(value.try_into()?))
}
}
impl From<Vec<TextRepresentation>> for MessageContentBlockSerDeHelper {
fn from(value: Vec<TextRepresentation>) -> Self {
let has_shortcut = let has_shortcut =
|message: &TextRepresentation| matches!(&*message.mimetype, "text/plain" | "text/html"); |message: &TextRepresentation| matches!(&*message.mimetype, "text/plain" | "text/html");
if value.iter().all(has_shortcut) { if value.iter().all(has_shortcut) {
let mut helper = Self::default(); let mut helper = Self::default();
for message in value.0.into_iter() { for message in value.into_iter() {
if message.mimetype == "text/plain" { if message.mimetype == "text/plain" {
helper.text = Some(message.body); helper.text = Some(message.body);
} else if message.mimetype == "text/html" { } else if message.mimetype == "text/html" {
@ -62,7 +88,13 @@ impl From<TextContentBlock> for MessageContentBlockSerDeHelper {
helper helper
} else { } else {
Self { message: Some(value.0), ..Default::default() } Self { message: Some(value), ..Default::default() }
} }
} }
} }
impl From<MessageContentBlock> for MessageContentBlockSerDeHelper {
fn from(value: MessageContentBlock) -> Self {
value.0.into()
}
}

View File

@ -83,7 +83,7 @@ pub(in super::super) mod msc3488 {
use crate::{ use crate::{
events::{ events::{
location::{AssetContent, LocationContent}, location::{AssetContent, LocationContent},
message::historical_serde::MessageContentBlockSerDeHelper, message::historical_serde::MessageContentBlock,
room::message::{LocationInfo, LocationMessageEventContent}, room::message::{LocationInfo, LocationMessageEventContent},
}, },
MilliSecondsSinceUnixEpoch, MilliSecondsSinceUnixEpoch,
@ -101,7 +101,7 @@ pub(in super::super) mod msc3488 {
pub info: Option<Box<LocationInfo>>, pub info: Option<Box<LocationInfo>>,
#[serde(flatten)] #[serde(flatten)]
pub message: MessageContentBlockSerDeHelper, pub message: Option<MessageContentBlock>,
#[serde(rename = "org.matrix.msc3488.location", skip_serializing_if = "Option::is_none")] #[serde(rename = "org.matrix.msc3488.location", skip_serializing_if = "Option::is_none")]
pub location: Option<LocationContent>, pub location: Option<LocationContent>,
@ -118,15 +118,7 @@ pub(in super::super) mod msc3488 {
let LocationMessageEventContent { body, geo_uri, info, message, location, asset, ts } = let LocationMessageEventContent { body, geo_uri, info, message, location, asset, ts } =
value; value;
Self { Self { body, geo_uri, info, message: message.map(Into::into), location, asset, ts }
body,
geo_uri,
info,
message: message.map(Into::into).unwrap_or_default(),
location,
asset,
ts,
}
} }
} }
@ -146,7 +138,7 @@ pub(in super::super) mod msc3488 {
body, body,
geo_uri, geo_uri,
info, info,
message: message.try_into().ok(), message: message.map(Into::into),
location, location,
asset, asset,
ts, ts,