imdb_async/
title.rs

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)]
13/// Represents a single title in IMDB; a "title" can be a show, an episode of a show, a movie, etc.  See [TitleType] for a list.
14pub struct Title {
15	/// ID from IMDB, with the leading "tt" removed
16	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} // }}}
43
44#[derive(Clone, Copy, Debug, Deserialize_repr, Eq, PartialEq, Serialize_repr, strum::IntoStaticStr)]
45#[repr(u8)]
46/// Identifies the type of a [Title].  IMDB has more possible values that, because this crate is opinionated, we collapse down.
47///
48/// For example, "episode", "tvEpisode", and "tvPilot" all become TitleType::Episode.
49pub 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} // }}}
81
82#[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