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::Omaha5 => Ok(create_range(
68                RangeChecker::<5, false>::from_src(src)?,
69                src,
70                game,
71            )),
72            PQLGame::ShortDeck => Ok(create_range(
73                RangeChecker::<2, true>::from_src(src)?,
74                src,
75                game,
76            )),
77        }
78    }
79}
80
81#[cfg(test)]
82pub mod tests {
83    use super::*;
84    use crate::*;
85
86    #[test]
87    fn test_err() {
88        for game in [PQLGame::Holdem, PQLGame::Omaha, PQLGame::ShortDeck] {
89            let res = PQLRange::try_from((game, "AAAAK")).unwrap_err();
90
91            assert_eq!(
92                res,
93                RangeError::TooManyCardsInRange((0, "AAAAK".len())).into()
94            );
95        }
96    }
97
98    #[quickcheck]
99    fn test_clone(cards: CardN<2, true>) {
100        let res = PQLRange::try_from((PQLGame::default(), "BB")).unwrap();
101        let cloned = res.clone();
102
103        assert_eq!(
104            res.is_satisfied(cards.as_slice()),
105            cloned.is_satisfied(cards.as_slice()),
106        );
107    }
108}