wasmtime_provider/
builder.rs1use crate::errors::{Error, Result};
2use crate::{WasmtimeEngineProvider, WasmtimeEngineProviderPre};
3
4#[cfg(feature = "async")]
5use crate::{WasmtimeEngineProviderAsync, WasmtimeEngineProviderAsyncPre};
6
7#[allow(missing_debug_implementations)]
9#[derive(Default)]
10pub struct WasmtimeEngineProviderBuilder<'a> {
11 engine: Option<wasmtime::Engine>,
12 module: Option<wasmtime::Module>,
13 module_bytes: Option<&'a [u8]>,
14 #[cfg(feature = "cache")]
15 cache_enabled: bool,
16 #[cfg(feature = "cache")]
17 cache_path: Option<std::path::PathBuf>,
18 #[cfg(feature = "wasi")]
19 wasi_params: Option<wapc::WasiParams>,
20 epoch_deadlines: Option<crate::EpochDeadlines>,
21}
22
23#[allow(deprecated)]
24impl<'a> WasmtimeEngineProviderBuilder<'a> {
25 #[must_use]
27 pub fn new() -> Self {
28 Default::default()
29 }
30
31 #[must_use]
33 pub fn module_bytes(mut self, module_bytes: &'a [u8]) -> Self {
34 self.module_bytes = Some(module_bytes);
35 self
36 }
37
38 #[must_use]
44 pub fn module(mut self, module: wasmtime::Module) -> Self {
45 self.module = Some(module);
46 self
47 }
48
49 #[must_use]
57 pub fn engine(mut self, engine: wasmtime::Engine) -> Self {
58 self.engine = Some(engine);
59 self
60 }
61
62 #[cfg(feature = "wasi")]
64 #[cfg_attr(docsrs, doc(cfg(feature = "wasi")))]
65 #[must_use]
66 pub fn wasi_params(mut self, wasi: wapc::WasiParams) -> Self {
67 self.wasi_params = Some(wasi);
68 self
69 }
70
71 #[cfg(feature = "cache")]
77 #[cfg_attr(docsrs, doc(cfg(feature = "cache")))]
78 #[must_use]
79 pub fn enable_cache(mut self, path: Option<&std::path::Path>) -> Self {
80 self.cache_enabled = true;
81 self.cache_path = path.map(|p| p.to_path_buf());
82 self
83 }
84
85 #[must_use]
105 pub fn enable_epoch_interruptions(mut self, wapc_init_deadline: u64, wapc_func_deadline: u64) -> Self {
106 self.epoch_deadlines = Some(crate::EpochDeadlines {
107 wapc_init: wapc_init_deadline,
108 wapc_func: wapc_func_deadline,
109 });
110 self
111 }
112
113 pub fn build_pre(&self) -> Result<WasmtimeEngineProviderPre> {
117 if self.module_bytes.is_some() && self.module.is_some() {
118 return Err(Error::BuilderInvalidConfig(
119 "`module_bytes` and `module` cannot be provided at the same time".to_owned(),
120 ));
121 }
122 if self.module_bytes.is_none() && self.module.is_none() {
123 return Err(Error::BuilderInvalidConfig(
124 "Neither `module_bytes` nor `module` have been provided".to_owned(),
125 ));
126 }
127
128 let pre = match &self.engine {
129 Some(e) => {
130 let module = self.module_bytes.as_ref().map_or_else(
131 || Ok(self.module.as_ref().unwrap().clone()),
132 |module_bytes| wasmtime::Module::new(e, module_bytes),
133 )?;
134
135 cfg_if::cfg_if! {
142 if #[cfg(feature = "wasi")] {
143 WasmtimeEngineProviderPre::new(e.clone(), module, self.wasi_params.clone(), self.epoch_deadlines)
144 } else {
145 WasmtimeEngineProviderPre::new(e.clone(), module, self.epoch_deadlines)
146 }
147 }
148 }
149 None => {
150 let mut config = wasmtime::Config::default();
151 if self.epoch_deadlines.is_some() {
152 config.epoch_interruption(true);
153 }
154
155 cfg_if::cfg_if! {
156 if #[cfg(feature = "cache")] {
157 if self.cache_enabled {
158 config.strategy(wasmtime::Strategy::Cranelift);
159 if let Some(cache) = &self.cache_path {
160 config.cache_config_load(cache)?;
161 } else if let Err(e) = config.cache_config_load_default() {
162 log::warn!("Wasmtime cache configuration not found ({}). Repeated loads will speed up significantly with a cache configuration. See https://docs.wasmtime.dev/cli-cache.html for more information.",e);
163 }
164 }
165 }
166 }
167
168 let engine = wasmtime::Engine::new(&config)?;
169
170 let module = self.module_bytes.as_ref().map_or_else(
171 || Ok(self.module.as_ref().unwrap().clone()),
172 |module_bytes| wasmtime::Module::new(&engine, module_bytes),
173 )?;
174
175 cfg_if::cfg_if! {
176 if #[cfg(feature = "wasi")] {
177 WasmtimeEngineProviderPre::new(engine, module, self.wasi_params.clone(), self.epoch_deadlines)
178 } else {
179 WasmtimeEngineProviderPre::new(engine, module, self.epoch_deadlines)
180
181 }
182 }
183 }
184 }?;
185
186 Ok(pre)
187 }
188
189 pub fn build(&self) -> Result<WasmtimeEngineProvider> {
191 let pre = self.build_pre()?;
192 pre.rehydrate()
193 }
194
195 #[cfg(feature = "async")]
202 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
203 pub fn build_async_pre(&self) -> Result<WasmtimeEngineProviderAsyncPre> {
204 if self.module_bytes.is_some() && self.module.is_some() {
205 return Err(Error::BuilderInvalidConfig(
206 "`module_bytes` and `module` cannot be provided at the same time".to_owned(),
207 ));
208 }
209 if self.module_bytes.is_none() && self.module.is_none() {
210 return Err(Error::BuilderInvalidConfig(
211 "Neither `module_bytes` nor `module` have been provided".to_owned(),
212 ));
213 }
214
215 let pre = match &self.engine {
216 Some(e) => {
217 let module = self.module_bytes.as_ref().map_or_else(
218 || Ok(self.module.as_ref().unwrap().clone()),
219 |module_bytes| wasmtime::Module::new(e, module_bytes),
220 )?;
221
222 cfg_if::cfg_if! {
229 if #[cfg(feature = "wasi")] {
230 WasmtimeEngineProviderAsyncPre::new(e.clone(), module, self.wasi_params.clone(), self.epoch_deadlines)
231 } else {
232 WasmtimeEngineProviderAsyncPre::new(e.clone(), module, self.epoch_deadlines)
233 }
234 }
235 }
236 None => {
237 let mut config = wasmtime::Config::default();
238 config.async_support(true);
239
240 if self.epoch_deadlines.is_some() {
241 config.epoch_interruption(true);
242 }
243
244 cfg_if::cfg_if! {
245 if #[cfg(feature = "cache")] {
246 if self.cache_enabled {
247 config.strategy(wasmtime::Strategy::Cranelift);
248 if let Some(cache) = &self.cache_path {
249 config.cache_config_load(cache)?;
250 } else if let Err(e) = config.cache_config_load_default() {
251 log::warn!("Wasmtime cache configuration not found ({}). Repeated loads will speed up significantly with a cache configuration. See https://docs.wasmtime.dev/cli-cache.html for more information.",e);
252 }
253 }
254 }
255 }
256
257 let engine = wasmtime::Engine::new(&config)?;
258
259 let module = self.module_bytes.as_ref().map_or_else(
260 || Ok(self.module.as_ref().unwrap().clone()),
261 |module_bytes| wasmtime::Module::new(&engine, module_bytes),
262 )?;
263
264 cfg_if::cfg_if! {
265 if #[cfg(feature = "wasi")] {
266 WasmtimeEngineProviderAsyncPre::new(engine, module, self.wasi_params.clone(), self.epoch_deadlines)
267 } else {
268 WasmtimeEngineProviderAsyncPre::new(engine, module, self.epoch_deadlines)
269 }
270 }
271 }
272 }?;
273
274 Ok(pre)
275 }
276
277 #[cfg(feature = "async")]
279 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
280 pub fn build_async(&self) -> Result<WasmtimeEngineProviderAsync> {
281 let pre = self.build_async_pre()?;
282 pre.rehydrate()
283 }
284}