1#[derive(Debug, PartialEq, Clone, Eq, Default)]
2pub enum PgnEvent {
3 #[default]
4 Casual,
5 Unknown,
6 Named(String),
7}
8impl std::str::FromStr for PgnEvent {
9 type Err = crate::errors::ChessError;
10
11 fn from_str(s: &str) -> Result<Self, Self::Err> {
12 if s.is_empty() || s == "?" {
13 return Ok(Self::Unknown);
14 }
15 if s.contains("Casual") {
16 return Ok(Self::Casual);
17 }
18 Ok(Self::Named(s.to_string()))
19 }
20}
21impl std::fmt::Display for PgnEvent {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::Casual => write!(f, "Casual Game"),
25 Self::Unknown => write!(f, "?"),
26 Self::Named(name) => write!(f, "{name}"),
27 }
28 }
29}
30
31#[derive(Debug, PartialEq, Clone, Eq, Default)]
32pub enum PgnSite {
33 #[default]
34 Unknown,
35 Named(String),
36}
37impl std::str::FromStr for PgnSite {
38 type Err = crate::errors::ChessError;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 if s.is_empty() || s == "?" {
42 return Ok(Self::Unknown);
43 }
44 Ok(Self::Named(s.to_string()))
45 }
46}
47impl std::fmt::Display for PgnSite {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Self::Unknown => write!(f, "?"),
51 Self::Named(name) => write!(f, "{name}"),
52 }
53 }
54}
55
56#[derive(Debug, PartialEq, Clone, Eq, Default)]
57pub enum PgnRound {
58 #[default]
59 Unknown,
60 Named(String),
61}
62impl std::str::FromStr for PgnRound {
63 type Err = crate::errors::ChessError;
64
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 if s.is_empty() || s == "-" {
67 return Ok(Self::Unknown);
68 }
69 Ok(Self::Named(s.to_string()))
70 }
71}
72impl std::fmt::Display for PgnRound {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self {
75 Self::Unknown => write!(f, "-"),
76 Self::Named(name) => write!(f, "{name}"),
77 }
78 }
79}
80
81#[derive(Debug, PartialEq, Clone, Eq, Default)]
82pub enum PgnResult {
83 #[default]
84 Unknown,
85 Outcome(shakmaty::Outcome),
86}
87impl std::str::FromStr for PgnResult {
88 type Err = crate::errors::ChessError;
89
90 fn from_str(s: &str) -> Result<Self, Self::Err> {
91 match s {
92 "1-0" => Ok(Self::Outcome(shakmaty::Outcome::Decisive {
93 winner: shakmaty::Color::White,
94 })),
95 "0-1" => Ok(Self::Outcome(shakmaty::Outcome::Decisive {
96 winner: shakmaty::Color::Black,
97 })),
98 "1/2-1/2" => Ok(Self::Outcome(shakmaty::Outcome::Draw)),
99 "*" => Ok(Self::Unknown),
100 _ => Err(crate::errors::ChessError::InvalidPgn(std::io::Error::new(
101 std::io::ErrorKind::InvalidData,
102 "Invalid result",
103 ))),
104 }
105 }
106}
107impl std::fmt::Display for PgnResult {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 match self {
110 Self::Unknown => write!(f, "*"),
111 Self::Outcome(outcome) => match outcome {
112 shakmaty::Outcome::Decisive { winner } => {
113 if winner == &shakmaty::Color::White {
114 write!(f, "1-0")
115 } else {
116 write!(f, "0-1")
117 }
118 }
119 shakmaty::Outcome::Draw => write!(f, "1/2-1/2"),
120 },
121 }
122 }
123}
124
125#[derive(Debug, PartialEq, Clone, Eq, Default)]
126pub enum PgnTermination {
127 Abandoned,
128 Adjudication,
129 Death,
130 Emergency,
131 #[default]
132 Normal,
133 RulesInfraction,
134 TimeForfeit,
135 Unterminated,
136}
137impl std::str::FromStr for PgnTermination {
138 type Err = crate::errors::ChessError;
139
140 fn from_str(s: &str) -> Result<Self, Self::Err> {
141 match s {
142 "Abandoned" => Ok(Self::Abandoned),
143 "Adjudication" => Ok(Self::Adjudication),
144 "Death" => Ok(Self::Death),
145 "Emergency" => Ok(Self::Emergency),
146 "Normal" => Ok(Self::Normal),
147 "Rules infraction" => Ok(Self::RulesInfraction),
148 "Time forfeit" => Ok(Self::TimeForfeit),
149 "Unterminated" => Ok(Self::Unterminated),
150 _ => Err(crate::errors::ChessError::InvalidPgn(std::io::Error::new(
151 std::io::ErrorKind::InvalidData,
152 "Invalid termination reason",
153 ))),
154 }
155 }
156}
157impl std::fmt::Display for PgnTermination {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 match self {
160 Self::Abandoned => write!(f, "Abandoned"),
161 Self::Adjudication => write!(f, "Adjudication"),
162 Self::Death => write!(f, "Death"),
163 Self::Emergency => write!(f, "Emergency"),
164 Self::Normal => write!(f, "Normal"),
165 Self::RulesInfraction => write!(f, "Rules infraction"),
166 Self::TimeForfeit => write!(f, "Time forfeit"),
167 Self::Unterminated => write!(f, "Unterminated"),
168 }
169 }
170}
171
172#[derive(Debug, PartialEq, Clone, Eq)]
173pub enum TimeControl {
174 Unknown,
175 NoTimeControl,
176 MovesInTime { moves: u32, seconds: u32 },
177 SuddenDeath { seconds: u32 },
178 Incremental { base: u32, increment: u32 },
179 Sandclock { seconds: u32 },
180 Multiple(Vec<TimeControl>),
181}
182#[derive(Debug, PartialEq, Eq)]
183pub enum TimeControlParseError {
184 EmptyString,
185 InvalidFormat(String),
186 InvalidNumber(String),
187 UnexpectedField(String),
188}
189impl TryFrom<&[u8]> for TimeControl {
190 type Error = TimeControlParseError;
191
192 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
193 let s = std::str::from_utf8(value)
194 .map_err(|_| TimeControlParseError::InvalidFormat("Invalid UTF-8".to_string()))?;
195 s.parse()
196 }
197}
198impl std::str::FromStr for TimeControl {
199 type Err = TimeControlParseError;
200
201 fn from_str(s: &str) -> Result<Self, Self::Err> {
202 if s.is_empty() {
203 return Err(TimeControlParseError::EmptyString);
204 }
205
206 match s {
208 "?" => return Ok(Self::Unknown),
209 "-" => return Ok(Self::NoTimeControl),
210 _ => (),
211 }
212
213 if s.contains(':') {
215 let fields: Vec<&str> = s.split(':').collect();
216 let mut controls = Vec::new();
217
218 for field in fields {
219 controls.push(field.parse()?);
220 }
221
222 return Ok(Self::Multiple(controls));
223 }
224
225 if s.contains('/') {
227 let parts: Vec<&str> = s.split('/').collect();
229 if parts.len() != 2 {
230 return Err(TimeControlParseError::InvalidFormat(s.to_string()));
231 }
232
233 let moves = parts[0]
234 .parse()
235 .map_err(|_| TimeControlParseError::InvalidNumber(parts[0].to_string()))?;
236 let seconds = parts[1]
237 .parse()
238 .map_err(|_| TimeControlParseError::InvalidNumber(parts[1].to_string()))?;
239
240 return Ok(Self::MovesInTime { moves, seconds });
241 } else if s.contains('+') {
242 let parts: Vec<&str> = s.split('+').collect();
244 if parts.len() != 2 {
245 return Err(TimeControlParseError::InvalidFormat(s.to_string()));
246 }
247
248 let base = parts[0]
249 .parse()
250 .map_err(|_| TimeControlParseError::InvalidNumber(parts[0].to_string()))?;
251 let increment = parts[1]
252 .parse()
253 .map_err(|_| TimeControlParseError::InvalidNumber(parts[1].to_string()))?;
254
255 return Ok(Self::Incremental { base, increment });
256 } else if let Some(stripped) = s.strip_prefix("*") {
257 let seconds = stripped
259 .parse()
260 .map_err(|_| TimeControlParseError::InvalidNumber(stripped.to_string()))?;
261
262 return Ok(Self::Sandclock { seconds });
263 } else
264 if let Ok(seconds) = s.parse() {
266 return Ok(Self::SuddenDeath { seconds });
267 }
268
269 Err(TimeControlParseError::InvalidFormat(s.to_string()))
270 }
271}
272
273impl std::fmt::Display for TimeControl {
274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275 match self {
276 Self::Unknown => write!(f, "?"),
277 Self::NoTimeControl => write!(f, "-"),
278 Self::MovesInTime { moves, seconds } => write!(f, "{moves}/{seconds}"),
279 Self::SuddenDeath { seconds } => write!(f, "{seconds}"),
280 Self::Incremental { base, increment } => write!(f, "{base}+{increment}"),
281 Self::Sandclock { seconds } => write!(f, "*{seconds}"),
282 Self::Multiple(controls) => {
283 let parts: Vec<String> = controls
284 .iter()
285 .map(std::string::ToString::to_string)
286 .collect();
287 write!(f, "{}", parts.join(":"))
288 }
289 }
290 }
291}
292
293#[cfg(test)]
294mod tests {
295 use super::*;
296
297 #[test]
298 fn test_parse_unknown_time() {
299 assert_eq!("?".parse(), Ok(TimeControl::Unknown));
300 }
301
302 #[test]
303 fn test_parse_no_time_control() {
304 assert_eq!("-".parse(), Ok(TimeControl::NoTimeControl));
305 }
306
307 #[test]
308 fn test_parse_moves_in_time() {
309 assert_eq!(
310 "40/9000".parse(),
311 Ok(TimeControl::MovesInTime {
312 moves: 40,
313 seconds: 9000
314 })
315 );
316 }
317
318 #[test]
319 fn test_parse_sudden_death_time() {
320 assert_eq!("300".parse(), Ok(TimeControl::SuddenDeath { seconds: 300 }));
321 }
322
323 #[test]
324 fn test_parse_incremental_time() {
325 assert_eq!(
326 "4500+60".parse(),
327 Ok(TimeControl::Incremental {
328 base: 4500,
329 increment: 60
330 })
331 );
332 }
333
334 #[test]
335 fn test_parse_sandclock_time() {
336 assert_eq!("*180".parse(), Ok(TimeControl::Sandclock { seconds: 180 }));
337 }
338
339 #[test]
340 fn test_parse_multiple_time() {
341 assert_eq!(
342 "40/9000:300".parse(),
343 Ok(TimeControl::Multiple(vec![
344 TimeControl::MovesInTime {
345 moves: 40,
346 seconds: 9000
347 },
348 TimeControl::SuddenDeath { seconds: 300 }
349 ]))
350 );
351 }
352
353 #[test]
354 fn test_display_time() {
355 assert_eq!(TimeControl::Unknown.to_string(), "?");
356 assert_eq!(TimeControl::NoTimeControl.to_string(), "-");
357 assert_eq!(
358 TimeControl::MovesInTime {
359 moves: 40,
360 seconds: 9000
361 }
362 .to_string(),
363 "40/9000"
364 );
365 assert_eq!(
366 TimeControl::Multiple(vec![
367 TimeControl::MovesInTime {
368 moves: 40,
369 seconds: 9000
370 },
371 TimeControl::SuddenDeath { seconds: 300 }
372 ])
373 .to_string(),
374 "40/9000:300"
375 );
376 }
377 #[test]
378 fn test_from_str() {
379 assert_eq!(
380 "USA".parse::<OlympicCountryCode>().unwrap(),
381 OlympicCountryCode::UnitedStatesOfAmerica
382 );
383 assert_eq!(
384 "ENG".parse::<OlympicCountryCode>().unwrap(),
385 OlympicCountryCode::England
386 );
387 assert_eq!(
388 "RUS".parse::<OlympicCountryCode>().unwrap(),
389 OlympicCountryCode::Russia
390 );
391 assert_eq!(
392 "JAP".parse::<OlympicCountryCode>().unwrap(),
393 OlympicCountryCode::Japan
394 );
395 }
396
397 #[test]
398 fn test_display() {
399 assert_eq!(OlympicCountryCode::UnitedStatesOfAmerica.to_string(), "USA");
400 assert_eq!(OlympicCountryCode::England.to_string(), "ENG");
401 assert_eq!(OlympicCountryCode::Russia.to_string(), "RUS");
402 assert_eq!(OlympicCountryCode::Japan.to_string(), "JAP");
403 }
404
405 #[test]
406 fn test_unknown_code() {
407 assert!("XYZ".parse::<OlympicCountryCode>().is_err());
408 }
409}
410
411#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
412pub enum OlympicCountryCode {
413 Afghanistan,
414 AboardAircraft,
415 Albania,
416 Algeria,
417 Andorra,
418 Angola,
419 Antigua,
420 Argentina,
421 Armenia,
422 Antarctica,
423 Australia,
424 Azerbaijan,
425 Bangladesh,
426 Bahrain,
427 Bahamas,
428 Belgium,
429 Bermuda,
430 BosniaHerzegovina,
431 Belarus,
432 Bulgaria,
433 Belize,
434 Bolivia,
435 Barbados,
436 Brazil,
437 Brunei,
438 Botswana,
439 Canada,
440 Chile,
441 Columbia,
442 CostaRica,
443 Croatia,
444 Czechoslovakia,
445 Cuba,
446 Cyprus,
447 Denmark,
448 DominicanRepublic,
449 Ecuador,
450 Egypt,
451 England,
452 Spain,
453 Estonia,
454 FaroeIslands,
455 Fiji,
456 Finland,
457 France,
458 Gambia,
459 GuernseyJersey,
460 Georgia,
461 Germany,
462 Ghana,
463 Greece,
464 Guatemala,
465 Guyana,
466 Haiti,
467 HongKong,
468 Honduras,
469 Hungary,
470 India,
471 Ireland,
472 Iran,
473 Iraq,
474 Iceland,
475 Israel,
476 Italy,
477 IvoryCoast,
478 Jamaica,
479 Japan,
480 Jordan,
481 Yugoslavia,
482 Kazakhstan,
483 Kenya,
484 Kyrgyzstan,
485 Kuwait,
486 Latvia,
487 Lebanon,
488 Libya,
489 Liechtenstein,
490 Lithuania,
491 Luxembourg,
492 Malaysia,
493 Mauritania,
494 Mexico,
495 Mali,
496 Malta,
497 Monaco,
498 Moldova,
499 Mongolia,
500 Mozambique,
501 Morocco,
502 Mauritius,
503 Myanmar,
504 Nicaragua,
505 TheInternet,
506 Nigeria,
507 NetherlandsAntilles,
508 Netherlands,
509 Norway,
510 NewZealand,
511 Austria,
512 Pakistan,
513 Palestine,
514 Panama,
515 Paraguay,
516 Peru,
517 Philippines,
518 PapuaNewGuinea,
519 Poland,
520 Portugal,
521 PeoplesRepublicOfChina,
522 PuertoRico,
523 Qatar,
524 Indonesia,
525 Romania,
526 Russia,
527 SouthAfrica,
528 ElSalvador,
529 Scotland,
530 AtSea,
531 Senegal,
532 Seychelles,
533 Singapore,
534 Slovenia,
535 SanMarino,
536 AboardSpacecraft,
537 SriLanka,
538 Sudan,
539 Surinam,
540 Sweden,
541 Switzerland,
542 Syria,
543 Thailand,
544 Turkmenistan,
545 Turkey,
546 TrinidadAndTobago,
547 Tunisia,
548 UnitedArabEmirates,
549 Uganda,
550 Ukraine,
551 Unknown,
552 Uruguay,
553 UnitedStatesOfAmerica,
554 Uzbekistan,
555 Venezuela,
556 BritishVirginIslands,
557 Vietnam,
558 USVirginIslands,
559 Wales,
560 Yemen,
561 Zambia,
562 Zimbabwe,
563 Zaire,
564}
565
566impl std::str::FromStr for OlympicCountryCode {
567 type Err = crate::errors::ChessError;
568
569 #[allow(clippy::too_many_lines)]
570 fn from_str(code: &str) -> Result<Self, Self::Err> {
571 match code {
572 "AFG" => Ok(Self::Afghanistan),
573 "AIR" => Ok(Self::AboardAircraft),
574 "ALB" => Ok(Self::Albania),
575 "ALG" => Ok(Self::Algeria),
576 "AND" => Ok(Self::Andorra),
577 "ANG" => Ok(Self::Angola),
578 "ANT" => Ok(Self::Antigua),
579 "ARG" => Ok(Self::Argentina),
580 "ARM" => Ok(Self::Armenia),
581 "ATA" => Ok(Self::Antarctica),
582 "AUS" => Ok(Self::Australia),
583 "AZB" => Ok(Self::Azerbaijan),
584 "BAN" => Ok(Self::Bangladesh),
585 "BAR" => Ok(Self::Bahrain),
586 "BHM" => Ok(Self::Bahamas),
587 "BEL" => Ok(Self::Belgium),
588 "BER" => Ok(Self::Bermuda),
589 "BIH" => Ok(Self::BosniaHerzegovina),
590 "BLA" => Ok(Self::Belarus),
591 "BLG" => Ok(Self::Bulgaria),
592 "BLZ" => Ok(Self::Belize),
593 "BOL" => Ok(Self::Bolivia),
594 "BRB" => Ok(Self::Barbados),
595 "BRS" => Ok(Self::Brazil),
596 "BRU" => Ok(Self::Brunei),
597 "BSW" => Ok(Self::Botswana),
598 "CAN" => Ok(Self::Canada),
599 "CHI" => Ok(Self::Chile),
600 "COL" => Ok(Self::Columbia),
601 "CRA" => Ok(Self::CostaRica),
602 "CRO" => Ok(Self::Croatia),
603 "CSR" => Ok(Self::Czechoslovakia),
604 "CUB" => Ok(Self::Cuba),
605 "CYP" => Ok(Self::Cyprus),
606 "DEN" => Ok(Self::Denmark),
607 "DOM" => Ok(Self::DominicanRepublic),
608 "ECU" => Ok(Self::Ecuador),
609 "EGY" => Ok(Self::Egypt),
610 "ENG" => Ok(Self::England),
611 "ESP" => Ok(Self::Spain),
612 "EST" => Ok(Self::Estonia),
613 "FAI" => Ok(Self::FaroeIslands),
614 "FIJ" => Ok(Self::Fiji),
615 "FIN" => Ok(Self::Finland),
616 "FRA" => Ok(Self::France),
617 "GAM" => Ok(Self::Gambia),
618 "GCI" => Ok(Self::GuernseyJersey),
619 "GEO" => Ok(Self::Georgia),
620 "GER" => Ok(Self::Germany),
621 "GHA" => Ok(Self::Ghana),
622 "GRC" => Ok(Self::Greece),
623 "GUA" => Ok(Self::Guatemala),
624 "GUY" => Ok(Self::Guyana),
625 "HAI" => Ok(Self::Haiti),
626 "HKG" => Ok(Self::HongKong),
627 "HON" => Ok(Self::Honduras),
628 "HUN" => Ok(Self::Hungary),
629 "IND" => Ok(Self::India),
630 "IRL" => Ok(Self::Ireland),
631 "IRN" => Ok(Self::Iran),
632 "IRQ" => Ok(Self::Iraq),
633 "ISD" => Ok(Self::Iceland),
634 "ISR" => Ok(Self::Israel),
635 "ITA" => Ok(Self::Italy),
636 "IVO" => Ok(Self::IvoryCoast),
637 "JAM" => Ok(Self::Jamaica),
638 "JAP" => Ok(Self::Japan),
639 "JRD" => Ok(Self::Jordan),
640 "JUG" => Ok(Self::Yugoslavia),
641 "KAZ" => Ok(Self::Kazakhstan),
642 "KEN" => Ok(Self::Kenya),
643 "KIR" => Ok(Self::Kyrgyzstan),
644 "KUW" => Ok(Self::Kuwait),
645 "LAT" => Ok(Self::Latvia),
646 "LEB" => Ok(Self::Lebanon),
647 "LIB" => Ok(Self::Libya),
648 "LIC" => Ok(Self::Liechtenstein),
649 "LTU" => Ok(Self::Lithuania),
650 "LUX" => Ok(Self::Luxembourg),
651 "MAL" => Ok(Self::Malaysia),
652 "MAU" => Ok(Self::Mauritania),
653 "MEX" => Ok(Self::Mexico),
654 "MLI" => Ok(Self::Mali),
655 "MLT" => Ok(Self::Malta),
656 "MNC" => Ok(Self::Monaco),
657 "MOL" => Ok(Self::Moldova),
658 "MON" => Ok(Self::Mongolia),
659 "MOZ" => Ok(Self::Mozambique),
660 "MRC" => Ok(Self::Morocco),
661 "MRT" => Ok(Self::Mauritius),
662 "MYN" => Ok(Self::Myanmar),
663 "NCG" => Ok(Self::Nicaragua),
664 "NET" => Ok(Self::TheInternet),
665 "NIG" => Ok(Self::Nigeria),
666 "NLA" => Ok(Self::NetherlandsAntilles),
667 "NLD" => Ok(Self::Netherlands),
668 "NOR" => Ok(Self::Norway),
669 "NZD" => Ok(Self::NewZealand),
670 "OST" => Ok(Self::Austria),
671 "PAK" => Ok(Self::Pakistan),
672 "PAL" => Ok(Self::Palestine),
673 "PAN" => Ok(Self::Panama),
674 "PAR" => Ok(Self::Paraguay),
675 "PER" => Ok(Self::Peru),
676 "PHI" => Ok(Self::Philippines),
677 "PNG" => Ok(Self::PapuaNewGuinea),
678 "POL" => Ok(Self::Poland),
679 "POR" => Ok(Self::Portugal),
680 "PRC" => Ok(Self::PeoplesRepublicOfChina),
681 "PRO" => Ok(Self::PuertoRico),
682 "QTR" => Ok(Self::Qatar),
683 "RIN" => Ok(Self::Indonesia),
684 "ROM" => Ok(Self::Romania),
685 "RUS" => Ok(Self::Russia),
686 "SAF" => Ok(Self::SouthAfrica),
687 "SAL" => Ok(Self::ElSalvador),
688 "SCO" => Ok(Self::Scotland),
689 "SEA" => Ok(Self::AtSea),
690 "SEN" => Ok(Self::Senegal),
691 "SEY" => Ok(Self::Seychelles),
692 "SIP" => Ok(Self::Singapore),
693 "SLV" => Ok(Self::Slovenia),
694 "SMA" => Ok(Self::SanMarino),
695 "SPC" => Ok(Self::AboardSpacecraft),
696 "SRI" => Ok(Self::SriLanka),
697 "SUD" => Ok(Self::Sudan),
698 "SUR" => Ok(Self::Surinam),
699 "SVE" => Ok(Self::Sweden),
700 "SWZ" => Ok(Self::Switzerland),
701 "SYR" => Ok(Self::Syria),
702 "TAI" => Ok(Self::Thailand),
703 "TMT" => Ok(Self::Turkmenistan),
704 "TRK" => Ok(Self::Turkey),
705 "TTO" => Ok(Self::TrinidadAndTobago),
706 "TUN" => Ok(Self::Tunisia),
707 "UAE" => Ok(Self::UnitedArabEmirates),
708 "UGA" => Ok(Self::Uganda),
709 "UKR" => Ok(Self::Ukraine),
710 "UNK" => Ok(Self::Unknown),
711 "URU" => Ok(Self::Uruguay),
712 "USA" => Ok(Self::UnitedStatesOfAmerica),
713 "UZB" => Ok(Self::Uzbekistan),
714 "VEN" => Ok(Self::Venezuela),
715 "VGB" => Ok(Self::BritishVirginIslands),
716 "VIE" => Ok(Self::Vietnam),
717 "VUS" => Ok(Self::USVirginIslands),
718 "WLS" => Ok(Self::Wales),
719 "YEM" => Ok(Self::Yemen),
720 "ZAM" => Ok(Self::Zambia),
721 "ZIM" => Ok(Self::Zimbabwe),
722 "ZRE" => Ok(Self::Zaire),
723 _ => Err(crate::errors::ChessError::InvalidPgn(std::io::Error::new(
724 std::io::ErrorKind::InvalidData,
725 format!("Unknown country code: {code}"),
726 ))),
727 }
728 }
729}
730
731impl std::fmt::Display for OlympicCountryCode {
732 #[allow(clippy::too_many_lines)]
733 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
734 let code = match self {
735 Self::Afghanistan => "AFG",
736 Self::AboardAircraft => "AIR",
737 Self::Albania => "ALB",
738 Self::Algeria => "ALG",
739 Self::Andorra => "AND",
740 Self::Angola => "ANG",
741 Self::Antigua => "ANT",
742 Self::Argentina => "ARG",
743 Self::Armenia => "ARM",
744 Self::Antarctica => "ATA",
745 Self::Australia => "AUS",
746 Self::Azerbaijan => "AZB",
747 Self::Bangladesh => "BAN",
748 Self::Bahrain => "BAR",
749 Self::Bahamas => "BHM",
750 Self::Belgium => "BEL",
751 Self::Bermuda => "BER",
752 Self::BosniaHerzegovina => "BIH",
753 Self::Belarus => "BLA",
754 Self::Bulgaria => "BLG",
755 Self::Belize => "BLZ",
756 Self::Bolivia => "BOL",
757 Self::Barbados => "BRB",
758 Self::Brazil => "BRS",
759 Self::Brunei => "BRU",
760 Self::Botswana => "BSW",
761 Self::Canada => "CAN",
762 Self::Chile => "CHI",
763 Self::Columbia => "COL",
764 Self::CostaRica => "CRA",
765 Self::Croatia => "CRO",
766 Self::Czechoslovakia => "CSR",
767 Self::Cuba => "CUB",
768 Self::Cyprus => "CYP",
769 Self::Denmark => "DEN",
770 Self::DominicanRepublic => "DOM",
771 Self::Ecuador => "ECU",
772 Self::Egypt => "EGY",
773 Self::England => "ENG",
774 Self::Spain => "ESP",
775 Self::Estonia => "EST",
776 Self::FaroeIslands => "FAI",
777 Self::Fiji => "FIJ",
778 Self::Finland => "FIN",
779 Self::France => "FRA",
780 Self::Gambia => "GAM",
781 Self::GuernseyJersey => "GCI",
782 Self::Georgia => "GEO",
783 Self::Germany => "GER",
784 Self::Ghana => "GHA",
785 Self::Greece => "GRC",
786 Self::Guatemala => "GUA",
787 Self::Guyana => "GUY",
788 Self::Haiti => "HAI",
789 Self::HongKong => "HKG",
790 Self::Honduras => "HON",
791 Self::Hungary => "HUN",
792 Self::India => "IND",
793 Self::Ireland => "IRL",
794 Self::Iran => "IRN",
795 Self::Iraq => "IRQ",
796 Self::Iceland => "ISD",
797 Self::Israel => "ISR",
798 Self::Italy => "ITA",
799 Self::IvoryCoast => "IVO",
800 Self::Jamaica => "JAM",
801 Self::Japan => "JAP",
802 Self::Jordan => "JRD",
803 Self::Yugoslavia => "JUG",
804 Self::Kazakhstan => "KAZ",
805 Self::Kenya => "KEN",
806 Self::Kyrgyzstan => "KIR",
807 Self::Kuwait => "KUW",
808 Self::Latvia => "LAT",
809 Self::Lebanon => "LEB",
810 Self::Libya => "LIB",
811 Self::Liechtenstein => "LIC",
812 Self::Lithuania => "LTU",
813 Self::Luxembourg => "LUX",
814 Self::Malaysia => "MAL",
815 Self::Mauritania => "MAU",
816 Self::Mexico => "MEX",
817 Self::Mali => "MLI",
818 Self::Malta => "MLT",
819 Self::Monaco => "MNC",
820 Self::Moldova => "MOL",
821 Self::Mongolia => "MON",
822 Self::Mozambique => "MOZ",
823 Self::Morocco => "MRC",
824 Self::Mauritius => "MRT",
825 Self::Myanmar => "MYN",
826 Self::Nicaragua => "NCG",
827 Self::TheInternet => "NET",
828 Self::Nigeria => "NIG",
829 Self::NetherlandsAntilles => "NLA",
830 Self::Netherlands => "NLD",
831 Self::Norway => "NOR",
832 Self::NewZealand => "NZD",
833 Self::Austria => "OST",
834 Self::Pakistan => "PAK",
835 Self::Palestine => "PAL",
836 Self::Panama => "PAN",
837 Self::Paraguay => "PAR",
838 Self::Peru => "PER",
839 Self::Philippines => "PHI",
840 Self::PapuaNewGuinea => "PNG",
841 Self::Poland => "POL",
842 Self::Portugal => "POR",
843 Self::PeoplesRepublicOfChina => "PRC",
844 Self::PuertoRico => "PRO",
845 Self::Qatar => "QTR",
846 Self::Indonesia => "RIN",
847 Self::Romania => "ROM",
848 Self::Russia => "RUS",
849 Self::SouthAfrica => "SAF",
850 Self::ElSalvador => "SAL",
851 Self::Scotland => "SCO",
852 Self::AtSea => "SEA",
853 Self::Senegal => "SEN",
854 Self::Seychelles => "SEY",
855 Self::Singapore => "SIP",
856 Self::Slovenia => "SLV",
857 Self::SanMarino => "SMA",
858 Self::AboardSpacecraft => "SPC",
859 Self::SriLanka => "SRI",
860 Self::Sudan => "SUD",
861 Self::Surinam => "SUR",
862 Self::Sweden => "SVE",
863 Self::Switzerland => "SWZ",
864 Self::Syria => "SYR",
865 Self::Thailand => "TAI",
866 Self::Turkmenistan => "TMT",
867 Self::Turkey => "TRK",
868 Self::TrinidadAndTobago => "TTO",
869 Self::Tunisia => "TUN",
870 Self::UnitedArabEmirates => "UAE",
871 Self::Uganda => "UGA",
872 Self::Ukraine => "UKR",
873 Self::Unknown => "UNK",
874 Self::Uruguay => "URU",
875 Self::UnitedStatesOfAmerica => "USA",
876 Self::Uzbekistan => "UZB",
877 Self::Venezuela => "VEN",
878 Self::BritishVirginIslands => "VGB",
879 Self::Vietnam => "VIE",
880 Self::USVirginIslands => "VUS",
881 Self::Wales => "WLS",
882 Self::Yemen => "YEM",
883 Self::Zambia => "ZAM",
884 Self::Zimbabwe => "ZIM",
885 Self::Zaire => "ZRE",
886 };
887 write!(f, "{code}")
888 }
889}