1use arrayvec::ArrayVec;
2use compact_str::CompactString;
3use serde::de::Unexpected;
4use serde::Deserialize;
5use serde::Deserializer;
6use serde::Serialize;
7use serde_repr::Deserialize_repr;
8use serde_repr::Serialize_repr;
9
10use crate::genre::Genre;
11
12#[derive(Debug, Deserialize, Serialize)]
13pub struct Title {
15 pub imdb_id: u32,
17 pub title_type: TitleType,
18 pub primary_title: CompactString,
19 pub original_title: CompactString,
20 pub is_adult: bool,
21 pub start_year: Option<u16>,
22 pub end_year: Option<u16>,
23 pub runtime_minutes: Option<u16>,
24 pub genres: ArrayVec<Genre, 3>
25}
26
27impl From<TitleFromImdb> for Title {
28 #[inline]
29 fn from(input: TitleFromImdb) -> Self {
30 Self{
31 imdb_id: input.imdb_id,
32 title_type: input.title_type.into(),
33 primary_title: input.primary_title,
34 original_title: input.original_title,
35 is_adult: input.is_adult != 0,
36 start_year: input.start_year,
37 end_year: input.end_year,
38 runtime_minutes: input.runtime_minutes,
39 genres: input.genres
40 }
41 }
42} #[derive(Clone, Copy, Debug, Deserialize_repr, Eq, PartialEq, Serialize_repr, strum::IntoStaticStr)]
45#[repr(u8)]
46pub enum TitleType {
50 Short = 0,
51 Movie = 1,
52 Episode = 2,
53 TVSeries = 3,
54 TVShort = 4,
55 TVSpecial = 5,
56 Video = 6,
57 VideoGame = 7,
58 Audiobook = 8,
59 RadioSeries = 9,
60 RadioEpisode = 10
61}
62
63impl From<TitleTypeFromImdb> for TitleType {
64 #[inline]
65 fn from(input: TitleTypeFromImdb) -> Self {
66 match input {
67 TitleTypeFromImdb::Short => Self::Short,
68 TitleTypeFromImdb::Movie => Self::Movie,
69 TitleTypeFromImdb::Episode => Self::Episode,
70 TitleTypeFromImdb::TVSeries => Self::TVSeries,
71 TitleTypeFromImdb::TVShort => Self::TVShort,
72 TitleTypeFromImdb::TVSpecial => Self::TVSpecial,
73 TitleTypeFromImdb::Video => Self::Video,
74 TitleTypeFromImdb::VideoGame => Self::VideoGame,
75 TitleTypeFromImdb::Audiobook => Self::Audiobook,
76 TitleTypeFromImdb::RadioSeries => Self::RadioSeries,
77 TitleTypeFromImdb::RadioEpisode => Self::RadioEpisode
78 }
79 }
80} #[derive(Debug, Deserialize)]
83#[serde(rename_all = "camelCase")]
84pub(crate) struct TitleFromImdb {
85 #[serde(rename = "tconst", deserialize_with = "crate::util::parse_imdb_id")]
86 pub imdb_id: u32,
87 pub title_type: TitleTypeFromImdb,
88 pub primary_title: CompactString,
89 pub original_title: CompactString,
90 pub is_adult: u8,
91 #[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
92 pub start_year: Option<u16>,
93 #[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
94 pub end_year: Option<u16>,
95 #[serde(deserialize_with = "crate::util::parse_janky_tsv_option")]
96 pub runtime_minutes: Option<u16>,
97 #[serde(deserialize_with = "crate::genre::deserialize")]
98 pub genres: ArrayVec<Genre, 3>
99}
100
101#[derive(Debug, Eq, PartialEq)]
102pub(crate) enum TitleTypeFromImdb {
103 Short,
104 Movie,
105 Episode,
106 TVSeries,
107 TVShort,
108 TVSpecial,
109 Video,
110 VideoGame,
111 Audiobook,
112 RadioSeries,
113 RadioEpisode
114}
115
116impl<'de> Deserialize<'de> for TitleTypeFromImdb {
117 #[inline]
118 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
119 let s: &str = Deserialize::deserialize(deserializer)?;
120 Ok(match s {
121 "short" => Self::Short,
122 "episode" | "tvEpisode" | "tvPilot" => Self::Episode,
123 "movie" | "tvMovie" => Self::Movie,
124 "tvSeries" | "tvMiniSeries" => Self::TVSeries,
125 "tvShort" => Self::TVShort,
126 "tvSpecial" => Self::TVSpecial,
127 "video" => Self::Video,
128 "videoGame" => Self::VideoGame,
129 "audiobook" => Self::Audiobook,
130 "radioSeries" => Self::RadioSeries,
131 "radioEpisode" => Self::RadioEpisode,
132 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'"))
133 })
134 }
135}
136