use std::str::FromStr;
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Text {
#[display("application/pgp-signature")]
PgpSignature,
#[display("application/yml; charset=utf-8")]
Yml,
#[display("text/html; charset=utf-8")]
Html,
#[display("application/json; charset=utf-8")]
Json,
#[display("application/javascript; charset=utf-8")]
Js,
#[display("text/plain; charset=utf-8")]
Txt,
#[display("text/markdown; charset=utf-8")]
Markdown,
#[display("text/css; charset=utf-8")]
Css,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Video {
#[display("video/mp4")]
Mp4,
#[display("video/webm")]
Webm,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Audio {
#[display("audio/flac")]
Flac,
#[display("audio/mpeg")]
Mpeg,
#[display("audio/wav")]
Wav,
#[display(" audio/mp4")]
Mp4,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Image {
#[display("image/apng")]
Apng,
#[display("image/avif")]
Avif,
#[display("image/gif")]
Gif,
#[display("image/jpeg")]
Jpeg,
#[display("image/jpg")]
Jpg,
#[display("image/png")]
Png,
#[display("image/webp")]
Webp,
#[display("image/svg+xml")]
Svg,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Doc {
#[display("application/pdf")]
Pdf,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, Debug, Clone, Copy, serde::Serialize, serde::Deserialize, strum::AsRefStr)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Other {
#[display("application/x-msdownload")]
Exe,
#[display("model/gltf-binary")]
Glb,
#[display("model/stl")]
Stl,
#[display("application/octet-stream")]
Bytes,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Extension {
Text(Text) = 1,
Video(Video) = 2,
Audio(Audio) = 3,
Image(Image) = 4,
Doc(Doc) = 5,
Other(Other) = 6,
}
impl Extension {
pub fn file_type(&self) -> String {
let extension = match self {
Extension::Text(v) => v.as_ref().to_string(),
Extension::Video(v) => v.as_ref().to_string(),
Extension::Audio(v) => v.as_ref().to_string(),
Extension::Image(v) => v.as_ref().to_string(),
Extension::Doc(v) => v.as_ref().to_string(),
Extension::Other(v) => v.as_ref().to_string(),
};
extension.to_uppercase()
}
}
impl std::fmt::Display for Extension {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let res = match self {
Extension::Text(v) => v.to_string(),
Extension::Video(v) => v.to_string(),
Extension::Audio(v) => v.to_string(),
Extension::Image(v) => v.to_string(),
Extension::Doc(v) => v.to_string(),
Extension::Other(v) => v.to_string(),
};
write!(f, "{res}")
}
}
impl FromStr for Extension {
type Err = anyhow::Error;
fn from_str(content_type: &str) -> Result<Self, Self::Err> {
let mime = content_type.trim().replace(' ', "").to_lowercase();
let extension = match mime.as_str() {
title if title.starts_with("application/json") => Extension::Text(Text::Json),
"application/pgp-signature" => Extension::Text(Text::PgpSignature),
"application/yaml" | "application/yml" => Extension::Text(Text::Yml),
title if title.starts_with("application/javascript") => Extension::Text(Text::Js),
title if title.starts_with("text/html") => Extension::Text(Text::Html),
title if title.starts_with("text/markdown") => Extension::Text(Text::Markdown),
title if title.starts_with("text/css") => Extension::Text(Text::Css),
"application/pdf" => Extension::Doc(Doc::Pdf),
"application/x-msdownload" => Extension::Other(Other::Exe),
"audio/flac" => Extension::Audio(Audio::Flac),
"audio/mpeg" => Extension::Audio(Audio::Mpeg),
"audio/wav" => Extension::Audio(Audio::Wav),
"audio/mp4" => Extension::Audio(Audio::Mp4),
"image/apng" => Extension::Image(Image::Apng),
"image/avif" => Extension::Image(Image::Avif),
"image/gif" => Extension::Image(Image::Gif),
"image/jpeg" => Extension::Image(Image::Jpeg),
"image/jpg" => Extension::Image(Image::Jpg),
"image/png" => Extension::Image(Image::Png),
"image/webp" => Extension::Image(Image::Webp),
"image/svg+xml" => Extension::Image(Image::Svg),
"video/mp4" => Extension::Video(Video::Mp4),
"video/webm" => Extension::Video(Video::Webm),
title if title.starts_with("text") => Extension::Text(Text::Txt),
gltf if gltf.starts_with("model/gltf") => Extension::Other(Other::Glb),
stf if stf.starts_with("model/stl") => Extension::Other(Other::Stl),
_ => Extension::Other(Other::Bytes),
};
Ok(extension)
}
}