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_attr(coverage_nightly, coverage(off))]
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use crate::*;
65
66    #[test]
67    fn test_try_from() {
68        fn assert_ok<T>(v: &mut VmValue)
69        where
70            for<'a> &'a T: TryFrom<&'a VmValue, Error = PQLError>,
71            for<'a> &'a mut T: TryFrom<&'a mut VmValue, Error = PQLError>,
72        {
73            assert!(<&T>::try_from(&*v).is_ok());
74            assert!(<&mut T>::try_from(v).is_ok());
75        }
76        fn assert_err<T>(v: &mut VmValue)
77        where
78            for<'a> &'a T: TryFrom<&'a VmValue, Error = PQLError>,
79            for<'a> &'a mut T: TryFrom<&'a mut VmValue, Error = PQLError>,
80        {
81            assert!(<&T>::try_from(&*v).is_err());
82            assert!(<&mut T>::try_from(v).is_err());
83        }
84
85        let mut v1 = VmValue::Thin(VmStackValue::from(1 as PQLLong));
86        let mut v2 = VmValue::Thin(VmStackValue::from(0.0));
87        let mut v3 = VmValue::Str(PQLString::from(""));
88        let mut v4 = VmValue::Range(PQLRange::default());
89        let mut v5 = VmValue::BoardRange(PQLBoardRange::default());
90
91        assert_ok::<VmStackValue>(&mut v1);
92        assert_ok::<VmStackValueNum>(&mut v1);
93        assert_ok::<PQLLong>(&mut v1);
94        assert_ok::<PQLDouble>(&mut v2);
95        assert_ok::<PQLString>(&mut v3);
96        assert_ok::<PQLRange>(&mut v4);
97        assert_ok::<PQLBoardRange>(&mut v5);
98
99        assert_err::<VmStackValue>(&mut v5);
100        assert_err::<VmStackValueNum>(&mut v5);
101        assert_err::<PQLLong>(&mut v5);
102        assert_err::<PQLDouble>(&mut v5);
103        assert_err::<PQLString>(&mut v5);
104        assert_err::<PQLRange>(&mut v5);
105        assert_err::<PQLBoardRange>(&mut v4);
106    }
107}