1use anyhow::Result;
2use std::time::{Duration, Instant};
3
4use crate::{limits::StoreLimitsAsync, State, WasmtimeEngine};
5
6#[cfg(doc)]
7use crate::EngineBuilder;
8
9pub struct Store<T> {
16 inner: wasmtime::Store<T>,
17 epoch_tick_interval: Duration,
18}
19
20impl<T> Store<T> {
21 pub fn set_deadline(&mut self, deadline: Instant) {
29 let now = Instant::now();
30 let duration = deadline - now;
31 let ticks = if duration.is_zero() {
32 tracing::warn!("Execution deadline set in past: {deadline:?} < {now:?}");
33 0
34 } else {
35 let ticks = duration.as_micros() / self.epoch_tick_interval.as_micros();
36 let ticks = ticks.min(u64::MAX as u128) as u64;
37 ticks + 1 };
39 self.inner.set_epoch_deadline(ticks);
40 }
41
42 pub fn data(&self) -> &T {
44 self.inner.data()
45 }
46
47 pub fn data_mut(&mut self) -> &mut T {
49 self.inner.data_mut()
50 }
51}
52
53impl<T> AsRef<wasmtime::Store<T>> for Store<T> {
54 fn as_ref(&self) -> &wasmtime::Store<T> {
55 &self.inner
56 }
57}
58
59impl<T> AsMut<wasmtime::Store<T>> for Store<T> {
60 fn as_mut(&mut self) -> &mut wasmtime::Store<T> {
61 &mut self.inner
62 }
63}
64
65impl<T> wasmtime::AsContext for Store<T> {
66 type Data = T;
67
68 fn as_context(&self) -> wasmtime::StoreContext<'_, Self::Data> {
69 self.inner.as_context()
70 }
71}
72
73impl<T> wasmtime::AsContextMut for Store<T> {
74 fn as_context_mut(&mut self) -> wasmtime::StoreContextMut<'_, Self::Data> {
75 self.inner.as_context_mut()
76 }
77}
78
79pub struct StoreBuilder {
83 engine: WasmtimeEngine,
84 epoch_tick_interval: Duration,
85 store_limits: StoreLimitsAsync,
86}
87
88impl StoreBuilder {
89 pub(crate) fn new(engine: WasmtimeEngine, epoch_tick_interval: Duration) -> Self {
91 Self {
92 engine,
93 epoch_tick_interval,
94 store_limits: StoreLimitsAsync::default(),
95 }
96 }
97
98 pub fn max_memory_size(&mut self, max_memory_size: usize) {
103 self.store_limits = StoreLimitsAsync::new(Some(max_memory_size), None);
104 }
105
106 pub fn build<T: AsState>(self, mut data: T) -> Result<Store<T>> {
111 data.as_state().store_limits = self.store_limits;
112
113 let mut inner = wasmtime::Store::new(&self.engine, data);
114 inner.limiter_async(|data| &mut data.as_state().store_limits);
115
116 inner.set_epoch_deadline(u64::MAX / 2);
121
122 Ok(Store {
123 inner,
124 epoch_tick_interval: self.epoch_tick_interval,
125 })
126 }
127}
128
129pub trait AsState {
132 fn as_state(&mut self) -> &mut State;
134}
135
136impl AsState for State {
137 fn as_state(&mut self) -> &mut State {
138 self
139 }
140}