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