Skip to main content

manabrew_engine/staticability/
static_ability_mode.rs

1//! Parsing helpers for `StaticMode`. Mirrors Java
2//! `StaticAbilityMode.smartValueOf` / `setValueOf`.
3
4pub use crate::staticability::StaticMode;
5
6/// Mirrors Java `StaticAbilityMode.smartValueOf(value)`. Case-insensitive
7/// (Java uses `compareToIgnoreCase`); unrecognised values are returned as
8/// `StaticMode::Other(<original casing>)` rather than throwing.
9pub fn smart_value_of(value: &str) -> StaticMode {
10    value.trim().parse().unwrap_or_else(|_| {
11        // StaticMode derives `EnumString` with a default `Other(String)` variant,
12        // so this is only a defensive fallback if that derive contract changes.
13        StaticMode::Other(value.trim().to_string())
14    })
15}
16
17/// Mirrors Java `StaticAbilityMode.setValueOf(values)`: split on `[, ]+`,
18/// dedup while preserving order.
19pub fn set_value_of(values: &str) -> Vec<StaticMode> {
20    let mut out: Vec<StaticMode> = Vec::new();
21    for token in values
22        .split(|c: char| c == ',' || c.is_whitespace())
23        .map(str::trim)
24        .filter(|s| !s.is_empty())
25    {
26        let parsed = smart_value_of(token);
27        if !out.contains(&parsed) {
28            out.push(parsed);
29        }
30    }
31    out
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn smart_value_of_known_modes() {
40        assert_eq!(smart_value_of("Continuous"), StaticMode::Continuous);
41        assert_eq!(smart_value_of("CantAttack"), StaticMode::CantAttack);
42        assert_eq!(smart_value_of("RaiseCost"), StaticMode::RaiseCost);
43    }
44
45    #[test]
46    fn smart_value_of_is_case_insensitive() {
47        assert_eq!(smart_value_of("continuous"), StaticMode::Continuous);
48        assert_eq!(smart_value_of("CANTATTACK"), StaticMode::CantAttack);
49        assert_eq!(smart_value_of("RaIsEcOsT"), StaticMode::RaiseCost);
50    }
51
52    #[test]
53    fn smart_value_of_unknown_keeps_original_casing() {
54        assert_eq!(
55            smart_value_of("Whatever"),
56            StaticMode::Other("Whatever".to_string())
57        );
58    }
59
60    #[test]
61    fn smart_value_of_recognises_late_added_java_modes() {
62        assert_eq!(smart_value_of("OptionalCost"), StaticMode::OptionalCost);
63        assert_eq!(
64            smart_value_of("PlayerMustAttack"),
65            StaticMode::PlayerMustAttack
66        );
67        assert_eq!(
68            smart_value_of("AttackRequirement"),
69            StaticMode::AttackRequirement
70        );
71    }
72
73    #[test]
74    fn set_value_of_comma() {
75        assert_eq!(
76            set_value_of("CantAttack,CantBlock"),
77            vec![StaticMode::CantAttack, StaticMode::CantBlock]
78        );
79    }
80
81    #[test]
82    fn set_value_of_space() {
83        assert_eq!(
84            set_value_of("CantAttack CantBlock"),
85            vec![StaticMode::CantAttack, StaticMode::CantBlock]
86        );
87    }
88
89    #[test]
90    fn set_value_of_three_modes() {
91        assert_eq!(
92            set_value_of("CantAttack,CantBlock,CantBeActivated"),
93            vec![
94                StaticMode::CantAttack,
95                StaticMode::CantBlock,
96                StaticMode::CantBeActivated,
97            ]
98        );
99    }
100
101    #[test]
102    fn set_value_of_continuous_combo() {
103        assert_eq!(
104            set_value_of("Continuous,CantPlayLand,CantBeCast"),
105            vec![
106                StaticMode::Continuous,
107                StaticMode::CantPlayLand,
108                StaticMode::CantBeCast,
109            ]
110        );
111    }
112
113    #[test]
114    fn set_value_of_preserves_unknown_per_token() {
115        assert_eq!(
116            set_value_of("CantAttack,Bogus"),
117            vec![
118                StaticMode::CantAttack,
119                StaticMode::Other("Bogus".to_string()),
120            ]
121        );
122    }
123
124    #[test]
125    fn set_value_of_dedups() {
126        assert_eq!(
127            set_value_of("CantAttack,CantAttack"),
128            vec![StaticMode::CantAttack]
129        );
130    }
131}