openpql_range_parser/ast/
card.rs1use super::{CardRank, CardSuit, From, RankConst, RankVar, SuitConst, SuitVar};
2
3#[derive(Copy, Clone, PartialEq, Eq, Debug, derive_more::Display)]
5pub enum RangeCard {
6 #[display("{_0}{_1}")]
8 CC(RankConst, SuitConst),
9 #[display("{_0}{_1}")]
11 CV(RankConst, SuitVar),
12 #[display("{_0}")]
14 CA(RankConst),
15 #[display("{_0}{_1}")]
17 VC(RankVar, SuitConst),
18 #[display("{_0}{_1}")]
20 VV(RankVar, SuitVar),
21 #[display("{_0}")]
23 VA(RankVar),
24 #[display("{_0}")]
26 AC(SuitConst),
27 #[display("{_0}")]
29 AV(SuitVar),
30 #[display("*")]
32 AA,
33}
34
35impl From<(CardRank, CardSuit)> for RangeCard {
36 fn from(t: (CardRank, CardSuit)) -> Self {
37 match t {
38 (CardRank::Const(r), CardSuit::Const(s)) => Self::CC(r, s),
39 (CardRank::Const(r), CardSuit::Var(s)) => Self::CV(r, s),
40 (CardRank::Var(r), CardSuit::Const(s)) => Self::VC(r, s),
41 (CardRank::Var(r), CardSuit::Var(s)) => Self::VV(r, s),
42 (CardRank::Any, CardSuit::Const(s)) => Self::AC(s),
43 (CardRank::Any, CardSuit::Var(s)) => Self::AV(s),
44 }
45 }
46}
47
48impl From<CardRank> for RangeCard {
49 fn from(r: CardRank) -> Self {
50 match r {
51 CardRank::Const(c) => Self::CA(c),
52 CardRank::Var(v) => Self::VA(v),
53 CardRank::Any => Self::AA,
54 }
55 }
56}
57
58impl From<CardSuit> for RangeCard {
59 fn from(s: CardSuit) -> Self {
60 match s {
61 CardSuit::Const(c) => Self::AC(c),
62 CardSuit::Var(v) => Self::AV(v),
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use crate::*;
71
72 impl Arbitrary for RangeCard {
73 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
74 match *g.choose(&[0, 1, 2, 3, 4, 5, 6, 7, 8]).unwrap() {
75 0 => Self::CC(RankConst::arbitrary(g), SuitConst::arbitrary(g)),
76 1 => Self::CV(RankConst::arbitrary(g), SuitVar::arbitrary(g)),
77 2 => Self::CA(RankConst::arbitrary(g)),
78 3 => Self::VC(RankVar::arbitrary(g), SuitConst::arbitrary(g)),
79 4 => Self::VV(RankVar::arbitrary(g), SuitVar::arbitrary(g)),
80 5 => Self::VA(RankVar::arbitrary(g)),
81 6 => Self::AC(SuitConst::arbitrary(g)),
82 7 => Self::AV(SuitVar::arbitrary(g)),
83 _ => Self::AA,
84 }
85 }
86 }
87
88 #[test]
89 fn test_card_cc() {
90 assert_range_card("As", "As");
91 }
92
93 #[test]
94 fn test_card_cv() {
95 assert_range_card("Aw", "Aw");
96 }
97
98 #[test]
99 fn test_card_ca() {
100 assert_range_card("A", "A");
101 }
102
103 #[test]
104 fn test_card_vc() {
105 assert_range_card("Bs", "Bs");
106 }
107
108 #[test]
109 fn test_card_vv() {
110 assert_range_card("Bw", "Bw");
111 }
112
113 #[test]
114 fn test_card_va() {
115 assert_range_card("B", "B");
116 }
117
118 #[test]
119 fn test_card_ac() {
120 assert_range_card("s", "s");
121 assert_range_card("*s", "s");
122 }
123
124 #[test]
125 fn test_card_av() {
126 assert_range_card("w", "w");
127 assert_range_card("*w", "w");
128 }
129
130 #[test]
131 fn test_card_aa() {
132 assert_range_card("*", "*");
133 }
134
135 #[quickcheck]
136 fn test_shortdeck(card: RangeCard) {
137 let src = card.to_string();
138 if src.chars().any(|c| ['2', '3', '4', '5'].contains(&c)) {
139 assert!(parse_card_sd(&src).is_err());
140 } else {
141 assert_eq!(Ok(card), parse_card_sd(&src));
142 }
143 }
144
145 fn assert_range_card_sd_err(s: &str, expected: Error) {
146 assert_eq!(parse_card_sd(s), Err(expected.into()));
147 }
148
149 #[test]
150 fn test_shortdeck_error() {
151 assert_range_card_sd_err("2", Error::InvalidRank((0, 1)));
152 assert_range_card_sd_err("3", Error::InvalidRank((0, 1)));
153 assert_range_card_sd_err("4", Error::InvalidRank((0, 1)));
154 assert_range_card_sd_err("5", Error::InvalidRank((0, 1)));
155 }
156}