datex_core/runtime/execution/execution_loop/
state.rs

1use crate::collections::HashMap;
2use crate::references::observers::TransceiverId;
3use crate::runtime::RuntimeInternal;
4use crate::runtime::execution::ExecutionError;
5use crate::runtime::execution::execution_loop::ExternalExecutionInterrupt;
6use crate::runtime::execution::execution_loop::interrupts::InterruptProvider;
7use crate::stdlib::boxed::Box;
8use crate::stdlib::rc::Rc;
9use crate::stdlib::vec::Vec;
10use crate::values::value_container::ValueContainer;
11use core::cell::RefCell;
12use core::fmt::Debug;
13
14pub struct ExecutionLoopState {
15    pub iterator: Box<
16        dyn Iterator<Item = Result<ExternalExecutionInterrupt, ExecutionError>>,
17    >,
18    pub dxb_body: Rc<RefCell<Vec<u8>>>,
19    pub(crate) interrupt_provider: InterruptProvider,
20}
21
22impl Debug for ExecutionLoopState {
23    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24        f.debug_struct("ExecutionIterator")
25            .field("dxb_body_length", &self.dxb_body.borrow().len())
26            .finish()
27    }
28}
29
30#[derive(Debug, Default)]
31pub struct RuntimeExecutionState {
32    /// Local memory slots for current execution context.
33    /// TODO #643: replace this with a local stack and deprecate local slots?
34    pub(crate) slots: RuntimeExecutionSlots,
35    pub(crate) runtime_internal: Option<Rc<RuntimeInternal>>,
36    pub(crate) source_id: TransceiverId,
37}
38
39#[derive(Debug, Default)]
40pub struct RuntimeExecutionSlots {
41    pub(crate) slots: HashMap<u32, Option<ValueContainer>>,
42}
43
44impl RuntimeExecutionSlots {
45    /// Allocates a new slot with the given slot address.
46    pub(crate) fn allocate_slot(
47        &mut self,
48        address: u32,
49        value: Option<ValueContainer>,
50    ) {
51        self.slots.insert(address, value);
52    }
53
54    /// Drops a slot by its address, returning the value if it existed.
55    /// If the slot is not allocated, it returns an error.
56    pub(crate) fn drop_slot(
57        &mut self,
58        address: u32,
59    ) -> Result<Option<ValueContainer>, ExecutionError> {
60        self.slots
61            .remove(&address)
62            .ok_or(())
63            .map_err(|_| ExecutionError::SlotNotAllocated(address))
64    }
65
66    /// Sets the value of a slot, returning the previous value if it existed.
67    /// If the slot is not allocated, it returns an error.
68    pub(crate) fn set_slot_value(
69        &mut self,
70        address: u32,
71        value: ValueContainer,
72    ) -> Result<Option<ValueContainer>, ExecutionError> {
73        self.slots
74            .insert(address, Some(value))
75            .ok_or(())
76            .map_err(|_| ExecutionError::SlotNotAllocated(address))
77    }
78
79    /// Retrieves a reference to the value of a slot by its address.
80    /// If the slot is not allocated, it returns an error.
81    pub(crate) fn get_slot_value(
82        &self,
83        address: u32,
84    ) -> Result<&ValueContainer, ExecutionError> {
85        self.slots
86            .get(&address)
87            .and_then(|inner| inner.as_ref())
88            .ok_or_else(|| ExecutionError::SlotNotAllocated(address))
89    }
90
91    /// Retrieves a mutable reference to the value of a slot by its address.
92    /// If the slot is not allocated, it returns an error.
93    pub(crate) fn get_slot_value_mut(
94        &mut self,
95        address: u32,
96    ) -> Result<&mut ValueContainer, ExecutionError> {
97        self.slots
98            .get_mut(&address)
99            .and_then(|inner| inner.as_mut())
100            .ok_or_else(|| ExecutionError::SlotNotAllocated(address))
101    }
102}