events: Add custom Deserialize impls for MediaSource
This commit is contained in:
parent
8afc3a1100
commit
deea762b8e
@ -5,7 +5,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use js_int::UInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de, Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
serde::{base64::UrlSafe, Base64},
|
||||
@ -34,7 +34,7 @@ pub mod tombstone;
|
||||
pub mod topic;
|
||||
|
||||
/// The source of a media file.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[allow(clippy::exhaustive_enums)]
|
||||
pub enum MediaSource {
|
||||
/// The MXC URI to the unencrypted media file.
|
||||
@ -46,6 +46,30 @@ pub enum MediaSource {
|
||||
Encrypted(Box<EncryptedFile>),
|
||||
}
|
||||
|
||||
/// Custom implementation of `Deserialize`, because serde doesn't guarantee what variant will be
|
||||
/// deserialized for "externally tagged"¹ enums where multiple "tag" fields exist.
|
||||
///
|
||||
/// ¹ https://serde.rs/enum-representations.html
|
||||
impl<'de> Deserialize<'de> for MediaSource {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
pub struct MediaSourceJsonRepr {
|
||||
url: Option<Box<MxcUri>>,
|
||||
file: Option<Box<EncryptedFile>>,
|
||||
}
|
||||
|
||||
match MediaSourceJsonRepr::deserialize(deserializer)? {
|
||||
MediaSourceJsonRepr { url: None, file: None } => Err(de::Error::missing_field("url")),
|
||||
// Prefer file if it is set
|
||||
MediaSourceJsonRepr { file: Some(file), .. } => Ok(MediaSource::Encrypted(file)),
|
||||
MediaSourceJsonRepr { url: Some(url), .. } => Ok(MediaSource::Plain(url)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata about an image.
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
|
@ -1,9 +1,8 @@
|
||||
//! De-/serialization functions for `Option<MediaSource>` objects representing a thumbnail source.
|
||||
|
||||
use serde::{
|
||||
de::Deserializer,
|
||||
ser::{SerializeStruct, Serializer},
|
||||
Deserialize,
|
||||
Deserialize, Deserializer,
|
||||
};
|
||||
|
||||
use crate::MxcUri;
|
||||
@ -32,25 +31,20 @@ pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<MediaSource>, D::Er
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Option::<ThumbnailSource>::deserialize(deserializer).map(|source| source.map(Into::into))
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
pub struct ThumbnailSourceJsonRepr {
|
||||
thumbnail_url: Option<Box<MxcUri>>,
|
||||
thumbnail_file: Option<Box<EncryptedFile>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
enum ThumbnailSource {
|
||||
/// The MXC URI to the unencrypted media file.
|
||||
#[serde(rename = "thumbnail_url")]
|
||||
Plain(Box<MxcUri>),
|
||||
|
||||
/// The encryption info of the encrypted media file.
|
||||
#[serde(rename = "thumbnail_file")]
|
||||
Encrypted(Box<EncryptedFile>),
|
||||
}
|
||||
|
||||
impl From<ThumbnailSource> for MediaSource {
|
||||
fn from(source: ThumbnailSource) -> Self {
|
||||
match source {
|
||||
ThumbnailSource::Plain(url) => Self::Plain(url),
|
||||
ThumbnailSource::Encrypted(file) => Self::Encrypted(file),
|
||||
match ThumbnailSourceJsonRepr::deserialize(deserializer)? {
|
||||
ThumbnailSourceJsonRepr { thumbnail_url: None, thumbnail_file: None } => Ok(None),
|
||||
// Prefer file if it is set
|
||||
ThumbnailSourceJsonRepr { thumbnail_file: Some(file), .. } => {
|
||||
Ok(Some(MediaSource::Encrypted(file)))
|
||||
}
|
||||
ThumbnailSourceJsonRepr { thumbnail_url: Some(url), .. } => {
|
||||
Ok(Some(MediaSource::Plain(url)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user