1use super::*;
2
3#[derive(Debug, Clone, Default)]
4pub struct VmStore {
5 pub(crate) inner: Vec<VmValue>,
6}
7
8impl VmStore {
9 pub fn try_push(&mut self, v: VmValue) -> Result<VmStoreVarIdx, PQLError> {
10 let idx = self.inner.len().try_into()?;
11
12 self.inner.push(v);
13
14 Ok(idx)
15 }
16
17 fn get(&self, i: VmStoreVarIdx) -> &VmValue {
18 &self.inner[i.to_usize()]
19 }
20
21 fn get_mut(&mut self, i: VmStoreVarIdx) -> &mut VmValue {
22 &mut self.inner[i.to_usize()]
23 }
24
25 pub fn downcast_get<'a, T>(
26 &'a self,
27 i: VmStoreVarIdx,
28 ) -> Result<T, PQLError>
29 where
30 T: TryFrom<&'a VmValue>,
31 {
32 T::try_from(self.get(i))
33 .map_or_else(|_| Err(InternalError::InvalidVmValue.into()), Ok)
34 }
35
36 pub fn downcast_get_mut<'a, T>(
37 &'a mut self,
38 i: VmStoreVarIdx,
39 ) -> Result<T, PQLError>
40 where
41 T: TryFrom<&'a mut VmValue>,
42 {
43 T::try_from(self.get_mut(i))
44 .map_or_else(|_| Err(InternalError::InvalidVmValue.into()), Ok)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::*;
52
53 impl VmStore {
54 pub fn new_packed() -> Self {
55 Self {
56 inner: vec![
57 VmStackValue::from(PQLStreet::default()).into();
58 u8::MAX as usize + 1
59 ],
60 }
61 }
62 }
63
64 #[test]
65 fn test_try_push() {
66 assert!(matches!(
67 VmStore::new_packed().try_push(VmValue::Str(String::new())),
68 Err(PQLError::TooManyVariables)
69 ));
70 }
71
72 #[test]
73 fn test_downcast_get() {
74 let mut i = PQLLong::default();
75 let v: VmValue = VmStackValue::from(i).into();
76 let mut store = VmStore::default();
77 let idx = store.try_push(v).unwrap();
78
79 assert_eq!(&i, store.downcast_get::<&PQLLong>(idx).unwrap());
80 assert_eq!(
81 &mut i,
82 store.downcast_get_mut::<&mut PQLLong>(idx).unwrap()
83 );
84
85 assert!(store.downcast_get::<&PQLString>(idx).is_err());
86 assert!(store.downcast_get_mut::<&mut PQLString>(idx).is_err());
87 }
88}