rust_anilist/models/
format.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2022-2025 Andriel Ferreira <https://github.com/AndrielFR>
3
4//! This module contains the `Format` struct.
5
6use serde::{Deserialize, Serialize};
7
8/// Represents the format of a media item.
9///
10/// The `Format` enum defines various formats that a media item can have,
11/// such as TV shows, movies, specials, OVAs, ONAs, music, manga, novels,
12/// and one-shots.
13///
14/// # Variants
15///
16/// * `Tv` - Represents a TV show.
17/// * `TvShort` - Represents a short TV show.
18/// * `Movie` - Represents a movie.
19/// * `Special` - Represents a special.
20/// * `Ova` - Represents an original video animation.
21/// * `Ona` - Represents an original net animation.
22/// * `Music` - Represents a music video.
23/// * `Manga` - Represents a manga.
24/// * `Novel` - Represents a novel.
25/// * `OneShot` - Represents a one-shot.
26#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Deserialize, Serialize)]
27#[serde(rename_all(deserialize = "SCREAMING_SNAKE_CASE"))]
28pub enum Format {
29    /// Represents a TV show.
30    #[default]
31    Tv,
32    /// Represents a short TV show.
33    TvShort,
34    /// Represents a movie.
35    Movie,
36    /// Represents a special.
37    Special,
38    /// Represents an original video animation.
39    Ova,
40    /// Represents an original net animation.
41    Ona,
42    /// Represents a music video.
43    Music,
44    /// Represents a manga.
45    Manga,
46    /// Represents a novel.
47    Novel,
48    /// Represents a one-shot.
49    OneShot,
50}
51
52impl Format {
53    /// Returns the name of the format.
54    pub fn name(&self) -> &str {
55        match self {
56            Format::Tv => "TV",
57            Format::TvShort => "TV Short",
58            Format::Movie => "Movie",
59            Format::Special => "Special",
60            Format::Ova => "OVA",
61            Format::Ona => "ONA",
62            Format::Music => "Music",
63            Format::Manga => "Manga",
64            Format::Novel => "Novel",
65            Format::OneShot => "One-Shot",
66        }
67    }
68
69    /// Returns a summary of the format.
70    pub fn summary(&self) -> &str {
71        match self {
72            Format::Tv => "Anime broadcast on television",
73            Format::TvShort => "Anime which are under 15 minutes in length and broadcast on television",
74            Format::Movie => "Anime movies with a theatrical release",
75            Format::Special => "Special episodes that have been included in DVD/Blu-ray releases, picture dramas, pilots, etc",
76            Format::Ova => "(Original Video Animation) Anime that have been released directly on DVD/Blu-ray without originally going through a theatrical release or television broadcast",
77            Format::Ona => "(Original Net Animation) Anime that have been originally released online or are only available through streaming services.",
78            Format::Music => "Short anime released as a music video",
79            Format::Manga => "Professionally published manga with more than one chapter",
80            Format::Novel => "Written books released as a series of light novels",
81            Format::OneShot => "Manga with just one chapter",
82        }
83    }
84}
85
86impl From<&str> for Format {
87    fn from(value: &str) -> Self {
88        match value.trim().to_uppercase().as_str() {
89            "TV" => Format::Tv,
90            "TV_SHORT" => Format::TvShort,
91            "MOVIE" => Format::Movie,
92            "SPECIAL" => Format::Special,
93            "OVA" => Format::Ova,
94            "ONA" => Format::Ona,
95            "MUSIC" => Format::Music,
96            "MANGA" => Format::Manga,
97            "NOVEL" => Format::Novel,
98            "ONE_SHOT" => Format::OneShot,
99            _ => Format::default(),
100        }
101    }
102}
103
104impl From<String> for Format {
105    fn from(value: String) -> Self {
106        Format::from(value.as_str())
107    }
108}
109
110impl std::fmt::Display for Format {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(f, "{}", self.name())
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn test_format_name() {
122        assert_eq!(Format::Tv.name(), "TV");
123        assert_eq!(Format::TvShort.name(), "TV Short");
124        assert_eq!(Format::Movie.name(), "Movie");
125        assert_eq!(Format::Special.name(), "Special");
126        assert_eq!(Format::Ova.name(), "OVA");
127        assert_eq!(Format::Ona.name(), "ONA");
128        assert_eq!(Format::Music.name(), "Music");
129        assert_eq!(Format::Manga.name(), "Manga");
130        assert_eq!(Format::Novel.name(), "Novel");
131        assert_eq!(Format::OneShot.name(), "One-Shot");
132    }
133
134    #[test]
135    fn test_from_str() {
136        assert_eq!(Format::from("tv"), Format::Tv);
137        assert_eq!(Format::from("TV_SHORT"), Format::TvShort);
138        assert_eq!(Format::from("movie"), Format::Movie);
139        assert_eq!(Format::from("SPECIAL"), Format::Special);
140        assert_eq!(Format::from("ova"), Format::Ova);
141        assert_eq!(Format::from("ONA"), Format::Ona);
142        assert_eq!(Format::from("music"), Format::Music);
143        assert_eq!(Format::from("MANGA"), Format::Manga);
144        assert_eq!(Format::from("novel"), Format::Novel);
145        assert_eq!(Format::from("ONE_SHOT"), Format::OneShot);
146        assert_eq!(Format::from("unknown"), Format::Tv); // Default case
147    }
148
149    #[test]
150    fn test_from_string() {
151        assert_eq!(Format::from("tv".to_string()), Format::Tv);
152        assert_eq!(Format::from("TV_SHORT".to_string()), Format::TvShort);
153        assert_eq!(Format::from("movie".to_string()), Format::Movie);
154        assert_eq!(Format::from("SPECIAL".to_string()), Format::Special);
155        assert_eq!(Format::from("ova".to_string()), Format::Ova);
156        assert_eq!(Format::from("ONA".to_string()), Format::Ona);
157        assert_eq!(Format::from("music".to_string()), Format::Music);
158        assert_eq!(Format::from("MANGA".to_string()), Format::Manga);
159        assert_eq!(Format::from("novel".to_string()), Format::Novel);
160        assert_eq!(Format::from("ONE_SHOT".to_string()), Format::OneShot);
161        assert_eq!(Format::from("unknown".to_string()), Format::Tv); // Default case
162    }
163}