openpql_prelude/card/
card_idx.rs

1use super::{Card, Idx, RankIdx, SuitIdx};
2
3/// Card index representation.
4///
5/// Converts cards to unique numeric indices (0-51).
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7pub struct CardIdx(pub(crate) Idx);
8
9impl CardIdx {
10    pub const fn to_card(self) -> Option<Card> {
11        match (RankIdx(self.0 / 4).to_rank(), SuitIdx(self.0 % 4).to_suit()) {
12            (Some(r), Some(s)) => Some(Card::new(r, s)),
13            _ => None,
14        }
15    }
16}
17
18impl From<Card> for CardIdx {
19    fn from(card: Card) -> Self {
20        let idx_rank = RankIdx::from(card.rank).0;
21        let idx_suit = SuitIdx::from(card.suit).0;
22
23        Self(idx_rank * 4 + idx_suit)
24    }
25}
26
27#[cfg(test)]
28#[cfg_attr(coverage_nightly, coverage(off))]
29mod tests {
30    use super::*;
31
32    #[test]
33    #[allow(clippy::cast_possible_wrap)]
34    fn test_from_card() {
35        for i in 0..Card::N_CARDS {
36            assert_eq!(
37                CardIdx::from(Card::all::<false>()[i as usize]).0,
38                i as Idx
39            );
40        }
41    }
42
43    #[test]
44    #[allow(clippy::cast_possible_wrap)]
45    fn test_to_card() {
46        for i in 0..Card::N_CARDS {
47            assert_eq!(
48                CardIdx(i as Idx).to_card().unwrap(),
49                Card::all::<false>()[i as usize]
50            );
51        }
52
53        assert!(CardIdx(-1).to_card().is_none());
54        assert!(CardIdx(53).to_card().is_none());
55    }
56}