use core::str::FromStr;
use derive_more::{Display, IsVariant, TryUnwrap, Unwrap};
use smol_str::SmolStr;
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::strings::container_format")
)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant, Unwrap, TryUnwrap)]
#[display("{}", self.as_str())]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
#[non_exhaustive]
pub enum Format {
Mov,
#[is_variant(ignore)]
Mp4,
Mkv,
Webm,
Avi,
Flv,
MpegTs,
Ogg,
Asf,
Rm,
Wmv,
Mxf,
Gxf,
Threegp,
Other(SmolStr),
}
impl Default for Format {
#[inline]
fn default() -> Self {
Self::Other(SmolStr::new_inline(""))
}
}
impl Format {
#[inline(always)]
pub const fn is_mp4(&self) -> bool {
matches!(self, Self::Mp4)
}
pub fn as_str(&self) -> &str {
match self {
Self::Mov => "mov",
Self::Mp4 => "mp4",
Self::Mkv => "mkv",
Self::Webm => "webm",
Self::Avi => "avi",
Self::Flv => "flv",
Self::MpegTs => "mpegts",
Self::Ogg => "ogg",
Self::Asf => "asf",
Self::Rm => "rm",
Self::Wmv => "wmv",
Self::Mxf => "mxf",
Self::Gxf => "gxf",
Self::Threegp => "3gp",
Self::Other(s) => s.as_str(),
}
}
#[inline(always)]
pub const fn as_extension(&self) -> &'static str {
match self {
Self::Mov => "mov",
Self::Mp4 => "mp4",
Self::Mkv => "mkv",
Self::Webm => "webm",
Self::Avi => "avi",
Self::Flv => "flv",
Self::MpegTs => "ts",
Self::Ogg => "ogv",
Self::Asf => "asf",
Self::Rm => "rm",
Self::Wmv => "wmv",
Self::Mxf => "mxf",
Self::Gxf => "gxf",
Self::Threegp => "3gp",
Self::Other(_) => "",
}
}
}
impl FromStr for Format {
type Err = core::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"mov" => Self::Mov,
"mp4" => Self::Mp4,
"mkv" => Self::Mkv,
"webm" => Self::Webm,
"avi" => Self::Avi,
"flv" => Self::Flv,
"mpegts" => Self::MpegTs,
"ogg" => Self::Ogg,
"asf" => Self::Asf,
"rm" => Self::Rm,
"wmv" => Self::Wmv,
"mxf" => Self::Mxf,
"gxf" => Self::Gxf,
"3gp" => Self::Threegp,
other => Self::Other(SmolStr::new(other)),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use ::std::string::ToString;
#[test]
fn every_named_variant_round_trips() {
for slug in [
"mov", "mp4", "mkv", "webm", "avi", "flv", "mpegts", "ogg", "asf", "rm", "wmv", "mxf", "gxf",
"3gp",
] {
let v: Format = slug.parse().unwrap();
assert!(!v.is_other(), "`{slug}` should be a named variant");
assert_eq!(v.as_str(), slug);
}
}
#[test]
fn unknown_slug_lands_in_other() {
let v: Format = "weird_container".parse().unwrap();
assert!(v.is_other());
assert_eq!(v.as_str(), "weird_container");
assert_eq!(v.to_string(), "weird_container");
}
#[test]
fn display_matches_as_str() {
assert_eq!(Format::Mp4.to_string(), "mp4");
assert_eq!(Format::MpegTs.to_string(), "mpegts");
assert_eq!(Format::Threegp.to_string(), "3gp");
assert_eq!(Format::Other(SmolStr::new("custom")).to_string(), "custom");
}
#[test]
fn is_variant_predicates() {
assert!(Format::Mp4.is_mp4());
assert!(!Format::Mkv.is_mp4());
assert!(Format::Threegp.is_threegp());
assert!(Format::Other(SmolStr::new("x")).is_other());
}
#[test]
fn unwrap_other_borrowed_view() {
let v = Format::Other(SmolStr::new("custom"));
assert_eq!(v.unwrap_other_ref().as_str(), "custom");
assert!(v.try_unwrap_other_ref().is_ok());
let named = Format::Mp4;
assert!(named.try_unwrap_other_ref().is_err());
}
#[test]
fn as_extension_matches_disk_form() {
assert_eq!(Format::Mov.as_extension(), "mov");
assert_eq!(Format::Mp4.as_extension(), "mp4");
assert_eq!(Format::Mkv.as_extension(), "mkv");
assert_eq!(Format::Webm.as_extension(), "webm");
assert_eq!(Format::Avi.as_extension(), "avi");
assert_eq!(Format::Flv.as_extension(), "flv");
assert_eq!(Format::Threegp.as_extension(), "3gp");
assert_eq!(Format::MpegTs.as_str(), "mpegts");
assert_eq!(Format::MpegTs.as_extension(), "ts");
assert_eq!(Format::Ogg.as_str(), "ogg");
assert_eq!(Format::Ogg.as_extension(), "ogv");
assert_eq!(Format::Other(SmolStr::new("weird")).as_extension(), "");
}
}