1use super::split_line::split_line;
2use crate::store_links::{StoreLink, StoreLinks};
3use std::fmt;
4
5#[derive(PartialEq, Eq, Debug, Clone)]
13pub enum Field {
14 Game(Option<String>),
16 Cover(Option<String>),
18 Engine(Option<String>),
20 Setup(Option<String>),
22 Runtime(Option<String>),
24 Hints(Option<String>),
26 Dev(Option<String>),
28 Publi(Option<String>),
30 Version(Option<String>),
32 Status(Option<String>),
34 Store(Option<StoreLinks>),
37 Genres(Option<Vec<String>>),
40 Tags(Option<Vec<String>>),
43 Year(Option<String>),
45 Added(Option<String>),
47 Updated(Option<String>),
49 IgdbId(Option<String>),
51 Unknown(Option<String>),
55}
56
57impl fmt::Display for Field {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 match self {
60 Field::Game(name) => match name {
61 Some(name) => write!(f, "Game\t{}", name),
62 None => write!(f, "Game"),
63 },
64 Field::Cover(name) => match name {
65 Some(name) => write!(f, "Cover\t{}", name),
66 None => write!(f, "Cover"),
67 },
68 Field::Engine(name) => match name {
69 Some(name) => write!(f, "Engine\t{}", name),
70 None => write!(f, "Engine"),
71 },
72 Field::Setup(name) => match name {
73 Some(name) => write!(f, "Setup\t{}", name),
74 None => write!(f, "Setup"),
75 },
76 Field::Runtime(name) => match name {
77 Some(name) => write!(f, "Runtime\t{}", name),
78 None => write!(f, "Runtime"),
79 },
80 Field::Hints(name) => match name {
81 Some(name) => write!(f, "Hints\t{}", name),
82 None => write!(f, "Hints"),
83 },
84 Field::Dev(name) => match name {
85 Some(name) => write!(f, "Dev\t{}", name),
86 None => write!(f, "Dev"),
87 },
88 Field::Publi(name) => match name {
89 Some(name) => write!(f, "Pub\t{}", name),
90 None => write!(f, "Pub"),
91 },
92 Field::Version(name) => match name {
93 Some(name) => write!(f, "Version\t{}", name),
94 None => write!(f, "Version"),
95 },
96 Field::Status(name) => match name {
97 Some(name) => write!(f, "Status\t{}", name),
98 None => write!(f, "Status"),
99 },
100 Field::Store(name) => match name {
101 Some(StoreLinks(name)) => {
102 write!(
103 f,
104 "Store\t{}",
105 name.iter()
106 .map(|a| a.url.to_string())
107 .collect::<Vec<String>>()
108 .join(" ")
109 )
110 }
111 None => write!(f, "Store"),
112 },
113 Field::Genres(name) => match name {
114 Some(name) => write!(f, "Genre\t{}", name.join(", ")),
115 None => write!(f, "Genre"),
116 },
117 Field::Tags(name) => match name {
118 Some(name) => write!(f, "Tags\t{}", name.join(", ")),
119 None => write!(f, "Tags"),
120 },
121 Field::Year(name) => match name {
122 Some(name) => write!(f, "Year\t{}", name),
123 None => write!(f, "Year"),
124 },
125 Field::Added(name) => match name {
126 Some(name) => write!(f, "Added\t{}", name),
127 None => write!(f, "Added"),
128 },
129 Field::Updated(name) => match name {
130 Some(name) => write!(f, "Updated\t{}", name),
131 None => write!(f, "Updated"),
132 },
133 Field::IgdbId(name) => match name {
134 Some(name) => write!(f, "IgdbId\t{}", name),
135 None => write!(f, "IgdbId"),
136 },
137 Field::Unknown(field) => match field {
138 Some(field) => {
139 write!(f, "Unknown field {}", field)
140 }
141 None => {
142 write!(f, "Unexpected patern")
143 }
144 },
145 }
146 }
147}
148
149impl Field {
150 pub fn from(line: &str) -> Self {
153 let (left, right) = split_line(line);
155 if let Some(left) = left {
157 match left {
158 "Game" => match right {
159 Some(right) => Field::Game(Some(right.into())),
160 None => Field::Game(None),
161 },
162 "Cover" => match right {
163 Some(right) => Field::Cover(Some(right.into())),
164 None => Field::Cover(None),
165 },
166 "Engine" => match right {
167 Some(right) => Field::Engine(Some(right.into())),
168 None => Field::Engine(None),
169 },
170 "Setup" => match right {
171 Some(right) => Field::Setup(Some(right.into())),
172 None => Field::Setup(None),
173 },
174 "Runtime" => match right {
175 Some(right) => Field::Runtime(Some(right.into())),
176 None => Field::Runtime(None),
177 },
178 "Hints" => match right {
179 Some(right) => Field::Hints(Some(right.into())),
180 None => Field::Hints(None),
181 },
182 "Dev" => match right {
183 Some(right) => Field::Dev(Some(right.into())),
184 None => Field::Dev(None),
185 },
186 "Pub" => match right {
187 Some(right) => Field::Publi(Some(right.into())),
188 None => Field::Publi(None),
189 },
190 "Version" => match right {
191 Some(right) => Field::Version(Some(right.into())),
192 None => Field::Version(None),
193 },
194 "Status" => match right {
195 Some(right) => Field::Status(Some(right.into())),
196 None => Field::Status(None),
197 },
198 "Store" => match right {
200 Some(right) => {
201 let mut items: Vec<StoreLink> = Vec::new();
202 for item in right.split(' ') {
203 let store = StoreLink::from(item.trim());
204 items.push(store);
205 }
206 Field::Store(Some(StoreLinks(items)))
207 }
208 None => Field::Store(None),
209 },
210 "Genre" => match right {
211 Some(right) => {
212 let mut items: Vec<String> = Vec::new();
213 for item in right.split(',') {
214 items.push(item.trim().into());
215 }
216 Field::Genres(Some(items))
217 }
218 None => Field::Genres(None),
219 },
220 "Tags" => match right {
221 Some(right) => {
222 let mut items: Vec<String> = Vec::new();
223 for item in right.split(',') {
224 items.push(item.trim().into());
225 }
226 Field::Tags(Some(items))
227 }
228 None => Field::Tags(None),
229 },
230 "Year" => match right {
231 Some(right) => Field::Year(Some(right.into())),
232 None => Field::Year(None),
233 },
234 "Added" => match right {
235 Some(right) => Field::Added(Some(right.into())),
236 None => Field::Added(Some("1970/01/01".into())),
237 },
238 "Updated" => match right {
239 Some(right) => Field::Updated(Some(right.into())),
240 None => Field::Updated(None),
241 },
242 "IgdbId" => match right {
243 Some(right) => Field::IgdbId(Some(right.into())),
244 None => Field::IgdbId(None),
245 },
246 _ => Field::Unknown(Some(left.into())),
247 }
248 } else {
249 Field::Unknown(None)
250 }
251 }
252}
253
254#[cfg(test)]
255mod field_tests {
256 use super::*;
257 #[test]
258 fn test_from_game_line() {
259 let input = "Game\tToto";
260 let field = Field::from(&input);
261 assert_eq!(Field::Game(Some("Toto".into())), field);
262 assert_eq!(format!("{}", field), input);
263 let input = "Game";
264 let field = Field::from(&input);
265 assert_eq!(Field::Game(None), field);
266 assert_eq!(format!("{}", field), input);
267 }
268 #[test]
269 fn test_from_cover_line() {
270 let input = "Cover\tToto";
271 let field = Field::from(&input);
272 assert_eq!(Field::Cover(Some("Toto".into())), field);
273 assert_eq!(format!("{}", field), input);
274 let input = "Cover";
275 let field = Field::from(&input);
276 assert_eq!(Field::Cover(None), field);
277 assert_eq!(format!("{}", field), input);
278 }
279 #[test]
280 fn test_from_engine_line() {
281 let input = "Engine\tToto";
282 let field = Field::from(&input);
283 assert_eq!(Field::Engine(Some("Toto".into())), field);
284 assert_eq!(format!("{}", field), input);
285 let input = "Engine";
286 let field = Field::from(&input);
287 assert_eq!(Field::Engine(None), field);
288 assert_eq!(format!("{}", field), input);
289 }
290 #[test]
291 fn test_from_setup_line() {
292 let input = "Setup\tToto";
293 let field = Field::from(&input);
294 assert_eq!(Field::Setup(Some("Toto".into())), field);
295 assert_eq!(format!("{}", field), input);
296 let input = "Setup";
297 let field = Field::from(&input);
298 assert_eq!(Field::Setup(None), field);
299 assert_eq!(format!("{}", field), input);
300 }
301 #[test]
302 fn test_from_runtime_line() {
303 let input = "Runtime\tToto";
304 let field = Field::from(&input);
305 assert_eq!(Field::Runtime(Some("Toto".into())), field);
306 assert_eq!(format!("{}", field), input);
307 let input = "Runtime";
308 let field = Field::from(&input);
309 assert_eq!(Field::Runtime(None), field);
310 assert_eq!(format!("{}", field), input);
311 }
312 #[test]
313 fn test_from_hints_line() {
314 let input = "Hints\tToto";
315 let field = Field::from(&input);
316 assert_eq!(Field::Hints(Some("Toto".into())), field);
317 assert_eq!(format!("{}", field), input);
318 let input = "Hints";
319 let field = Field::from(&input);
320 assert_eq!(Field::Hints(None), field);
321 assert_eq!(format!("{}", field), input);
322 }
323 #[test]
324 fn test_from_dev_line() {
325 let input = "Dev\tToto";
326 let field = Field::from(&input);
327 assert_eq!(Field::Dev(Some("Toto".into())), field);
328 assert_eq!(format!("{}", field), input);
329 let input = "Dev";
330 let field = Field::from(&input);
331 assert_eq!(Field::Dev(None), field);
332 assert_eq!(format!("{}", field), input);
333 }
334 #[test]
335 fn test_from_publi_line() {
336 let input = "Pub\tToto";
337 let field = Field::from(&input);
338 assert_eq!(Field::Publi(Some("Toto".into())), field);
339 assert_eq!(format!("{}", field), input);
340 let input = "Pub";
341 let field = Field::from(&input);
342 assert_eq!(Field::Publi(None), field);
343 assert_eq!(format!("{}", field), input);
344 }
345 #[test]
346 fn test_from_version_line() {
347 let input = "Version\tToto";
348 let field = Field::from(&input);
349 assert_eq!(Field::Version(Some("Toto".into())), field);
350 assert_eq!(format!("{}", field), input);
351 let input = "Version";
352 let field = Field::from(&input);
353 assert_eq!(Field::Version(None), field);
354 assert_eq!(format!("{}", field), input);
355 }
356 #[test]
357 fn test_from_status_line() {
358 let input = "Status\tToto";
359 let field = Field::from(&input);
360 assert_eq!(Field::Status(Some("Toto".into())), field);
361 assert_eq!(format!("{}", field), input);
362 let input = "Status";
363 let field = Field::from(&input);
364 assert_eq!(Field::Status(None), field);
365 assert_eq!(format!("{}", field), input);
366 }
367 #[test]
368 fn test_from_store_line() {
369 let input = "Store\tfirst second";
370 let field = Field::from(&input);
371 assert_eq!(
372 Field::Store(Some(StoreLinks(vec![
373 StoreLink::from("first"),
374 StoreLink::from("second")
375 ]))),
376 field
377 );
378 assert_eq!(format!("{}", field), input);
379 let input = "Store";
380 let field = Field::from(&input);
381 assert_eq!(Field::Store(None), field);
382 assert_eq!(format!("{}", field), input);
383 }
384 #[test]
385 fn test_from_genre_line() {
386 let input = "Genre\tfirst, second";
387 let field = Field::from(&input);
388 assert_eq!(
389 Field::Genres(Some(vec!["first".into(), "second".into()])),
390 field
391 );
392 assert_eq!(format!("{}", field), input);
393 let input = "Genre";
394 let field = Field::from(&input);
395 assert_eq!(Field::Genres(None), field);
396 assert_eq!(format!("{}", field), input);
397 }
398 #[test]
399 fn test_from_tag_line() {
400 let input = "Tags\tfirst, second";
401 let field = Field::from(&input);
402 assert_eq!(
403 Field::Tags(Some(vec!["first".into(), "second".into()])),
404 field
405 );
406 assert_eq!(format!("{}", field), input);
407 let input = "Tags";
408 let field = Field::from(&input);
409 assert_eq!(Field::Tags(None), field);
410 assert_eq!(format!("{}", field), input);
411 }
412 #[test]
413 fn test_from_year_line() {
414 let input = "Year\t1980";
415 let field = Field::from(&input);
416 assert_eq!(Field::Year(Some("1980".into())), field);
417 assert_eq!(format!("{}", field), input);
418 let input = "Year";
419 let field = Field::from(&input);
420 assert_eq!(Field::Year(None), field);
421 assert_eq!(format!("{}", field), input);
422 }
423 #[test]
424 fn test_from_unknown_field() {
425 let input = "Let's not\tpanic";
426 let field = Field::from(&input);
427 assert_eq!(Field::Unknown(Some("Let's not".into())), field);
428 assert_eq!(
429 format!("{}", field),
430 format!("Unknown field {}", "Let's not")
431 );
432 }
433 #[test]
434 fn test_from_unknown_field_with_notab() {
435 let input = "Let's not";
436 let field = Field::from(&input);
437 assert_eq!(Field::Unknown(Some("Let's not".into())), field);
438 assert_eq!(format!("{}", field), format!("Unknown field {}", input));
439 }
440 #[test]
441 fn test_from_igdb_id_line() {
442 let input = "IgdbId\t12";
443 let field = Field::from(&input);
444 assert_eq!(Field::IgdbId(Some("12".into())), field);
445 assert_eq!(format!("{}", field), input);
446 let input = "IgdbId";
447 let field = Field::from(&input);
448 assert_eq!(Field::IgdbId(None), field);
449 assert_eq!(format!("{}", field), input);
450 }
451}