redoubt_buffer/
page_buffer.rs1use crate::error::{BufferError, PageError};
11use crate::page::Page;
12use crate::traits::Buffer;
13
14#[derive(Debug, Clone, Copy, Eq, PartialEq)]
16pub enum ProtectionStrategy {
17 MemProtected,
19 MemNonProtected,
21}
22
23pub struct PageBuffer {
25 page: Page,
26 len: usize,
27 strategy: ProtectionStrategy,
28}
29
30impl PageBuffer {
31 fn abort(error: PageError) -> ! {
32 #[cfg(test)]
34 std::process::exit(error as i32);
35
36 #[cfg(not(test))]
37 {
38 let _ = error;
39 unsafe { libc::abort() }
40 }
41 }
42
43 pub fn new(strategy: ProtectionStrategy, len: usize) -> Result<Self, PageError> {
45 let page = Page::new()?;
46
47 page.lock()?;
48 page.mark_dontdump()?;
49
50 if strategy == ProtectionStrategy::MemProtected {
51 page.protect()?;
52 }
53
54 Ok(Self {
55 page,
56 len,
57 strategy,
58 })
59 }
60
61 fn maybe_unprotect(&mut self) -> Result<(), PageError> {
62 if self.strategy == ProtectionStrategy::MemProtected {
63 self.page.unprotect()?;
64 }
65
66 Ok(())
67 }
68
69 fn maybe_protect(&mut self) -> Result<(), PageError> {
70 if self.strategy == ProtectionStrategy::MemProtected {
71 self.page.protect()?;
72 }
73
74 Ok(())
75 }
76
77 fn try_open(
78 &mut self,
79 f: &mut dyn FnMut(&[u8]) -> Result<(), BufferError>,
80 ) -> Result<(), BufferError> {
81 self.maybe_unprotect()?;
82
83 let slice = unsafe { self.page.as_slice() };
84 f(&slice[..self.len])?;
85
86 self.maybe_protect()?;
87
88 Ok(())
89 }
90
91 fn try_open_mut(
92 &mut self,
93 f: &mut dyn FnMut(&mut [u8]) -> Result<(), BufferError>,
94 ) -> Result<(), BufferError> {
95 self.maybe_unprotect()?;
96
97 let slice = unsafe { self.page.as_mut_slice() };
98 f(&mut slice[..self.len])?;
99
100 self.maybe_protect()?;
101
102 Ok(())
103 }
104
105 pub fn is_empty(&self) -> bool {
107 self.len == 0
108 }
109
110 pub fn dispose(&mut self) {
112 self.page.dispose();
113 }
114}
115
116unsafe impl Sync for PageBuffer {}
118
119impl core::fmt::Debug for PageBuffer {
120 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121 f.debug_struct("PageBuffer")
122 .field("len", &self.len)
123 .field("strategy", &self.strategy)
124 .finish_non_exhaustive()
125 }
126}
127
128impl Buffer for PageBuffer {
129 #[inline(always)]
130 fn open(
131 &mut self,
132 f: &mut dyn FnMut(&[u8]) -> Result<(), BufferError>,
133 ) -> Result<(), BufferError> {
134 let result = self.try_open(f);
135
136 if let Err(BufferError::Page(e)) = &result {
137 self.page.dispose();
138 Self::abort(*e);
139 }
140
141 result
142 }
143
144 #[inline(always)]
145 fn open_mut(
146 &mut self,
147 f: &mut dyn FnMut(&mut [u8]) -> Result<(), BufferError>,
148 ) -> Result<(), BufferError> {
149 let result = self.try_open_mut(f);
150
151 if let Err(BufferError::Page(e)) = &result {
152 self.page.dispose();
153 Self::abort(*e);
154 }
155
156 result
157 }
158
159 fn len(&self) -> usize {
160 self.len
161 }
162}