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