Skip to main content

tiger_lib/
game.rs

1//! Dealing with which game we are validating
2
3use std::fmt::{Display, Formatter};
4
5use bitflags::bitflags;
6
7pub use tiger_tables::game::Game;
8
9use crate::helpers::display_choices;
10
11bitflags! {
12    /// A set of bitflags to indicate for which game something is intended,
13    /// independent of which game we are validating.
14    ///
15    /// This way, error messages about things being used in the wrong game can be given at runtime.
16    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17    pub struct GameFlags: u8 {
18        const Ck3 = 0x01;
19        const Vic3 = 0x02;
20        const Imperator = 0x04;
21        const Eu5 = 0x08;
22        const Hoi4 = 0x10;
23    }
24}
25
26impl GameFlags {
27    /// Get a [`GameFlags`] value representing the game being validated.
28    /// Useful for checking with `.contains`.
29    pub fn game() -> Self {
30        // Unfortunately we have to translate between the types here.
31        match Game::game() {
32            #[cfg(feature = "ck3")]
33            Game::Ck3 => GameFlags::Ck3,
34            #[cfg(feature = "vic3")]
35            Game::Vic3 => GameFlags::Vic3,
36            #[cfg(feature = "imperator")]
37            Game::Imperator => GameFlags::Imperator,
38            #[cfg(feature = "eu5")]
39            Game::Eu5 => GameFlags::Eu5,
40            #[cfg(feature = "hoi4")]
41            Game::Hoi4 => GameFlags::Hoi4,
42        }
43    }
44
45    pub const fn jomini() -> Self {
46        GameFlags::Ck3.union(GameFlags::Vic3).union(GameFlags::Imperator).union(GameFlags::Eu5)
47    }
48}
49
50impl Display for GameFlags {
51    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
52        let mut vec = Vec::new();
53        if self.contains(Self::Ck3) {
54            vec.push("Crusader Kings 3");
55        }
56        if self.contains(Self::Vic3) {
57            vec.push("Victoria 3");
58        }
59        if self.contains(Self::Imperator) {
60            vec.push("Imperator: Rome");
61        }
62        if self.contains(Self::Eu5) {
63            vec.push("Europa Universalis 5");
64        }
65        if self.contains(Self::Hoi4) {
66            vec.push("Hearts of Iron 4");
67        }
68        display_choices(f, &vec, "and")
69    }
70}
71
72impl From<Game> for GameFlags {
73    /// Convert a [`Game`] into a [`GameFlags`] with just that game's flag set.
74    fn from(game: Game) -> Self {
75        match game {
76            #[cfg(feature = "ck3")]
77            Game::Ck3 => GameFlags::Ck3,
78            #[cfg(feature = "vic3")]
79            Game::Vic3 => GameFlags::Vic3,
80            #[cfg(feature = "imperator")]
81            Game::Imperator => GameFlags::Imperator,
82            #[cfg(feature = "eu5")]
83            Game::Eu5 => GameFlags::Eu5,
84            #[cfg(feature = "hoi4")]
85            Game::Hoi4 => GameFlags::Hoi4,
86        }
87    }
88}