revm_context_interface/
local.rs1use core::{
3 cell::{Ref, RefCell},
4 ops::Range,
5};
6use std::{rc::Rc, vec::Vec};
7
8#[derive(Debug, Clone)]
10pub struct FrameStack<T> {
11 stack: Vec<T>,
12 index: Option<usize>,
13}
14
15impl<T> Default for FrameStack<T> {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl<T> FrameStack<T> {
22 pub fn new() -> Self {
24 Self {
25 stack: Vec::with_capacity(4),
26 index: None,
27 }
28 }
29
30 #[inline]
32 pub fn start_init(&mut self) -> OutFrame<'_, T> {
33 self.index = None;
34 if self.stack.is_empty() {
35 self.stack.reserve(1);
36 }
37 self.out_frame_at(0)
38 }
39
40 #[inline]
46 pub unsafe fn end_init(&mut self, token: FrameToken) {
47 token.assert();
48 if self.stack.is_empty() {
49 unsafe { self.stack.set_len(1) };
50 }
51 self.index = Some(0);
52 }
53
54 #[inline]
56 pub fn index(&self) -> Option<usize> {
57 self.index
58 }
59
60 #[inline]
67 pub unsafe fn push(&mut self, token: FrameToken) {
68 token.assert();
69 let index = self.index.as_mut().unwrap();
70 if *index + 1 == self.stack.len() {
71 unsafe { self.stack.set_len(self.stack.len() + 1) };
72 self.stack.reserve(1);
73 }
74 *index += 1;
75 }
76
77 #[inline]
80 pub fn clear(&mut self) {
81 self.index = None;
82 }
83
84 #[inline]
86 pub fn pop(&mut self) {
87 self.index = self.index.unwrap_or(0).checked_sub(1);
88 }
89
90 #[inline]
92 pub fn get(&mut self) -> &mut T {
93 debug_assert!(self.stack.capacity() > self.index.unwrap() + 1);
94 unsafe { &mut *self.stack.as_mut_ptr().add(self.index.unwrap()) }
95 }
96
97 #[inline]
99 pub fn get_next(&mut self) -> OutFrame<'_, T> {
100 self.out_frame_at(self.index.unwrap() + 1)
101 }
102
103 fn out_frame_at(&mut self, idx: usize) -> OutFrame<'_, T> {
104 unsafe {
105 OutFrame::new_maybe_uninit(self.stack.as_mut_ptr().add(idx), idx < self.stack.len())
106 }
107 }
108}
109
110#[allow(missing_debug_implementations)]
112pub struct OutFrame<'a, T> {
113 ptr: *mut T,
114 init: bool,
115 lt: core::marker::PhantomData<&'a mut T>,
116}
117
118impl<'a, T> OutFrame<'a, T> {
119 pub fn new_init(slot: &'a mut T) -> Self {
121 unsafe { Self::new_maybe_uninit(slot, true) }
122 }
123
124 pub fn new_uninit(slot: &'a mut core::mem::MaybeUninit<T>) -> Self {
126 unsafe { Self::new_maybe_uninit(slot.as_mut_ptr(), false) }
127 }
128
129 pub unsafe fn new_maybe_uninit(ptr: *mut T, init: bool) -> Self {
137 Self {
138 ptr,
139 init,
140 lt: Default::default(),
141 }
142 }
143
144 pub fn get(&mut self, f: impl FnOnce() -> T) -> &mut T {
146 if !self.init {
147 self.do_init(f);
148 }
149 unsafe { &mut *self.ptr }
150 }
151
152 #[inline(never)]
153 #[cold]
154 fn do_init(&mut self, f: impl FnOnce() -> T) {
155 unsafe {
156 self.init = true;
157 self.ptr.write(f());
158 }
159 }
160
161 pub unsafe fn get_unchecked(&mut self) -> &mut T {
167 debug_assert!(self.init, "OutFrame must be initialized before use");
168 unsafe { &mut *self.ptr }
169 }
170
171 pub fn consume(self) -> FrameToken {
173 FrameToken(self.init)
174 }
175}
176
177#[allow(missing_debug_implementations)]
179pub struct FrameToken(bool);
180
181impl FrameToken {
182 #[cfg_attr(debug_assertions, track_caller)]
184 pub fn assert(self) {
185 assert!(self.0, "FrameToken must be initialized before use");
186 }
187}
188
189pub trait LocalContextTr {
191 fn shared_memory_buffer(&self) -> &Rc<RefCell<Vec<u8>>>;
193
194 fn shared_memory_buffer_slice(&self, range: Range<usize>) -> Option<Ref<'_, [u8]>> {
196 let buffer = self.shared_memory_buffer();
197 buffer.borrow().get(range.clone())?;
198 Some(Ref::map(buffer.borrow(), |b| {
199 b.get(range).unwrap_or_default()
200 }))
201 }
202
203 fn clear(&mut self);
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn frame_stack() {
213 let mut stack = FrameStack::new();
214 let mut frame = stack.start_init();
215 frame.get(|| 1);
216 let token = frame.consume();
217 unsafe { stack.end_init(token) };
218
219 assert_eq!(stack.index(), Some(0));
220 assert_eq!(stack.stack.len(), 1);
221
222 let a = stack.get();
223 assert_eq!(a, &mut 1);
224 let mut b = stack.get_next();
225 assert!(!b.init);
226 assert_eq!(b.get(|| 2), &mut 2);
227 let token = b.consume(); unsafe { stack.push(token) };
229
230 assert_eq!(stack.index(), Some(1));
231 assert_eq!(stack.stack.len(), 2);
232 let a = stack.get();
233 assert_eq!(a, &mut 2);
234 let b = stack.get_next();
235 assert!(!b.init);
236
237 stack.pop();
238
239 assert_eq!(stack.index(), Some(0));
240 assert_eq!(stack.stack.len(), 2);
241 let a = stack.get();
242 assert_eq!(a, &mut 1);
243 let mut b = stack.get_next();
244 assert!(b.init);
245 assert_eq!(unsafe { b.get_unchecked() }, &mut 2);
246 }
247}