anidb_api/http/models/anime/
episode.rs1use crate::http::models::common::{ApiError, Title};
2use serde::{Deserialize, Serialize};
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
6#[serde(from = "FromEpisode")]
7pub struct Episode {
9 pub episode_id: String,
10 pub episode_num: Option<String>,
11 pub episode_type: Option<EpisodeType>,
12 pub length: Option<String>,
13 pub updated: Option<String>,
14 pub titles: Vec<Title>,
15 pub description: Option<String>,
16 pub air_date: Option<String>, }
18
19#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
20pub enum EpisodeType {
21 #[serde(rename(deserialize = "1"))]
22 Episode = 1,
23 #[serde(rename(deserialize = "2"))]
24 Credits = 2,
25 #[serde(rename(deserialize = "3"))]
26 Special = 3,
27 #[serde(rename(deserialize = "4"))]
28 Trailer = 4,
29 #[serde(rename(deserialize = "5"))]
30 Parody = 5,
31 #[serde(rename(deserialize = "6"))]
32 Other = 6,
33}
34
35#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
36pub(crate) struct EpisodeList {
37 #[serde(rename = "episode")]
38 pub list: Vec<Episode>,
39}
40
41#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
42pub(crate) struct FromEpisode {
43 #[serde(rename = "id")]
44 pub episode_id: String,
45 pub epno: Option<EpisodeNumber>,
46 pub length: Option<String>,
47 #[serde(rename = "update")]
48 pub updated: Option<String>,
49 #[serde(rename = "title")]
50 pub titles: Option<Vec<Title>>,
51 pub description: Option<String>,
52 #[serde(rename = "airdate")]
53 pub air_date: Option<String>, }
55
56#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
57pub(crate) struct EpisodeNumber {
58 #[serde(rename(deserialize = "$value"))]
59 pub episode_num: Option<String>,
60 #[serde(rename = "type")]
61 pub episode_type: Option<String>,
62}
63
64impl From<FromEpisode> for Episode {
65 fn from(value: FromEpisode) -> Self {
66 let (episode_num, episode_type) = value
67 .epno
68 .map_or_else(|| (None, None), |x| (x.episode_num, x.episode_type));
69 Self {
70 episode_id: value.episode_id,
71 episode_num,
72 episode_type: episode_type.map(|x| EpisodeType::from_str(&x).unwrap()),
73 length: value.length,
74 updated: value.updated,
75 titles: value.titles.unwrap_or_default(),
76 description: value.description,
77 air_date: value.air_date,
78 }
79 }
80}
81
82impl From<Episode> for FromEpisode {
83 fn from(value: Episode) -> Self {
84 let epno = if value.episode_num.is_none() && value.episode_type.is_none() {
85 None
86 } else {
87 Some(EpisodeNumber {
88 episode_num: value.episode_num,
89 episode_type: value.episode_type.map(|x| x.to_string()),
90 })
91 };
92
93 Self {
94 episode_id: value.episode_id,
95 epno,
96 length: value.length,
97 updated: value.updated,
98 titles: if value.titles.is_empty() {
99 None
100 } else {
101 Some(value.titles)
102 },
103 description: value.description,
104 air_date: value.air_date,
105 }
106 }
107}
108
109impl FromStr for EpisodeType {
110 type Err = ApiError;
111
112 fn from_str(s: &str) -> Result<Self, Self::Err> {
113 match s {
114 "1" => Ok(EpisodeType::Episode),
115 "2" => Ok(EpisodeType::Credits),
116 "3" => Ok(EpisodeType::Special),
117 "4" => Ok(EpisodeType::Trailer),
118 "5" => Ok(EpisodeType::Parody),
119 "6" => Ok(EpisodeType::Other),
120 _ => Err(ApiError::Parse(
121 "Error parse &str to EpisodeType".to_string(),
122 )),
123 }
124 }
125}
126
127impl std::fmt::Display for EpisodeType {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 std::fmt::Debug::fmt(self, f)
130 }
131}