Skip to main content

tiger_tables/
game.rs

1//! Dealing with which game we are validating
2
3use std::sync::OnceLock;
4
5/// Records at runtime which game we are validating, in case there are multiple feature flags set.
6static GAME: OnceLock<Game> = OnceLock::new();
7
8/// Enum specifying which game we are validating.
9///
10/// This enum is meant to be optimized away entirely when there is only one feature flag set.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum Game {
13    #[cfg(feature = "ck3")]
14    Ck3,
15    #[cfg(feature = "vic3")]
16    Vic3,
17    #[cfg(feature = "imperator")]
18    Imperator,
19    #[cfg(feature = "eu5")]
20    Eu5,
21    #[cfg(feature = "hoi4")]
22    Hoi4,
23}
24
25impl Game {
26    /// Decide which game we are validating. Should be called as early as possible.
27    /// Returns an error if called more than once.
28    pub fn set(game: Game) -> Result<(), String> {
29        GAME.set(game).map_err(|_| "tried to set game type twice".to_string())?;
30        Ok(())
31    }
32
33    /// Return which game we are validating. Should only be called after [`Game::set`].
34    ///
35    /// ## Panics
36    /// May panic if called before [`Game::set`].
37    #[allow(clippy::self_named_constructors)] // not a constructor
38    #[allow(unreachable_code)]
39    pub fn game() -> Game {
40        #[cfg(all(
41            feature = "ck3",
42            not(feature = "vic3"),
43            not(feature = "imperator"),
44            not(feature = "eu5"),
45            not(feature = "hoi4")
46        ))]
47        return Game::Ck3;
48        #[cfg(all(
49            feature = "vic3",
50            not(feature = "ck3"),
51            not(feature = "imperator"),
52            not(feature = "eu5"),
53            not(feature = "hoi4")
54        ))]
55        return Game::Vic3;
56        #[cfg(all(
57            feature = "imperator",
58            not(feature = "ck3"),
59            not(feature = "vic3"),
60            not(feature = "eu5"),
61            not(feature = "hoi4")
62        ))]
63        return Game::Imperator;
64        #[cfg(all(
65            feature = "hoi4",
66            not(feature = "ck3"),
67            not(feature = "vic3"),
68            not(feature = "imperator"),
69            not(feature = "eu5"),
70        ))]
71        return Game::Hoi4;
72        #[cfg(all(
73            feature = "eu5",
74            not(feature = "ck3"),
75            not(feature = "vic3"),
76            not(feature = "imperator"),
77            not(feature = "hoi4"),
78        ))]
79        return Game::Eu5;
80        *GAME.get().expect("internal error: don't know which game we are validating")
81    }
82
83    /// Convenience function indicating whether we are validating Crusader Kings 3 mods.
84    #[inline]
85    pub fn is_ck3() -> bool {
86        #[cfg(not(feature = "ck3"))]
87        return false;
88        #[cfg(all(
89            feature = "ck3",
90            not(feature = "vic3"),
91            not(feature = "imperator"),
92            not(feature = "eu5"),
93            not(feature = "hoi4")
94        ))]
95        return true;
96        #[cfg(all(
97            feature = "ck3",
98            any(feature = "vic3", feature = "imperator", feature = "eu5", feature = "hoi4")
99        ))]
100        return GAME.get() == Some(&Game::Ck3);
101    }
102
103    /// Convenience function indicating whether we are validating Victoria 3 mods.
104    #[inline]
105    pub fn is_vic3() -> bool {
106        #[cfg(not(feature = "vic3"))]
107        return false;
108        #[cfg(all(
109            feature = "vic3",
110            not(feature = "ck3"),
111            not(feature = "imperator"),
112            not(feature = "eu5"),
113            not(feature = "hoi4")
114        ))]
115        return true;
116        #[cfg(all(
117            feature = "vic3",
118            any(feature = "ck3", feature = "imperator", feature = "eu5", feature = "hoi4")
119        ))]
120        return GAME.get() == Some(&Game::Vic3);
121    }
122
123    /// Convenience function indicating whether we are validating Imperator: Rome mods.
124    #[inline]
125    pub fn is_imperator() -> bool {
126        #[cfg(not(feature = "imperator"))]
127        return false;
128        #[cfg(all(
129            feature = "imperator",
130            not(feature = "ck3"),
131            not(feature = "vic3"),
132            not(feature = "eu5"),
133            not(feature = "hoi4")
134        ))]
135        return true;
136        #[cfg(all(
137            feature = "imperator",
138            any(feature = "ck3", feature = "vic3", feature = "hoi4", feature = "eu5")
139        ))]
140        return GAME.get() == Some(&Game::Imperator);
141    }
142
143    /// Convenience function indicating whether we are validating Europa Universalis 5 mods.
144    #[inline]
145    pub fn is_eu5() -> bool {
146        #[cfg(not(feature = "eu5"))]
147        return false;
148        #[cfg(all(
149            feature = "eu5",
150            not(feature = "ck3"),
151            not(feature = "vic3"),
152            not(feature = "imperator"),
153            not(feature = "hoi4")
154        ))]
155        return true;
156        #[cfg(all(
157            feature = "eu5",
158            any(feature = "ck3", feature = "vic3", feature = "hoi4", feature = "imperator")
159        ))]
160        return GAME.get() == Some(&Game::Eu5);
161    }
162
163    /// Convenience function indicating whether we are validating one of the newer games
164    /// which use the Jomini scripting engine.
165    #[inline]
166    pub fn is_jomini() -> bool {
167        Game::is_ck3() || Game::is_vic3() || Game::is_imperator() || Game::is_eu5()
168    }
169
170    /// Convenience function indicating whether we are validating Hearts of Iron 4 mods.
171    #[inline]
172    pub fn is_hoi4() -> bool {
173        #[cfg(not(feature = "hoi4"))]
174        return false;
175        #[cfg(all(
176            feature = "hoi4",
177            not(feature = "ck3"),
178            not(feature = "vic3"),
179            not(feature = "imperator"),
180            not(feature = "eu5")
181        ))]
182        return true;
183        #[cfg(all(
184            feature = "hoi4",
185            any(feature = "ck3", feature = "vic3", feature = "imperator", feature = "eu5")
186        ))]
187        return GAME.get() == Some(&Game::Hoi4);
188    }
189}