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_attr(coverage_nightly, coverage(off))]
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use crate::*;
53
54 impl VmStore {
55 pub fn new_packed() -> Self {
56 Self {
57 inner: vec![
58 VmStackValue::from(PQLStreet::default()).into();
59 u8::MAX as usize + 1
60 ],
61 }
62 }
63 }
64
65 #[test]
66 fn test_try_push() {
67 assert!(matches!(
68 VmStore::new_packed().try_push(VmValue::Str(String::new())),
69 Err(PQLError::TooManyVariables)
70 ));
71 }
72
73 #[test]
74 fn test_downcast_get() {
75 let mut i = PQLLong::default();
76 let v: VmValue = VmStackValue::from(i).into();
77 let mut store = VmStore::default();
78 let idx = store.try_push(v).unwrap();
79
80 assert_eq!(&i, store.downcast_get::<&PQLLong>(idx).unwrap());
81 assert_eq!(
82 &mut i,
83 store.downcast_get_mut::<&mut PQLLong>(idx).unwrap()
84 );
85
86 assert!(store.downcast_get::<&PQLString>(idx).is_err());
87 assert!(store.downcast_get_mut::<&mut PQLString>(idx).is_err());
88 }
89}