embedded_shadow/view/
host_staged.rs

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