open_pql/base/
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
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use crate::*;
58
59    const W: Suit = Suit::S;
60    const X: Suit = Suit::H;
61    const Y: Suit = Suit::D;
62    const Z: Suit = Suit::C;
63
64    #[test]
65    fn test_suit_mapping() {
66        let mut mapping = SuitMapping::new();
67
68        let s0 = mapping.map_suit(Suit::H);
69        assert_eq!(s0, W);
70
71        let s1 = mapping.map_suit(Suit::S);
72        assert_eq!(s1, X);
73
74        let s0_again = mapping.map_suit(Suit::H);
75        assert_eq!(s0_again, W);
76
77        let s2 = mapping.map_suit(Suit::C);
78        assert_eq!(s2, Y);
79
80        let s3 = mapping.map_suit(Suit::D);
81        assert_eq!(s3, Z);
82
83        assert_eq!(mapping.len(), 4);
84
85        mapping.clear();
86        assert_eq!(mapping.len(), 0);
87        assert!(mapping.is_empty());
88    }
89}