opql/types/
pql_type.rs

1use super::*;
2
3macro_rules! union {
4    ($single:ident) => {
5        PQLType::$single.bits()
6    };
7    ($first:ident, $($rest:ident),+) => {
8        PQLType::$first.bits() | union!($($rest),+)
9    };
10}
11
12bitflags! {
13  #[derive(Clone, Copy, Debug, PartialEq, Eq, Display)]
14  pub struct PQLType: u32 {
15    const BOARDRANGE = 1;
16    const BOOLEAN = 1 << 1;
17    const CARD = 1 << 2;
18    const CARDCOUNT = 1 << 3;
19    const DOUBLE = 1 << 4;
20    const EQUITY = union!(DOUBLE);
21    const FLOPHANDCATEGORY = 1 << 6;
22    const FRACTION = 1 << 7;
23    const HANDRANKING = 1 << 8;
24    const HANDTYPE = 1 << 9;
25    const HIRATING = 1 << 10;
26    const INTEGER = union!(LONG);
27    const LONG = 1 << 12;
28    const LORATING = 1 << 13;
29    const NUMERIC = union!(CARDCOUNT, LONG, DOUBLE, FRACTION);
30    const PLAYER = 1 << 15;
31    const PLAYERCOUNT = union!(CARDCOUNT);
32    const RANGE = 1 << 17;
33    const RANK = 1 << 18;
34    const RANKSET = 1 << 19;
35    const STREET = 1 << 20;
36    const STRING = 1 << 21;
37  }
38}
39
40impl PQLType {
41    pub const fn is_num(self) -> bool {
42        Self::NUMERIC.contains(self)
43    }
44
45    pub const fn is_concrete(self) -> bool {
46        self.bits().is_power_of_two()
47    }
48}
49
50impl From<ast::SelectorKind> for PQLType {
51    fn from(sel: ast::SelectorKind) -> Self {
52        match sel {
53            ast::SelectorKind::Avg => Self::NUMERIC,
54            ast::SelectorKind::Count => Self::BOOLEAN,
55            ast::SelectorKind::Max | ast::SelectorKind::Min => {
56                Self::NUMERIC
57                    | Self::FLOPHANDCATEGORY
58                    | Self::HANDTYPE
59                    | Self::HIRATING
60                    | Self::RANK
61            }
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use crate::*;
70
71    #[test]
72    fn test_type_alias() {
73        assert_eq!(PQLType::PLAYERCOUNT, PQLType::CARDCOUNT);
74        assert_eq!(PQLType::INTEGER, PQLType::LONG);
75        assert_eq!(PQLType::EQUITY, PQLType::DOUBLE);
76    }
77
78    #[test]
79    fn test_type_num() {
80        for tp in [
81            PQLType::PLAYERCOUNT,
82            PQLType::CARDCOUNT,
83            PQLType::INTEGER,
84            PQLType::LONG,
85            PQLType::EQUITY,
86            PQLType::DOUBLE,
87            PQLType::FRACTION,
88        ] {
89            assert!(PQLType::NUMERIC.contains(tp));
90        }
91    }
92
93    #[test]
94    fn test_type_for_selector() {
95        use ast::SelectorKind::*;
96        fn assert_match(sel: ast::SelectorKind, kind: PQLType) {
97            assert!(PQLType::from(sel).contains(kind));
98        }
99        fn assert_match_max_min(kind: PQLType) {
100            assert_match(Max, kind);
101            assert_match(Min, kind);
102        }
103
104        assert_match(Avg, PQLType::CARDCOUNT);
105        assert_match(Avg, PQLType::LONG);
106        assert_match(Avg, PQLType::FRACTION);
107        assert_match(Avg, PQLType::DOUBLE);
108
109        assert_match(Count, PQLType::BOOLEAN);
110
111        assert_match_max_min(PQLType::CARDCOUNT);
112        assert_match_max_min(PQLType::LONG);
113        assert_match_max_min(PQLType::FRACTION);
114        assert_match_max_min(PQLType::DOUBLE);
115        assert_match_max_min(PQLType::FLOPHANDCATEGORY);
116        assert_match_max_min(PQLType::HANDTYPE);
117        assert_match_max_min(PQLType::HIRATING);
118        assert_match_max_min(PQLType::RANK);
119    }
120}