openpql_prelude/card/
suit_mapping.rs

1use super::Suit;
2
3/// Suit mapping for isomorphic transformations.
4///
5/// Tracks and applies suit transformations during isomorphic hand generation.
6#[derive(Clone, Debug, Default)]
7pub struct SuitMapping {
8    map: [Option<Suit>; Suit::N_SUITS as usize],
9    next_suit: Suit,
10}
11
12impl SuitMapping {
13    /// Creates a new empty suit mapping.
14    pub const fn new() -> Self {
15        Self {
16            map: [None; Suit::N_SUITS as usize],
17            next_suit: Suit::S,
18        }
19    }
20
21    /// Maps a suit to its isomorphic equivalent, creating a new mapping if needed.
22    pub const fn map_suit(&mut self, suit: Suit) -> Suit {
23        let idx = suit as usize;
24        if let Some(iso_suit) = self.map[idx] {
25            return iso_suit;
26        }
27
28        let iso_suit = self.next_suit;
29        self.map[idx] = Some(iso_suit);
30        self.advance_suit();
31
32        iso_suit
33    }
34
35    /// Returns the number of suits that have been mapped.
36    pub fn len(&self) -> usize {
37        self.map.iter().filter(|&&s| s.is_some()).count()
38    }
39
40    /// Returns `true` if no suits have been mapped.
41    pub fn is_empty(&self) -> bool {
42        self.map.iter().all(|&s| s.is_none())
43    }
44
45    const fn advance_suit(&mut self) {
46        self.next_suit = match self.next_suit {
47            Suit::S => Suit::H,
48            Suit::H => Suit::D,
49            _ => Suit::C,
50        };
51    }
52}
53
54#[cfg(test)]
55#[cfg_attr(coverage_nightly, coverage(off))]
56mod tests {
57    use super::*;
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        assert_eq!(mapping.len(), 0);
69        assert!(mapping.is_empty());
70
71        let suits = [Suit::H, Suit::S, Suit::H, Suit::C, Suit::D];
72        let mapped = suits.map(|suit| mapping.map_suit(suit));
73
74        assert_eq!(mapped, [W, X, W, Y, Z]);
75
76        assert_eq!(mapping.len(), 4);
77    }
78}