Skip to main content

opql/types/
pql_board_range.rs

1use super::*;
2
3pub struct PQLBoardRange(pub(crate) FnCheckRange, RangeSrc, PQLGame);
4
5impl fmt::Debug for PQLBoardRange {
6    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7        f.debug_tuple("PQLBoardRange")
8            .field(&self.1)
9            .field(&self.2)
10            .finish()
11    }
12}
13
14impl PQLBoardRange {
15    #[inline]
16    pub fn is_satisfied(&self, cs: &[PQLCard]) -> bool {
17        (self.0)(cs)
18    }
19}
20
21/// # Panics
22/// `PQLBoardRange` ensures valid range text
23impl Clone for PQLBoardRange {
24    fn clone(&self) -> Self {
25        (self.2, self.1.as_str()).try_into().unwrap()
26    }
27}
28
29#[cfg(test)]
30impl PQLBoardRange {
31    /// AK != KA but good for assertions in tests
32    pub fn src_eq(&self, other: &Self) -> bool {
33        self.1 == other.1 && self.2 == other.2
34    }
35}
36
37impl Default for PQLBoardRange {
38    fn default() -> Self {
39        Self(Box::new(|_| true), "*".into(), PQLGame::default())
40    }
41}
42
43impl TryFrom<(PQLGame, &str)> for PQLBoardRange {
44    type Error = PQLErrorKind;
45
46    fn try_from((game, src): (PQLGame, &str)) -> Result<Self, Self::Error> {
47        fn create_range<const SD: bool>(
48            checker: BoardRangeChecker<SD>,
49            src: &str,
50            game: PQLGame,
51        ) -> PQLBoardRange {
52            PQLBoardRange(
53                Box::new(move |cs: &[PQLCard]| checker.is_satisfied(cs)),
54                src.to_string(),
55                game,
56            )
57        }
58
59        if game == PQLGame::ShortDeck {
60            Ok(create_range(
61                BoardRangeChecker::<true>::from_src(src)?,
62                src,
63                game,
64            ))
65        } else {
66            Ok(create_range(
67                BoardRangeChecker::<false>::from_src(src)?,
68                src,
69                game,
70            ))
71        }
72    }
73}
74
75#[cfg(test)]
76pub mod tests {
77    use super::*;
78    use crate::*;
79
80    #[test]
81    fn test_debug() {
82        let range = PQLBoardRange::default();
83
84        assert_eq!(format!("{range:?}"), r#"PQLBoardRange("*", Holdem)"#);
85    }
86
87    #[test]
88    fn test_err() {
89        for game in [PQLGame::Holdem, PQLGame::Omaha, PQLGame::ShortDeck] {
90            let res = PQLBoardRange::try_from((game, "AAAAKK")).unwrap_err();
91
92            assert_eq!(
93                res,
94                RangeError::TooManyCardsInRange((0, "AAAAKK".len())).into()
95            );
96        }
97    }
98
99    #[quickcheck]
100    fn test_clone(cards: CardN<5, true>) {
101        let res = PQLBoardRange::try_from((PQLGame::default(), "BB")).unwrap();
102        let cloned = res.clone();
103
104        assert_eq!(
105            res.is_satisfied(cards.as_slice()),
106            cloned.is_satisfied(cards.as_slice()),
107        );
108
109        let res = PQLBoardRange::try_from((PQLGame::ShortDeck, "BB")).unwrap();
110        let cloned = res.clone();
111
112        assert_eq!(
113            res.is_satisfied(cards.as_slice()),
114            cloned.is_satisfied(cards.as_slice()),
115        );
116    }
117}