rust_anilist/models/
title.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2022-2025 Andriel Ferreira <https://github.com/AndrielFR>
3
4//! This module contains the `Title` struct.
5
6use serde::{Deserialize, Serialize};
7
8/// Represents a title with various language options.
9#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
10#[serde(rename_all(deserialize = "lowercase"))]
11pub struct Title {
12    /// The title in Romaji (Latin script).
13    romaji: Option<String>,
14    /// The title in English.
15    english: Option<String>,
16    /// The title in the native language.
17    native: String,
18    /// The title preferred by the user.
19    user_preferred: Option<String>,
20}
21
22impl Title {
23    /// Returns the title in Romaji (Latin script).
24    pub fn romaji(&self) -> &str {
25        self.romaji.as_deref().unwrap_or(&self.native)
26    }
27
28    /// Returns the title in English.
29    pub fn english(&self) -> &str {
30        self.english.as_deref().unwrap_or(&self.native)
31    }
32
33    /// Returns the title in the native language.
34    pub fn native(&self) -> &str {
35        &self.native
36    }
37
38    /// Returns the title preferred by the user.
39    pub fn user_preferred(&self) -> &str {
40        self.user_preferred.as_deref().unwrap_or(&self.native)
41    }
42
43    /// Checks if the title is empty.
44    ///
45    /// A title is considered empty if all of its fields are either `None` or empty.
46    ///
47    /// # Returns
48    ///
49    /// * `true` if the `romaji`, `english`, and `user_preferred` fields are `None`
50    ///   and the `native` field is an empty string.
51    /// * `false` otherwise.
52    pub fn is_empty(&self) -> bool {
53        self.romaji.is_none()
54            && self.english.is_none()
55            && self.native.is_empty()
56            && self.user_preferred.is_none()
57    }
58}
59
60impl From<Title> for String {
61    fn from(title: Title) -> Self {
62        title.native().to_string()
63    }
64}
65
66impl std::fmt::Display for Title {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        write!(f, "{}", self.native())
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_romaji_with_romaji() {
78        let title = Title {
79            romaji: Some("Romaji Title".to_string()),
80            english: None,
81            native: "Native Title".to_string(),
82            user_preferred: None,
83        };
84
85        assert_eq!(title.romaji(), "Romaji Title");
86    }
87
88    #[test]
89    fn test_romaji_without_romaji() {
90        let title = Title {
91            romaji: None,
92            english: None,
93            native: "Native Title".to_string(),
94            user_preferred: None,
95        };
96
97        assert_eq!(title.romaji(), "Native Title");
98    }
99
100    #[test]
101    fn test_english_with_english() {
102        let title = Title {
103            romaji: None,
104            english: Some("English Title".to_string()),
105            native: "Native Title".to_string(),
106            user_preferred: None,
107        };
108
109        assert_eq!(title.english(), "English Title");
110    }
111
112    #[test]
113    fn test_english_without_english() {
114        let title = Title {
115            romaji: None,
116            english: None,
117            native: "Native Title".to_string(),
118            user_preferred: None,
119        };
120
121        assert_eq!(title.english(), "Native Title");
122    }
123
124    #[test]
125    fn test_native() {
126        let title = Title {
127            romaji: None,
128            english: None,
129            native: "Native Title".to_string(),
130            user_preferred: None,
131        };
132
133        assert_eq!(title.native(), "Native Title");
134    }
135
136    #[test]
137    fn test_user_preferred_with_user_preferred() {
138        let title = Title {
139            romaji: None,
140            english: None,
141            native: "Native Title".to_string(),
142            user_preferred: Some("User Preferred Title".to_string()),
143        };
144
145        assert_eq!(title.user_preferred(), "User Preferred Title");
146    }
147
148    #[test]
149    fn test_user_preferred_without_user_preferred() {
150        let title = Title {
151            romaji: None,
152            english: None,
153            native: "Native Title".to_string(),
154            user_preferred: None,
155        };
156
157        assert_eq!(title.user_preferred(), "Native Title");
158    }
159
160    #[test]
161    fn test_is_empty_all_none_and_empty() {
162        let title = Title {
163            romaji: None,
164            english: None,
165            native: String::new(),
166            user_preferred: None,
167        };
168
169        assert!(title.is_empty());
170    }
171
172    #[test]
173    fn test_is_empty_romaji_some() {
174        let title = Title {
175            romaji: Some(String::from("Romaji")),
176            english: None,
177            native: String::new(),
178            user_preferred: None,
179        };
180
181        assert!(!title.is_empty());
182    }
183
184    #[test]
185    fn test_is_empty_english_some() {
186        let title = Title {
187            romaji: None,
188            english: Some(String::from("English")),
189            native: String::new(),
190            user_preferred: None,
191        };
192
193        assert!(!title.is_empty());
194    }
195
196    #[test]
197    fn test_is_empty_native_not_empty() {
198        let title = Title {
199            romaji: None,
200            english: None,
201            native: String::from("Native"),
202            user_preferred: None,
203        };
204
205        assert!(!title.is_empty());
206    }
207
208    #[test]
209    fn test_is_empty_user_preferred_some() {
210        let title = Title {
211            romaji: None,
212            english: None,
213            native: String::new(),
214            user_preferred: Some(String::from("User Preferred")),
215        };
216
217        assert!(!title.is_empty());
218    }
219
220    #[test]
221    fn test_from_title_to_string() {
222        let title = Title {
223            romaji: None,
224            english: None,
225            native: "Native Title".to_string(),
226            user_preferred: None,
227        };
228        let title_string: String = title.into();
229
230        assert_eq!(title_string, "Native Title");
231    }
232}