opql/types/
pql_range.rs

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