open_pql/vm/
value.rs

1use super::*;
2
3#[derive(Debug, Clone, From, TryInto)]
4pub enum VmValue {
5    Thin(VmStackValue),
6    Range(PQLRange),
7    BoardRange(PQLBoardRange),
8    Str(PQLString),
9}
10
11mod try_from {
12    use VmValue::{BoardRange, Range, Str, Thin};
13
14    use super::*;
15
16    macro_rules! impl_try_from {
17        ($to:ty, $pattern:pat => $value:expr) => {
18            impl<'a> TryFrom<&'a VmValue> for &'a $to {
19                type Error = PQLError;
20
21                fn try_from(value: &'a VmValue) -> Result<Self, Self::Error> {
22                    match value {
23                        $pattern => Ok($value),
24                        _ => Err(InternalError::InvalidVmValue.into()),
25                    }
26                }
27            }
28
29            impl<'a> TryFrom<&'a mut VmValue> for &'a mut $to {
30                type Error = PQLError;
31
32                fn try_from(
33                    value: &'a mut VmValue,
34                ) -> Result<Self, Self::Error> {
35                    match value {
36                        $pattern => Ok($value),
37                        _ => Err(InternalError::InvalidVmValue.into()),
38                    }
39                }
40            }
41        };
42    }
43
44    impl_try_from!(VmStackValue, Thin(v) => v);
45    impl_try_from!(VmStackValueNum, Thin(VmStackValue::Num(v)) => v);
46
47    impl_try_from!(PQLRange, Range(r) => r);
48    impl_try_from!(PQLBoardRange, BoardRange(r) => r);
49    impl_try_from!(PQLString, Str(r) => r);
50
51    impl_try_from!(PQLLong, Thin(VmStackValue::Num(VmStackValueNum::Long(v))) => v);
52    impl_try_from!(PQLDouble, Thin(VmStackValue::Num(VmStackValueNum::Double(v))) => v);
53    impl_try_from!(PQLCardCount, Thin(VmStackValue::Num(VmStackValueNum::CardCount(v))) => v);
54
55    impl_try_from!(PQLHandType, Thin(VmStackValue::HandType(v)) => v);
56    impl_try_from!(PQLFlopHandCategory, Thin(VmStackValue::FlopCategory(v)) => v);
57    impl_try_from!(PQLHiRating, Thin(VmStackValue::Rating(v)) => v);
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use crate::*;
64
65    #[test]
66    fn test_try_from() {
67        fn assert_ok<T>(v: &mut VmValue)
68        where
69            for<'a> &'a T: TryFrom<&'a VmValue, Error = PQLError>,
70            for<'a> &'a mut T: TryFrom<&'a mut VmValue, Error = PQLError>,
71        {
72            assert!(<&T>::try_from(&*v).is_ok());
73            assert!(<&mut T>::try_from(v).is_ok());
74        }
75        fn assert_err<T>(v: &mut VmValue)
76        where
77            for<'a> &'a T: TryFrom<&'a VmValue, Error = PQLError>,
78            for<'a> &'a mut T: TryFrom<&'a mut VmValue, Error = PQLError>,
79        {
80            assert!(<&T>::try_from(&*v).is_err());
81            assert!(<&mut T>::try_from(v).is_err());
82        }
83
84        let mut v1 = VmValue::Thin(VmStackValue::from(1 as PQLLong));
85        let mut v2 = VmValue::Thin(VmStackValue::from(0.0));
86        let mut v3 = VmValue::Str(PQLString::from(""));
87        let mut v4 = VmValue::Range(PQLRange::default());
88        let mut v5 = VmValue::BoardRange(PQLBoardRange::default());
89
90        assert_ok::<VmStackValue>(&mut v1);
91        assert_ok::<VmStackValueNum>(&mut v1);
92        assert_ok::<PQLLong>(&mut v1);
93        assert_ok::<PQLDouble>(&mut v2);
94        assert_ok::<PQLString>(&mut v3);
95        assert_ok::<PQLRange>(&mut v4);
96        assert_ok::<PQLBoardRange>(&mut v5);
97
98        assert_err::<VmStackValue>(&mut v5);
99        assert_err::<VmStackValueNum>(&mut v5);
100        assert_err::<PQLLong>(&mut v5);
101        assert_err::<PQLDouble>(&mut v5);
102        assert_err::<PQLString>(&mut v5);
103        assert_err::<PQLRange>(&mut v5);
104        assert_err::<PQLBoardRange>(&mut v4);
105    }
106}