shuttle_engine/runtime/
storage.rs1use std::any::Any;
2use std::collections::{HashMap, VecDeque};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct StorageKey(pub usize, pub usize); #[derive(Debug)]
15pub struct StorageMap {
16 locals: HashMap<StorageKey, Option<Box<dyn Any>>>,
17 order: VecDeque<StorageKey>,
18 last: VecDeque<StorageKey>,
21}
22
23impl StorageMap {
24 pub fn new() -> Self {
25 Self {
26 locals: HashMap::new(),
27 order: VecDeque::new(),
28 last: VecDeque::new(),
29 }
30 }
31
32 pub fn get<T: 'static>(&self, key: StorageKey) -> Option<Result<&T, AlreadyDestructedError>> {
33 self.locals.get(&key).map(|val| {
34 val.as_ref()
35 .map(|val| {
36 Ok(val
37 .downcast_ref::<T>()
38 .expect("local value must downcast to expected type"))
39 })
40 .unwrap_or(Err(AlreadyDestructedError))
41 })
42 }
43
44 pub fn init<T: 'static>(&mut self, key: StorageKey, value: T) {
45 self.insert(key, value);
46 self.order.push_back(key);
47 }
48
49 pub fn init_destructed_last<T: 'static>(&mut self, key: StorageKey, value: T) {
51 self.insert(key, value);
52 self.last.push_back(key);
53 }
54
55 fn insert<T: 'static>(&mut self, key: StorageKey, value: T) {
56 let result = self.locals.insert(key, Some(Box::new(value)));
57 assert!(result.is_none(), "cannot reinitialize a storage slot");
58 }
59
60 pub fn is_empty(&self) -> bool {
62 self.order.is_empty() && self.last.is_empty()
63 }
64
65 pub fn pop(&mut self) -> Option<Box<dyn Any>> {
68 let key = self.order.pop_front().or_else(|| self.last.pop_front())?;
69 let value = self
70 .locals
71 .get_mut(&key)
72 .expect("keys in `order` must exist")
73 .take()
74 .expect("keys in `order` must not yet be destructed");
75 Some(value)
76 }
77}
78
79#[derive(Debug)]
80#[non_exhaustive]
81pub struct AlreadyDestructedError;