use arrayvec::ArrayVec;
use compact_str::CompactString;
use serde::de::Unexpected;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use serde_repr::Deserialize_repr;
use serde_repr::Serialize_repr;
use crate::genre::Genre;
#[derive(Debug, Deserialize, Serialize)]
pub struct Title {
pub imdb_id: u32,
pub title_type: TitleType,
pub primary_title: CompactString,
pub original_title: CompactString,
pub is_adult: bool,
pub start_year: Option<u16>,
pub end_year: Option<u16>,
pub runtime_minutes: Option<u16>,
pub genres: ArrayVec<Genre, 3>
}
impl From<TitleFromImdb> for Title {
#[inline]
fn from(input: TitleFromImdb) -> Self {
Self{
imdb_id: input.imdb_id,
title_type: input.title_type.into(),
primary_title: input.primary_title,
original_title: input.original_title,
is_adult: input.is_adult != 0,
start_year: input.start_year,
end_year: input.end_year,
runtime_minutes: input.runtime_minutes,
genres: input.genres
}
}
}
#[derive(Clone, Copy, Debug, Deserialize_repr, Eq, PartialEq, Serialize_repr, strum::IntoStaticStr)]
#[repr(u8)]
pub enum TitleType {
Short = 0,
Movie = 1,
Episode = 2,
TVSeries = 3,
TVShort = 4,
TVSpecial = 5,
Video = 6,
VideoGame = 7,
Audiobook = 8,
RadioSeries = 9,
RadioEpisode = 10
}
impl From<TitleTypeFromImdb> for TitleType {
#[inline]
fn from(input: TitleTypeFromImdb) -> Self {
match input {
TitleTypeFromImdb::Short => Self::Short,
TitleTypeFromImdb::Movie => Self::Movie,
TitleTypeFromImdb::Episode => Self::Episode,
TitleTypeFromImdb::TVSeries => Self::TVSeries,
TitleTypeFromImdb::TVShort => Self::TVShort,
TitleTypeFromImdb::TVSpecial => Self::TVSpecial,
TitleTypeFromImdb::Video => Self::Video,
TitleTypeFromImdb::VideoGame => Self::VideoGame,
TitleTypeFromImdb::Audiobook => Self::Audiobook,
TitleTypeFromImdb::RadioSeries => Self::RadioSeries,
TitleTypeFromImdb::RadioEpisode => Self::RadioEpisode
}
}
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct TitleFromImdb {
#[serde(rename = "tconst", deserialize_with = "crate::util::parse_imdb_id")]
pub imdb_id: u32,
pub title_type: TitleTypeFromImdb,
pub primary_title: CompactString,
pub original_title: CompactString,
pub is_adult: u8,
#[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
pub start_year: Option<u16>,
#[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
pub end_year: Option<u16>,
#[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
pub runtime_minutes: Option<u16>,
#[serde(deserialize_with = "crate::genre::deserialize")]
pub genres: ArrayVec<Genre, 3>
}
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum TitleTypeFromImdb {
Short,
Movie,
Episode,
TVSeries,
TVShort,
TVSpecial,
Video,
VideoGame,
Audiobook,
RadioSeries,
RadioEpisode
}
impl<'de> Deserialize<'de> for TitleTypeFromImdb {
#[inline]
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s: &str = Deserialize::deserialize(deserializer)?;
Ok(match s {
"short" => Self::Short,
"episode" | "tvEpisode" | "tvPilot" => Self::Episode,
"movie" | "tvMovie" => Self::Movie,
"tvSeries" | "tvMiniSeries" => Self::TVSeries,
"tvShort" => Self::TVShort,
"tvSpecial" => Self::TVSpecial,
"video" => Self::Video,
"videoGame" => Self::VideoGame,
"audiobook" => Self::Audiobook,
"radioSeries" => Self::RadioSeries,
"radioEpisode" => Self::RadioEpisode,
s => return Err(serde::de::Error::invalid_value(Unexpected::Str(s), &"'short', 'episode', 'tvEpisode', 'tvPilot', 'movie', 'tvMovie', 'tvSeries', 'tvMiniSeries', 'tvShort', 'tvSpecial', 'video', 'videoGame', 'audiobook', 'radioSeries', 'radioEpisode'"))
})
}
}