use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MediaKind {
Png,
Jpeg,
Gif,
Webp,
Mp4,
Webm,
Unknown,
}
impl MediaKind {
#[must_use]
pub const fn media_type(self) -> Option<&'static str> {
match self {
Self::Png => Some("image/png"),
Self::Jpeg => Some("image/jpeg"),
Self::Gif => Some("image/gif"),
Self::Webp => Some("image/webp"),
Self::Mp4 => Some("video/mp4"),
Self::Webm => Some("video/webm"),
Self::Unknown => None,
}
}
#[must_use]
pub const fn can_be_animated(self) -> bool {
matches!(self, Self::Gif | Self::Webp)
}
#[must_use]
pub const fn is_image(self) -> bool {
matches!(self, Self::Png | Self::Jpeg | Self::Gif | Self::Webp)
}
#[must_use]
pub const fn is_video(self) -> bool {
matches!(self, Self::Mp4 | Self::Webm)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ImageDimensions {
pub width: u32,
pub height: u32,
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct MediaPolicy {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_inline_base64_bytes: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_image_dimension: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_images: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_videos: Option<usize>,
pub allow_gif: bool,
pub allow_webp: bool,
pub allow_images: bool,
pub allow_videos: bool,
pub allow_documents: bool,
}
impl Default for MediaPolicy {
fn default() -> Self {
Self {
max_inline_base64_bytes: None,
max_image_dimension: None,
max_images: None,
max_videos: None,
allow_gif: true,
allow_webp: true,
allow_images: true,
allow_videos: true,
allow_documents: true,
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ParsedDataUrl {
pub media_type: String,
pub data: Vec<u8>,
}
#[must_use]
pub fn detect_media_kind(bytes: &[u8]) -> MediaKind {
if bytes.starts_with(b"\x89PNG\r\n\x1a\n") {
return MediaKind::Png;
}
if bytes.starts_with(b"\xff\xd8\xff") {
return MediaKind::Jpeg;
}
if bytes.starts_with(b"GIF87a") || bytes.starts_with(b"GIF89a") {
return MediaKind::Gif;
}
if bytes.len() >= 12 && bytes.starts_with(b"RIFF") && &bytes[8..12] == b"WEBP" {
return MediaKind::Webp;
}
if bytes.len() >= 12 && &bytes[4..8] == b"ftyp" {
return MediaKind::Mp4;
}
if bytes.starts_with(b"\x1a\x45\xdf\xa3") {
return MediaKind::Webm;
}
MediaKind::Unknown
}