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}