events: Avoid unnecessary allocations during conversion
This commit is contained in:
parent
96155915fe
commit
bda17c3662
@ -89,12 +89,17 @@ impl AudioEventContent {
|
||||
#[cfg(feature = "unstable-msc3245")]
|
||||
voice: _,
|
||||
} = content;
|
||||
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
|
||||
|
||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
||||
let file = file.unwrap_or_else(|| {
|
||||
FileContent::from_room_message_content(source, info.as_deref(), None)
|
||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
||||
});
|
||||
let audio = audio.unwrap_or_else(|| {
|
||||
let mut content = AudioContent::new();
|
||||
content.duration = duration;
|
||||
content
|
||||
});
|
||||
let audio = audio.or_else(|| info.as_deref().map(Into::into)).unwrap_or_default();
|
||||
|
||||
Self { message, file, audio, relates_to }
|
||||
}
|
||||
@ -136,19 +141,17 @@ impl AudioContent {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Creates a new `AudioContent` with the given duration.
|
||||
pub(crate) fn from_room_message_content(duration: Duration) -> Self {
|
||||
Self { duration: Some(duration), ..Default::default() }
|
||||
}
|
||||
|
||||
/// Whether this `AudioContent` is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.duration.is_none() && self.waveform.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AudioInfo> for AudioContent {
|
||||
fn from(info: &AudioInfo) -> Self {
|
||||
let AudioInfo { duration, .. } = info;
|
||||
Self { duration: duration.to_owned(), ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// The waveform representation of audio content.
|
||||
///
|
||||
/// Must include between 30 and 120 `Amplitude`s.
|
||||
|
@ -12,10 +12,9 @@ use super::{
|
||||
message::MessageContent,
|
||||
room::{
|
||||
message::{
|
||||
AudioInfo, FileInfo, FileMessageEventContent, MessageType, Relation,
|
||||
RoomMessageEventContent, VideoInfo,
|
||||
FileInfo, FileMessageEventContent, MessageType, Relation, RoomMessageEventContent,
|
||||
},
|
||||
EncryptedFile, ImageInfo, JsonWebKey, MediaSource,
|
||||
EncryptedFile, JsonWebKey, MediaSource,
|
||||
},
|
||||
};
|
||||
use crate::{serde::Base64, OwnedMxcUri};
|
||||
@ -108,10 +107,11 @@ impl FileEventContent {
|
||||
relates_to: Option<Relation>,
|
||||
) -> Self {
|
||||
let FileMessageEventContent { body, filename, source, info, message, file } = content;
|
||||
let FileInfo { mimetype, size, .. } = info.map(|info| *info).unwrap_or_default();
|
||||
|
||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
||||
let file = file.unwrap_or_else(|| {
|
||||
FileContent::from_room_message_content(source, info.as_deref(), filename)
|
||||
FileContent::from_room_message_content(source, filename, mimetype, size)
|
||||
});
|
||||
|
||||
Self { message, file, relates_to }
|
||||
@ -167,16 +167,15 @@ impl FileContent {
|
||||
/// Create a new `FileContent` with the given media source, file info and filename.
|
||||
pub fn from_room_message_content(
|
||||
source: MediaSource,
|
||||
info: Option<impl Into<FileContentInfo>>,
|
||||
filename: Option<String>,
|
||||
mimetype: Option<String>,
|
||||
size: Option<UInt>,
|
||||
) -> Self {
|
||||
let (url, encryption_info) = match source {
|
||||
MediaSource::Plain(url) => (url, None),
|
||||
MediaSource::Encrypted(file) => (file.url.clone(), Some(Box::new((&*file).into()))),
|
||||
};
|
||||
let info = FileContentInfo::from_room_message_content(info, filename).map(Box::new);
|
||||
let (url, encryption_info) = source.into_extensible_content();
|
||||
let info =
|
||||
FileContentInfo::from_room_message_content(filename, mimetype, size).map(Box::new);
|
||||
|
||||
Self { url, encryption_info, info }
|
||||
Self { url, encryption_info: encryption_info.map(Box::new), info }
|
||||
}
|
||||
|
||||
/// Whether the file is encrypted.
|
||||
@ -208,51 +207,22 @@ impl FileContentInfo {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Create a new `FileContentInfo` with the given file info and filename.
|
||||
/// Create a new `FileContentInfo` with the given filename, mimetype and size.
|
||||
///
|
||||
/// Returns `None` if both parameters are `None`.
|
||||
/// Returns `None` if all parameters are `None`.
|
||||
pub fn from_room_message_content(
|
||||
info: Option<impl Into<FileContentInfo>>,
|
||||
filename: Option<String>,
|
||||
mimetype: Option<String>,
|
||||
size: Option<UInt>,
|
||||
) -> Option<Self> {
|
||||
if filename.is_none() && info.is_none() {
|
||||
if filename.is_none() && mimetype.is_none() && size.is_none() {
|
||||
None
|
||||
} else {
|
||||
let mut info: Self = info.map(Into::into).unwrap_or_default();
|
||||
info.name = filename;
|
||||
Some(info)
|
||||
Some(Self { name: filename, mimetype, size })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AudioInfo> for FileContentInfo {
|
||||
fn from(info: &AudioInfo) -> Self {
|
||||
let AudioInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned(), ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&FileInfo> for FileContentInfo {
|
||||
fn from(info: &FileInfo) -> Self {
|
||||
let FileInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned(), ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImageInfo> for FileContentInfo {
|
||||
fn from(info: &ImageInfo) -> Self {
|
||||
let ImageInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned(), ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&VideoInfo> for FileContentInfo {
|
||||
fn from(info: &VideoInfo) -> Self {
|
||||
let VideoInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned(), ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// The encryption info of a file sent to a room with end-to-end encryption enabled.
|
||||
///
|
||||
/// To create an instance of this type, first create a `EncryptedContentInit` and convert it via
|
||||
@ -310,7 +280,7 @@ impl From<EncryptedContentInit> for EncryptedContent {
|
||||
|
||||
impl From<&EncryptedFile> for EncryptedContent {
|
||||
fn from(encrypted: &EncryptedFile) -> Self {
|
||||
let EncryptedFile { key, iv, hashes, v, .. } = encrypted.to_owned();
|
||||
Self { key, iv, hashes, v }
|
||||
let EncryptedFile { key, iv, hashes, v, .. } = encrypted;
|
||||
Self { key: key.to_owned(), iv: iv.to_owned(), hashes: hashes.to_owned(), v: v.to_owned() }
|
||||
}
|
||||
}
|
||||
|
@ -104,25 +104,21 @@ impl ImageEventContent {
|
||||
thumbnail,
|
||||
caption,
|
||||
} = content;
|
||||
let ImageInfo { height, width, mimetype, size, thumbnail_info, thumbnail_source, .. } =
|
||||
info.map(|info| *info).unwrap_or_default();
|
||||
|
||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
||||
let file = file.unwrap_or_else(|| {
|
||||
FileContent::from_room_message_content(source, info.as_deref(), None)
|
||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
||||
});
|
||||
let image =
|
||||
image.or_else(|| info.as_deref().map(|info| Box::new(info.into()))).unwrap_or_default();
|
||||
let thumbnail = thumbnail
|
||||
.or_else(|| {
|
||||
info.as_deref()
|
||||
.and_then(|info| {
|
||||
ThumbnailContent::from_room_message_content(
|
||||
info.thumbnail_source.as_ref(),
|
||||
info.thumbnail_info.as_deref(),
|
||||
)
|
||||
})
|
||||
.map(|thumbnail| vec![thumbnail])
|
||||
})
|
||||
let image = image
|
||||
.or_else(|| ImageContent::from_room_message_content(width, height).map(Box::new))
|
||||
.unwrap_or_default();
|
||||
let thumbnail = thumbnail.unwrap_or_else(|| {
|
||||
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
|
||||
.into_iter()
|
||||
.collect()
|
||||
});
|
||||
|
||||
Self { message, file, image, thumbnail, caption, relates_to }
|
||||
}
|
||||
@ -165,26 +161,26 @@ impl ImageContent {
|
||||
Self { height: Some(height), width: Some(width) }
|
||||
}
|
||||
|
||||
/// Creates a new `ImageContent` with the given optional width and height.
|
||||
///
|
||||
/// Returns `None` if both parameters are `None`.
|
||||
pub(crate) fn from_room_message_content(
|
||||
width: Option<UInt>,
|
||||
height: Option<UInt>,
|
||||
) -> Option<Self> {
|
||||
if width.is_none() && height.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Self { width, height })
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this `ImageContent` is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.height.is_none() && self.width.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImageInfo> for ImageContent {
|
||||
fn from(info: &ImageInfo) -> Self {
|
||||
let ImageInfo { height, width, .. } = info;
|
||||
Self { height: height.to_owned(), width: width.to_owned() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ThumbnailInfo> for ImageContent {
|
||||
fn from(info: &ThumbnailInfo) -> Self {
|
||||
let ThumbnailInfo { height, width, .. } = info;
|
||||
Self { height: height.to_owned(), width: width.to_owned() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Thumbnail content.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
@ -208,13 +204,14 @@ impl ThumbnailContent {
|
||||
///
|
||||
/// Returns `None` if no thumbnail was found.
|
||||
pub fn from_room_message_content(
|
||||
thumbnail_source: Option<&MediaSource>,
|
||||
thumbnail_info: Option<&ThumbnailInfo>,
|
||||
source: Option<MediaSource>,
|
||||
info: Option<Box<ThumbnailInfo>>,
|
||||
) -> Option<Self> {
|
||||
thumbnail_source.map(|thumbnail_source| {
|
||||
let file =
|
||||
ThumbnailFileContent::from_room_message_content(thumbnail_source, thumbnail_info);
|
||||
let image = thumbnail_info.map(|info| Box::new(info.into()));
|
||||
source.map(|source| {
|
||||
let ThumbnailInfo { height, width, mimetype, size } = *info.unwrap_or_default();
|
||||
|
||||
let file = ThumbnailFileContent::from_room_message_content(source, mimetype, size);
|
||||
let image = ImageContent::from_room_message_content(width, height).map(Box::new);
|
||||
|
||||
Self { file, image }
|
||||
})
|
||||
@ -259,18 +256,15 @@ impl ThumbnailFileContent {
|
||||
///
|
||||
/// Returns `None` if no thumbnail was found.
|
||||
fn from_room_message_content(
|
||||
thumbnail_source: &MediaSource,
|
||||
thumbnail_info: Option<&ThumbnailInfo>,
|
||||
source: MediaSource,
|
||||
mimetype: Option<String>,
|
||||
size: Option<UInt>,
|
||||
) -> Self {
|
||||
match thumbnail_source {
|
||||
MediaSource::Plain(url) => {
|
||||
Self::plain(url.to_owned(), thumbnail_info.map(|info| Box::new(info.into())))
|
||||
}
|
||||
MediaSource::Encrypted(file) => Self::encrypted(
|
||||
file.url.clone(),
|
||||
(&**file).into(),
|
||||
thumbnail_info.map(|info| Box::new(info.into())),
|
||||
),
|
||||
let info =
|
||||
ThumbnailFileContentInfo::from_room_message_content(mimetype, size).map(Box::new);
|
||||
match source.into_extensible_content() {
|
||||
(url, None) => Self::plain(url, info),
|
||||
(url, Some(encryption_info)) => Self::encrypted(url, encryption_info, info),
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,11 +292,15 @@ impl ThumbnailFileContentInfo {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ThumbnailInfo> for ThumbnailFileContentInfo {
|
||||
fn from(info: &ThumbnailInfo) -> Self {
|
||||
let ThumbnailInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned() }
|
||||
/// Creates a new `ThumbnailFileContentInfo` with the given optional MIME type and size.
|
||||
///
|
||||
/// Returns `None` if both the mimetype and the size are `None`.
|
||||
fn from_room_message_content(mimetype: Option<String>, size: Option<UInt>) -> Option<Self> {
|
||||
if mimetype.is_none() && size.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Self { mimetype, size })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use js_int::UInt;
|
||||
use serde::{de, Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "unstable-msc3551")]
|
||||
use super::file::{EncryptedContent, FileContent};
|
||||
use super::file::{EncryptedContent, EncryptedContentInit, FileContent};
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
use super::{
|
||||
file::FileContentInfo,
|
||||
@ -55,6 +55,19 @@ pub enum MediaSource {
|
||||
Encrypted(Box<EncryptedFile>),
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-msc3551")]
|
||||
impl MediaSource {
|
||||
pub(crate) fn into_extensible_content(self) -> (OwnedMxcUri, Option<EncryptedContent>) {
|
||||
match self {
|
||||
MediaSource::Plain(url) => (url, None),
|
||||
MediaSource::Encrypted(encrypted_file) => {
|
||||
let EncryptedFile { url, key, iv, hashes, v } = *encrypted_file;
|
||||
(url, Some(EncryptedContentInit { key, iv, hashes, v }.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Custom implementation of `Deserialize`, because serde doesn't guarantee what variant will be
|
||||
// deserialized for "externally tagged"¹ enums where multiple "tag" fields exist.
|
||||
//
|
||||
|
@ -8,7 +8,7 @@ use crate::events::voice::VoiceContent;
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
use crate::events::{
|
||||
audio::AudioContent,
|
||||
file::{FileContent, FileContentInfo},
|
||||
file::{EncryptedContent, FileContent, FileContentInfo},
|
||||
message::MessageContent,
|
||||
};
|
||||
use crate::{
|
||||
@ -84,10 +84,22 @@ impl AudioMessageEventContent {
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
file: Some(FileContent::plain(
|
||||
url.clone(),
|
||||
info.as_deref().map(|info| Box::new(info.into())),
|
||||
info.as_deref().and_then(|info| {
|
||||
FileContentInfo::from_room_message_content(
|
||||
None,
|
||||
info.mimetype.to_owned(),
|
||||
info.size.to_owned(),
|
||||
)
|
||||
.map(Box::new)
|
||||
}),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
audio: Some(info.as_deref().map_or_else(AudioContent::default, Into::into)),
|
||||
audio: Some(
|
||||
info.as_deref()
|
||||
.and_then(|info| info.duration)
|
||||
.map(AudioContent::from_room_message_content)
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
#[cfg(feature = "unstable-msc3245")]
|
||||
voice: None,
|
||||
body,
|
||||
@ -103,7 +115,11 @@ impl AudioMessageEventContent {
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
message: Some(MessageContent::plain(body.clone())),
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
file: Some(FileContent::encrypted(file.url.clone(), (&file).into(), None)),
|
||||
file: Some(FileContent::encrypted(
|
||||
file.url.clone(),
|
||||
EncryptedContent::from(&file),
|
||||
None,
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
audio: Some(AudioContent::default()),
|
||||
#[cfg(feature = "unstable-msc3245")]
|
||||
@ -184,19 +200,24 @@ impl AudioInfo {
|
||||
}
|
||||
|
||||
/// Create an `AudioInfo` from the given file info and audio info.
|
||||
///
|
||||
/// Returns `None` if the `AudioInfo` would be empty.
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
pub fn from_extensible_content(
|
||||
file_info: Option<&FileContentInfo>,
|
||||
audio: &AudioContent,
|
||||
) -> Option<Self> {
|
||||
if file_info.is_none() && audio.is_empty() {
|
||||
let (mimetype, size) = file_info
|
||||
.map(|info| {
|
||||
let FileContentInfo { mimetype, size, .. } = info;
|
||||
(mimetype.to_owned(), size.to_owned())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let AudioContent { duration, .. } = audio;
|
||||
|
||||
if duration.is_none() && mimetype.is_none() && size.is_none() {
|
||||
None
|
||||
} else {
|
||||
let (mimetype, size) = file_info
|
||||
.map(|info| (info.mimetype.to_owned(), info.size.to_owned()))
|
||||
.unwrap_or_default();
|
||||
let AudioContent { duration, .. } = audio;
|
||||
|
||||
Some(Self { duration: duration.to_owned(), mimetype, size })
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,14 @@ impl FileMessageEventContent {
|
||||
#[cfg(feature = "unstable-msc3551")]
|
||||
file: Some(FileContent::plain(
|
||||
url.clone(),
|
||||
info.as_deref().map(|info| Box::new(info.into())),
|
||||
info.as_deref().and_then(|info| {
|
||||
FileContentInfo::from_room_message_content(
|
||||
None,
|
||||
info.mimetype.to_owned(),
|
||||
info.size.to_owned(),
|
||||
)
|
||||
.map(Box::new)
|
||||
}),
|
||||
)),
|
||||
body,
|
||||
filename: None,
|
||||
@ -101,7 +108,10 @@ impl FileMessageEventContent {
|
||||
message[0].body.clone()
|
||||
};
|
||||
let filename = file.info.as_deref().and_then(|info| info.name.clone());
|
||||
let info = file.info.as_deref().map(|info| Box::new(info.into()));
|
||||
let info = file.info.as_deref().and_then(|info| {
|
||||
FileInfo::from_extensible_content(info.mimetype.to_owned(), info.size.to_owned())
|
||||
.map(Box::new)
|
||||
});
|
||||
let source = (&file).into();
|
||||
|
||||
Self { message: Some(message), file: Some(file), body, filename, source, info }
|
||||
@ -138,12 +148,16 @@ impl FileInfo {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-msc3551")]
|
||||
impl From<&FileContentInfo> for FileInfo {
|
||||
fn from(info: &FileContentInfo) -> Self {
|
||||
let FileContentInfo { mimetype, size, .. } = info;
|
||||
Self { mimetype: mimetype.to_owned(), size: size.to_owned(), ..Default::default() }
|
||||
/// Creates a `FileInfo` with the given optional mimetype and size.
|
||||
///
|
||||
/// Returns `None` if the `FileInfo` would be empty.
|
||||
#[cfg(feature = "unstable-msc3551")]
|
||||
fn from_extensible_content(mimetype: Option<String>, size: Option<UInt>) -> Option<Self> {
|
||||
if mimetype.is_none() && size.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Self { mimetype, size, ..Default::default() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
use crate::events::{
|
||||
file::FileContent,
|
||||
file::{FileContent, FileContentInfo},
|
||||
image::{ImageContent, ThumbnailContent},
|
||||
message::MessageContent,
|
||||
};
|
||||
@ -89,17 +89,30 @@ impl ImageMessageEventContent {
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
file: Some(FileContent::plain(
|
||||
url.clone(),
|
||||
info.as_deref().map(|info| Box::new(info.into())),
|
||||
info.as_deref().and_then(|info| {
|
||||
FileContentInfo::from_room_message_content(
|
||||
None,
|
||||
info.mimetype.to_owned(),
|
||||
info.size,
|
||||
)
|
||||
.map(Box::new)
|
||||
}),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
image: Some(Box::new(info.as_deref().map_or_else(ImageContent::default, Into::into))),
|
||||
image: Some(Box::new(
|
||||
info.as_deref()
|
||||
.and_then(|info| {
|
||||
ImageContent::from_room_message_content(info.width, info.height)
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
thumbnail: info
|
||||
.as_deref()
|
||||
.and_then(|info| {
|
||||
ThumbnailContent::from_room_message_content(
|
||||
info.thumbnail_source.as_ref(),
|
||||
info.thumbnail_info.as_deref(),
|
||||
info.thumbnail_source.to_owned(),
|
||||
info.thumbnail_info.to_owned(),
|
||||
)
|
||||
})
|
||||
.map(|thumbnail| vec![thumbnail]),
|
||||
|
@ -91,17 +91,34 @@ impl VideoMessageEventContent {
|
||||
#[cfg(feature = "unstable-msc3553")]
|
||||
file: Some(FileContent::plain(
|
||||
url.clone(),
|
||||
info.as_deref().map(|info| Box::new(info.into())),
|
||||
info.as_deref().and_then(|info| {
|
||||
FileContentInfo::from_room_message_content(
|
||||
None,
|
||||
info.mimetype.to_owned(),
|
||||
info.size.to_owned(),
|
||||
)
|
||||
.map(Box::new)
|
||||
}),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3553")]
|
||||
video: Some(Box::new(info.as_deref().map_or_else(VideoContent::default, Into::into))),
|
||||
video: Some(Box::new(
|
||||
info.as_deref()
|
||||
.map(|info| {
|
||||
VideoContent::from_room_message_content(
|
||||
info.height,
|
||||
info.width,
|
||||
info.duration,
|
||||
)
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3553")]
|
||||
thumbnail: info
|
||||
.as_deref()
|
||||
.and_then(|info| {
|
||||
ThumbnailContent::from_room_message_content(
|
||||
info.thumbnail_source.as_ref(),
|
||||
info.thumbnail_info.as_deref(),
|
||||
info.thumbnail_source.to_owned(),
|
||||
info.thumbnail_info.to_owned(),
|
||||
)
|
||||
})
|
||||
.map(|thumbnail| vec![thumbnail]),
|
||||
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
use super::{
|
||||
file::FileContent,
|
||||
file::{FileContent, FileContentInfo},
|
||||
image::{ImageContent, ThumbnailContent},
|
||||
message::MessageContent,
|
||||
};
|
||||
@ -96,13 +96,20 @@ impl StickerEventContent {
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
message: Some(MessageContent::plain(body.clone())),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
file: Some(FileContent::plain(url.clone(), Some(Box::new((&info).into())))),
|
||||
file: Some(FileContent::plain(
|
||||
url.clone(),
|
||||
FileContentInfo::from_room_message_content(None, info.mimetype.clone(), info.size)
|
||||
.map(Box::new),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
image: Some(Box::new((&info).into())),
|
||||
image: Some(Box::new(
|
||||
ImageContent::from_room_message_content(info.width, info.height)
|
||||
.unwrap_or_default(),
|
||||
)),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
thumbnail: ThumbnailContent::from_room_message_content(
|
||||
info.thumbnail_source.as_ref(),
|
||||
info.thumbnail_info.as_deref(),
|
||||
info.thumbnail_source.clone(),
|
||||
info.thumbnail_info.clone(),
|
||||
)
|
||||
.map(|thumbnail| vec![thumbnail]),
|
||||
#[cfg(feature = "unstable-msc3552")]
|
||||
|
@ -105,25 +105,29 @@ impl VideoEventContent {
|
||||
thumbnail,
|
||||
caption,
|
||||
} = content;
|
||||
let VideoInfo {
|
||||
duration,
|
||||
height,
|
||||
width,
|
||||
mimetype,
|
||||
size,
|
||||
thumbnail_info,
|
||||
thumbnail_source,
|
||||
..
|
||||
} = info.map(|info| *info).unwrap_or_default();
|
||||
|
||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
||||
let file = file.unwrap_or_else(|| {
|
||||
FileContent::from_room_message_content(source, info.as_deref(), None)
|
||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
||||
});
|
||||
let video = video.unwrap_or_else(|| {
|
||||
Box::new(VideoContent::from_room_message_content(height, width, duration))
|
||||
});
|
||||
let thumbnail = thumbnail.unwrap_or_else(|| {
|
||||
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
|
||||
.into_iter()
|
||||
.collect()
|
||||
});
|
||||
let video =
|
||||
video.or_else(|| info.as_deref().map(|info| Box::new(info.into()))).unwrap_or_default();
|
||||
let thumbnail = thumbnail
|
||||
.or_else(|| {
|
||||
info.as_deref()
|
||||
.and_then(|info| {
|
||||
ThumbnailContent::from_room_message_content(
|
||||
info.thumbnail_source.as_ref(),
|
||||
info.thumbnail_info.as_deref(),
|
||||
)
|
||||
})
|
||||
.map(|thumbnail| vec![thumbnail])
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Self { message, file, video, thumbnail, caption, relates_to }
|
||||
}
|
||||
@ -169,15 +173,17 @@ impl VideoContent {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Creates a new `VideoContent` with the given optional height, width and duration.
|
||||
pub(crate) fn from_room_message_content(
|
||||
height: Option<UInt>,
|
||||
width: Option<UInt>,
|
||||
duration: Option<Duration>,
|
||||
) -> Self {
|
||||
Self { height, width, duration }
|
||||
}
|
||||
|
||||
/// Whether this `VideoContent` is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.height.is_none() && self.width.is_none() && self.duration.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&VideoInfo> for VideoContent {
|
||||
fn from(info: &VideoInfo) -> Self {
|
||||
let VideoInfo { height, width, duration, .. } = info;
|
||||
Self { height: height.to_owned(), width: width.to_owned(), duration: duration.to_owned() }
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ use super::{
|
||||
audio::AudioContent,
|
||||
file::FileContent,
|
||||
message::{MessageContent, TryFromExtensibleError},
|
||||
room::message::{AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent},
|
||||
room::message::{
|
||||
AudioInfo, AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent,
|
||||
},
|
||||
};
|
||||
|
||||
/// The payload for an extensible voice message.
|
||||
@ -82,12 +84,15 @@ impl VoiceEventContent {
|
||||
relates_to: Option<Relation>,
|
||||
) -> Result<Self, TryFromExtensibleError> {
|
||||
let AudioMessageEventContent { body, source, info, message, file, audio, voice } = content;
|
||||
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
|
||||
|
||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
||||
let file = file.unwrap_or_else(|| {
|
||||
FileContent::from_room_message_content(source, info.as_deref(), None)
|
||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
||||
});
|
||||
let audio = audio.or_else(|| info.as_deref().map(Into::into)).unwrap_or_default();
|
||||
let audio = audio
|
||||
.or_else(|| duration.map(AudioContent::from_room_message_content))
|
||||
.unwrap_or_default();
|
||||
let voice = if let Some(voice) = voice {
|
||||
voice
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user