#[cfg(any(feature = "mime", feature = "mediatype"))]
macro_rules! try_conv {
(
$from:ty;
$into:ty : $err:ty => (singular: $singular:literal, plural: $plural:literal, title: $title:literal, sec: $sec:literal);
$def:expr;
$($id:ident => $main:expr $(,$other:expr)*;)*
) => {
#[doc = concat!("
Provides conversion from [`", stringify!($from), "`] to preferred [", $singular, "][", stringify!($into), "].
Read more at: [", $singular, " support info][", stringify!($from), "#", $sec, "-support-info]."
)]
impl TryInto<$into> for $from {
type Error = $err;
#[doc = concat!("
Converts this type into the preferred [", $singular, "][", stringify!($into), "].
")]
fn try_into(self) -> Result<$into, Self::Error> {
match self {
$(<$from>::$id => parse_mime($main),)*
_ => parse_mime($def),
}
}
}
#[doc = concat!("
Provides conversion from [`", stringify!($from), "`] to known [", $plural, "][", stringify!($into), "] that they correspond to.
# ", $title, " support info
Be aware that different media types are supported by different browsers, and some of them,
for example, supports the `x-` prefixed one, and others don't.
This means that you should always test those ", $plural, " and select then based on the browser
support and the `User-Agent` header.
Another case is the [Matroska][", stringify!($from), "::Matroska] ", $plural, ", which some browsers support
as `video/x-matroska` and others as `video/webm`, but the latter is the preferred [", $singular, "][", stringify!($into), "].
Also, the [", $plural, "][", stringify!($into), "] that starts with `x-` (unregistered), `vnd.` or `prs.` are commonly not
**the preferred** [", $singular, "][", stringify!($into), "], so they are *commonly* present at the end of the list, unless
there is no other functional alternative (like any alternative that browsers recognize
and presents or manages the content correctly).
# Preferred ", $plural, "
The preferred [", $singular, "][", stringify!($into), "] is the most common or most browser compatible one,
and this [`TryInto`] implementation returns them in the preferred order, below is a list of preferred browser mimes:
", $(concat!("- [", stringify!($id), "][", stringify!($from), "::", stringify!($id), "]: `", $main, "`\n"),)* "")]
impl TryInto<Vec<$into>> for $from {
type Error = $err;
#[doc = concat!("
Converts this type into known [", $plural, "][", stringify!($into), "].
")]
fn try_into(self) -> Result<Vec<$into>, Self::Error> {
match self {
$(<$from>::$id => parse_mimes(&[$main, $($other,)*]),)*
_ => parse_mimes(&[$def]),
}
}
}
}
}
#[cfg(any(feature = "mime", feature = "mediatype"))]
macro_rules! impl_for {
(
$from:ty;
$feat:expr, $name:ident: $into:ty, $err:ty => (singular: $singular:literal, plural: $plural:literal, title: $title:literal, sec: $sec: literal);
$def:expr; $($id:ident => $main:expr $(,$other:expr)*;)*
) => {
#[cfg(feature = $feat)]
mod $name {
try_conv!{$from; $into : $err => (singular: $singular, plural: $plural, title: $title, sec: $sec); $def; $($id => $main $(,$other)*;)*}
fn parse_mime(mime_type: &str) -> Result<$into, $err> {
mime_type.parse()
}
fn parse_mimes(mimes: &[&str]) -> Result<Vec<$into>, $err> {
let mut parsed_mimes = vec![];
let mut has_ok = false;
for mime in mimes {
let p = mime.parse::<$into>();
has_ok |= p.is_ok();
parsed_mimes.push(p);
}
if has_ok {
Ok(parsed_mimes.into_iter().filter_map(|p| p.ok()).collect())
} else {
parsed_mimes.into_iter().collect::<Result<Vec<$into>, _>>()
}
}
}
};
}
#[cfg(any(feature = "mime", feature = "mediatype"))]
macro_rules! conv_mod {
(
$from: ty;
those {
$($feat:expr, $name:ident: $typ:ty, $err:ty => (singular: $singular:literal, plural: $plural:literal, title: $title:literal, sec: $sec:literal);)+
}
$def:expr; $($id:ident => $main:expr $(,$other:expr)*;)*
) => {
conv_mod! {
@inner
$from;
those {
$($feat, $name: $typ, $err => (singular: $singular, plural: $plural, title: $title, sec: $sec);)*
}
$def; $($id => $main $(,$other)*;)*
}
};
(
@inner
$from: ty;
those {}
$def:expr; $($id:ident => $main:expr $(,$other:expr)*;)*
) => {};
(
@inner
$from: ty;
those {
$head_feat:expr, $head_name:ident: $head_typ:ty, $head_err:ty => (singular: $head_singular:literal, plural: $head_plural:literal, title: $head_title:literal, sec: $head_sec:literal);
$($tail_feat:expr, $tail_name:ident: $tail_typ:ty, $tail_err:ty => (singular: $tail_singular:literal, plural: $tail_plural:literal, title: $tail_title:literal, sec: $tail_sec:literal);)*
}
$def:expr; $($id:ident => $main:expr $(,$other:expr)*;)*
) => {
impl_for! { $from; $head_feat, $head_name: $head_typ, $head_err => (singular: $head_singular, plural: $head_plural, title: $head_title, sec: $head_sec); $def; $($id => $main $(,$other)*;)* }
conv_mod! {
@inner
$from;
those {
$($tail_feat, $tail_name: $tail_typ, $tail_err => (singular: $tail_singular, plural: $tail_plural, title: $tail_title, sec: $tail_sec);)*
}
$def; $($id => $main $(,$other)*;)*
}
};
}
conv_mod! {
crate::FileType;
those {
"mime", mime: mime::Mime, mime::FromStrError => (singular: "mime", plural: "mimes", title: "Mime", sec: "mime");
"mediatype", mediatype: mediatype::MediaTypeBuf, mediatype::MediaTypeError => (singular: "media type", plural: "media types", title: "Media Type", sec: "media-type");
}
"application/octet-stream";
Png => "image/png";
Jpg => "image/jpeg";
Gif => "image/gif";
Bmp => "image/bmp";
Webp => "image/webp";
Opus => "audio/opus", "audio/ogg";
Vorbis => "audio/vorbis", "audio/ogg";
Mp3 => "audio/mpeg", "audio/mpeg3", "audio/mp3", "audio/x-mpeg3";
Flac => "audio/flac", "audio/x-flac";
Matroska => "video/webm", "video/x-matroska";
Wasm => "application/wasm";
Class => "application/java-vm", "application/x-java-vm";
Wav => "audio/wav", "audio/x-wav";
Avi => "video/avi", "video/msvideo", "video/x-msvideo";
Aiff => "audio/aiff", "audio/x-aiff";
Tiff => "image/tiff";
Sqlite3 => "application/vnd.sqlite3", "application/x-sqlite3";
Ico => "image/x-icon";
Pdf => "application/pdf", "application/x-pdf";
}
conv_mod! {
crate::FileRootType;
those {
"mime", root_mime: mime::Mime, mime::FromStrError => (singular: "mime", plural: "mimes", title: "Mime", sec: "mime");
"mediatype", root_mediatype: mediatype::MediaTypeBuf, mediatype::MediaTypeError => (singular: "media type", plural: "media types", title: "Media Type", sec: "media-type");
}
"application/octet-stream";
Png => "image/png";
Jpg => "image/jpeg";
Gif => "image/gif";
Bmp => "image/bmp";
Webp => "image/webp";
Ogg => "audio/opus", "audio/ogg";
Mp3 => "audio/mpeg", "audio/mpeg3", "audio/mp3", "audio/x-mpeg3";
Flac => "audio/flac", "audio/x-flac";
Matroska => "video/webm", "video/x-matroska";
Wasm => "application/wasm";
Class => "application/java-vm", "application/x-java-vm";
Wav => "audio/wav", "audio/x-wav";
Avi => "video/avi", "video/msvideo", "video/x-msvideo";
Aiff => "audio/aiff", "audio/x-aiff";
Tiff => "image/tiff";
Sqlite3 => "application/vnd.sqlite3", "application/x-sqlite3";
Ico => "image/x-icon";
Pdf => "application/pdf", "application/x-pdf";
}