open_pql/base/isomorphic/
suit_mapping.rs

1use super::Suit;
2
3/// Maps original suits to isomorphic suits for normalization
4#[derive(Clone, Debug, Default)]
5pub struct SuitMapping {
6    map: [Option<Suit>; 4],
7    next_suit: Suit,
8}
9
10impl SuitMapping {
11    /// Creates a new empty suit mapping
12    pub const fn new() -> Self {
13        Self {
14            map: [None; 4],
15            next_suit: Suit::S,
16        }
17    }
18
19    /// Maps a suit to its isomorphic equivalent, creating a new mapping if needed
20    pub const fn map_suit(&mut self, suit: Suit) -> Suit {
21        let idx = suit as usize;
22        if let Some(iso_suit) = self.map[idx] {
23            return iso_suit;
24        }
25
26        let iso_suit = self.next_suit;
27        self.map[idx] = Some(iso_suit);
28        self.next_suit = match self.next_suit {
29            Suit::S => Suit::H,
30            Suit::H => Suit::D,
31            Suit::D | Suit::C => Suit::C,
32        };
33
34        iso_suit
35    }
36
37    /// Returns the number of suits that have been mapped
38    pub fn len(&self) -> usize {
39        self.map.iter().filter(|&&s| s.is_some()).count()
40    }
41
42    /// Returns true if no suits have been mapped
43    pub fn is_empty(&self) -> bool {
44        self.map.iter().all(|&s| s.is_none())
45    }
46
47    /// Clears all mappings
48    pub fn clear(&mut self) {
49        self.map = [None; 4];
50        self.next_suit = Suit::default();
51    }
52
53    #[cfg(test)]
54    pub const fn no_map() -> Self {
55        let mut mapping = Self::new();
56        mapping.map_suit(Suit::S);
57        mapping.map_suit(Suit::H);
58        mapping.map_suit(Suit::D);
59        mapping.map_suit(Suit::C);
60        mapping
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    const W: Suit = Suit::S;
69    const X: Suit = Suit::H;
70    const Y: Suit = Suit::D;
71    const Z: Suit = Suit::C;
72
73    #[test]
74    fn test_suit_mapping() {
75        let mut mapping = SuitMapping::new();
76
77        let s0 = mapping.map_suit(Suit::H);
78        assert_eq!(s0, W);
79
80        let s1 = mapping.map_suit(Suit::S);
81        assert_eq!(s1, X);
82
83        let s0_again = mapping.map_suit(Suit::H);
84        assert_eq!(s0_again, W);
85
86        let s2 = mapping.map_suit(Suit::C);
87        assert_eq!(s2, Y);
88
89        let s3 = mapping.map_suit(Suit::D);
90        assert_eq!(s3, Z);
91
92        assert_eq!(mapping.len(), 4);
93
94        mapping.clear();
95        assert_eq!(mapping.len(), 0);
96        assert!(mapping.is_empty());
97    }
98}