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}