use std::fmt;
use std::hash::{Hash, Hasher};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AutomaticCaption {
#[serde(rename = "ext")]
pub extension: Extension,
pub url: String,
pub name: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Extension {
Json,
Json3,
Srv1,
Srv2,
Srv3,
Ttml,
#[default]
Vtt,
Srt,
Ass,
Ssa,
#[serde(other)]
Unknown,
}
impl Extension {
pub fn as_str(&self) -> &'static str {
match self {
Extension::Json => "json",
Extension::Json3 => "json3",
Extension::Srv1 => "srv1",
Extension::Srv2 => "srv2",
Extension::Srv3 => "srv3",
Extension::Ttml => "ttml",
Extension::Vtt => "vtt",
Extension::Srt => "srt",
Extension::Ass => "ass",
Extension::Ssa => "ssa",
Extension::Unknown => "unknown",
}
}
}
impl fmt::Display for AutomaticCaption {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AutomaticCaption(lang={}, ext={:?})",
self.name.as_deref().unwrap_or("unknown"),
self.extension
)
}
}
impl Hash for AutomaticCaption {
fn hash<H: Hasher>(&self, state: &mut H) {
self.url.hash(state);
self.name.hash(state);
std::mem::discriminant(&self.extension).hash(state);
}
}
impl fmt::Display for Extension {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl Eq for Extension {}
impl Hash for Extension {
fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Subtitle {
pub language_code: Option<String>,
pub language_name: Option<String>,
pub url: String,
#[serde(rename = "ext")]
pub extension: Extension,
#[serde(default)]
pub is_automatic: bool,
}
impl Subtitle {
pub fn from_automatic_caption(caption: &AutomaticCaption, language_code: String) -> Self {
Self {
language_code: Some(language_code),
language_name: caption.name.clone(),
url: caption.url.clone(),
extension: caption.extension.clone(),
is_automatic: true,
}
}
pub fn is_format(&self, format: &Extension) -> bool {
&self.extension == format
}
pub fn file_extension(&self) -> &str {
self.extension.as_str()
}
}
impl fmt::Display for Subtitle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Subtitle(lang={}, format={}, auto={})",
self.language_name
.as_deref()
.or(self.language_code.as_deref())
.unwrap_or("unknown"),
self.file_extension(),
self.is_automatic
)
}
}
impl Hash for Subtitle {
fn hash<H: Hasher>(&self, state: &mut H) {
self.language_code.hash(state);
self.url.hash(state);
std::mem::discriminant(&self.extension).hash(state);
}
}