opql/types/
pql_board_range.rs

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