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
22impl 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 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}