imdb_async/
show.rs

1use std::cmp::Ordering;
2use std::convert::TryFrom;
3
4use arrayvec::ArrayVec;
5use compact_str::CompactString;
6
7use crate::genre::Genre;
8use crate::EpisodeLink;
9use crate::Error;
10use crate::Title;
11use crate::TitleType;
12
13#[derive(Eq, PartialEq)]
14/// Represents a TV series from IMDB.
15pub struct Show {
16	pub imdb_id: u32,
17	pub title: CompactString,
18	pub is_adult: bool,
19	pub start_year: u16,
20	pub end_year: Option<u16>,
21	pub runtime_minutes: Option<u16>,
22	pub genres: ArrayVec<Genre, 3>,
23	pub episodes: Vec<Episode>
24}
25
26impl std::fmt::Debug for Show /* {{{ */ {
27	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28		f.debug_struct("Show")
29			.field("imdb_id", &self.imdb_id)
30			.field("title", &self.title)
31			.field("is_adult", &self.is_adult)
32			.field("start_year", &self.start_year)
33			.field("end_year", &self.end_year)
34			.field("runtime_minutes", &self.runtime_minutes)
35			.field("genres", &self.genres)
36			.field("episodes", &self.episodes.len())
37			.finish()
38	}
39} // }}}
40
41impl Show {
42	pub(crate) fn from_wrapped_title(input: Result<Title, Error>) -> Result<Self, Error> /* {{{ */ {
43		Self::try_from(input?)
44	} // }}}
45}
46
47impl TryFrom<Title> for Show /* {{{ */ {
48	type Error = Error;
49	#[inline]
50	fn try_from(input: Title) -> Result<Self, Error> {
51		match input.title_type {
52			TitleType::TVSeries => Ok(Self{
53				imdb_id: input.imdb_id,
54				title: input.primary_title,
55				is_adult: input.is_adult,
56				start_year: match input.start_year {
57					Some(v) => v,
58					None => return Err(Error::YearMissing)
59				},
60				end_year: input.end_year,
61				runtime_minutes: input.runtime_minutes,
62				genres: input.genres,
63				episodes: Vec::new()
64			}),
65			_ => Err(Error::WrongMediaType(input.title_type.into(), "Show"))
66		}
67	}
68} // }}}
69
70#[derive(Clone, Debug, Eq, PartialEq)]
71/// Represents an episode of a TV series from IMDB.  Pared down from [Title] and EpisodeLink based on fields that make sense for an individual episode.
72pub struct Episode {
73	pub season: u16,
74	pub episode: u16,
75	pub imdb_id: u32,
76	pub title: CompactString,
77	pub year: Option<u16>,
78	pub runtime_minutes: Option<u16>
79}
80
81impl PartialOrd for Episode /* {{{ */ {
82	#[inline]
83	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
84		Some(self.cmp(other))
85	}
86} // }}}
87
88impl Ord for Episode /* {{{ */ {
89	#[inline]
90	fn cmp(&self, other: &Self) -> Ordering {
91		match self.season.cmp(&other.season) {
92			Ordering::Equal => self.episode.cmp(&other.episode),
93			v => v
94		}
95	}
96} // }}}
97
98impl Episode {
99	#[cfg(test)]
100	pub(crate) fn new(season: u16, episode: u16, imdb_id: u32, title: &str, year: Option<u16>, runtime_minutes: Option<u16>) -> Self /* {{{ */ {
101		Self{
102			season,
103			episode,
104			imdb_id,
105			title: CompactString::new(title),
106			year,
107			runtime_minutes
108		}
109	} // }}}
110
111	#[inline]
112	pub(crate) fn from_title_and_link(title: Title, link: EpisodeLink) -> Result<Self, Error> /* {{{ */ {
113		match title.title_type {
114			TitleType::Episode => Ok(Self{
115				season: match link.season {
116					Some(v) => v,
117					None => return Err(Error::SeasonMissing)
118				},
119				episode: match link.episode {
120					Some(v) => v,
121					None => return Err(Error::EpisodeMissing)
122				},
123				imdb_id: title.imdb_id,
124				title: title.primary_title,
125				year: title.start_year,
126				runtime_minutes: title.runtime_minutes
127			}),
128			_ => Err(Error::WrongMediaType(title.title_type.into(), "Episode"))
129		}
130	} // }}}
131}
132
133#[inline]
134pub(crate) fn title_matches_show_name_and_year(title: &Result<Title, Error>, name: &str, year: u16) -> bool /* {{{ */ {
135	if let Ok(title) = title {
136		if(title.title_type != TitleType::TVSeries) {
137			return false;
138		}
139		if let Some(title_year) = title.start_year {
140			if(title_year != year) {
141				return false;
142			}
143		} else {
144			return false;
145		}
146		if(title.primary_title != name && title.original_title != name) {
147			return false;
148		}
149		return true;
150	}
151	false
152} // }}}
153