embedded_shadow/view/
host.rs

1use core::marker::PhantomData;
2
3use crate::{AccessPolicy, PersistTrigger, ShadowError, policy::PersistPolicy, table::ShadowTable};
4use bitmaps::{Bits, BitsImpl};
5
6pub struct HostView<'a, const TS: usize, const BS: usize, const BC: usize, AP, PP, PT, PK>
7where
8    BitsImpl<BC>: Bits,
9    AP: AccessPolicy,
10    PP: PersistPolicy<PK>,
11    PT: PersistTrigger<PK>,
12{
13    pub(crate) table: &'a mut ShadowTable<TS, BS, BC>,
14    pub(crate) access_policy: &'a AP,
15    pub(crate) persist_policy: &'a PP,
16    pub(crate) persist_trigger: &'a mut PT,
17    _phantom: PhantomData<PK>,
18}
19
20impl<'a, const TS: usize, const BS: usize, const BC: usize, AP, PP, PT, PK>
21    HostView<'a, TS, BS, BC, AP, PP, PT, PK>
22where
23    BitsImpl<BC>: Bits,
24    AP: AccessPolicy,
25    PP: PersistPolicy<PK>,
26    PT: PersistTrigger<PK>,
27{
28    pub(crate) fn new(
29        table: &'a mut ShadowTable<TS, BS, BC>,
30        access_policy: &'a AP,
31        persist_policy: &'a PP,
32        persist_trigger: &'a mut PT,
33    ) -> Self {
34        Self {
35            table,
36            access_policy,
37            persist_policy,
38            persist_trigger,
39            _phantom: PhantomData,
40        }
41    }
42
43    pub fn read_range(&self, addr: u16, out: &mut [u8]) -> Result<(), ShadowError> {
44        if !self.access_policy.can_read(addr, out.len()) {
45            return Err(ShadowError::Denied);
46        }
47        self.table.read_range(addr, out)
48    }
49
50    /// Host write: marks dirty + may request persistence.
51    pub fn write_range(&mut self, addr: u16, data: &[u8]) -> Result<(), ShadowError> {
52        self.write_range_no_persist(addr, data)?;
53
54        let should_persist =
55            self.persist_policy
56                .push_persist_keys_for_range(addr, data.len(), |key| {
57                    self.persist_trigger.push_key(key)
58                });
59
60        if should_persist {
61            self.persist_trigger.request_persist();
62        }
63
64        Ok(())
65    }
66
67    pub(crate) fn write_range_no_persist(
68        &mut self,
69        addr: u16,
70        data: &[u8],
71    ) -> Result<(), ShadowError> {
72        if !self.access_policy.can_write(addr, data.len()) {
73            return Err(ShadowError::Denied);
74        }
75
76        self.table.write_range(addr, data)?;
77        self.table.mark_dirty(addr, data.len())?;
78
79        Ok(())
80    }
81}