embedded_shadow/view/
host_staged.rs1use 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}