Skip to main content

opql/types/
pql_range.rs

1use super::*;
2
3pub struct PQLRange(pub(crate) FnCheckRange, RangeSrc, PQLGame);
4
5impl fmt::Debug for PQLRange {
6    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7        f.debug_tuple("PQLRange")
8            .field(&self.1)
9            .field(&self.2)
10            .finish()
11    }
12}
13
14impl PQLRange {
15    #[inline]
16    pub fn is_satisfied(&self, cs: &[PQLCard]) -> bool {
17        (self.0)(cs)
18    }
19}
20
21/// # Panics
22/// `PQLRange` ensures valid range text
23impl Clone for PQLRange {
24    fn clone(&self) -> Self {
25        (self.2, self.1.as_str()).try_into().unwrap()
26    }
27}
28
29#[cfg(test)]
30impl PQLRange {
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 TryFrom<(PQLGame, &str)> for PQLRange {
38    type Error = PQLErrorKind;
39
40    fn try_from((game, src): (PQLGame, &str)) -> Result<Self, Self::Error> {
41        fn create_range<const N: usize, const SD: bool>(
42            checker: RangeChecker<N, SD>,
43            src: &str,
44            game: PQLGame,
45        ) -> PQLRange
46        where
47            [u8; N]: smallvec::Array<Item = u8>,
48        {
49            PQLRange(
50                Box::new(move |cs: &[PQLCard]| checker.is_satisfied(cs)),
51                src.to_string(),
52                game,
53            )
54        }
55
56        match game {
57            PQLGame::Holdem => Ok(create_range(
58                RangeChecker::<2, false>::from_src(src)?,
59                src,
60                game,
61            )),
62            PQLGame::Omaha => Ok(create_range(
63                RangeChecker::<4, false>::from_src(src)?,
64                src,
65                game,
66            )),
67            PQLGame::ShortDeck => Ok(create_range(
68                RangeChecker::<2, true>::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 = PQLRange::try_from((game, "AAAAK")).unwrap_err();
85
86            assert_eq!(
87                res,
88                RangeError::TooManyCardsInRange((0, "AAAAK".len())).into()
89            );
90        }
91    }
92
93    #[quickcheck]
94    fn test_clone(cards: CardN<2, true>) {
95        let res = PQLRange::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}