Skip to main content

openpql_range_parser/ast/
suit.rs

1use super::{Error, LocInfo, ResultE};
2
3pub type SuitConst = openpql_prelude::Suit;
4
5/// Single-letter suit variable token.
6#[derive(Copy, Clone, PartialEq, Eq, Debug, derive_more::Display)]
7pub enum SuitVar {
8    /// Suit variable "w".
9    #[display("w")]
10    W,
11    /// Suit variable "x".
12    #[display("x")]
13    X,
14    /// Suit variable "y".
15    #[display("y")]
16    Y,
17    /// Suit variable "z".
18    #[display("z")]
19    Z,
20}
21
22/// Suit slot in a range card: concrete or variable.
23#[derive(Copy, Clone, PartialEq, Eq, Debug, derive_more::Display)]
24pub enum CardSuit {
25    /// Concrete suit.
26    #[display("{_0}")]
27    Const(SuitConst),
28    /// Suit variable.
29    #[display("{_0}")]
30    Var(SuitVar),
31}
32
33impl CardSuit {
34    pub(crate) fn from_token(c: char, loc: LocInfo) -> ResultE<'static, Self> {
35        match c {
36            's' | 'S' => Ok(Self::Const(SuitConst::S)),
37            'h' | 'H' => Ok(Self::Const(SuitConst::H)),
38            'd' | 'D' => Ok(Self::Const(SuitConst::D)),
39            'c' | 'C' => Ok(Self::Const(SuitConst::C)),
40
41            'w' | 'W' => Ok(Self::Var(SuitVar::W)),
42            'x' | 'X' => Ok(Self::Var(SuitVar::X)),
43            'y' | 'Y' => Ok(Self::Var(SuitVar::Y)),
44            'z' | 'Z' => Ok(Self::Var(SuitVar::Z)),
45
46            _ => Err(Error::InvalidSuit(loc).into()),
47        }
48    }
49}
50
51#[cfg(test)]
52pub mod tests {
53    use super::*;
54    use crate::*;
55
56    impl Arbitrary for SuitVar {
57        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
58            *g.choose(&[Self::W, Self::X, Self::Y, Self::Z]).unwrap()
59        }
60    }
61
62    #[test]
63    fn test_card_suit_const() {
64        assert_range_card("S", "s");
65        assert_range_card("H", "h");
66        assert_range_card("D", "d");
67        assert_range_card("C", "c");
68
69        assert_range_card("s", "s");
70        assert_range_card("h", "h");
71        assert_range_card("d", "d");
72        assert_range_card("c", "c");
73    }
74
75    #[test]
76    fn test_card_suit_var() {
77        assert_range_card("W", "w");
78        assert_range_card("X", "x");
79        assert_range_card("Y", "y");
80        assert_range_card("Z", "z");
81
82        assert_range_card("w", "w");
83        assert_range_card("x", "x");
84        assert_range_card("y", "y");
85        assert_range_card("z", "z");
86    }
87
88    #[test]
89    fn test_from_token() {
90        // unreachable
91        assert![CardSuit::from_token('?', (0, 1)).is_err()];
92    }
93}