wasmtime_provider/
builder.rs1use crate::errors::{Error, Result};
2use crate::{WasmtimeEngineProvider, WasmtimeEngineProviderPre};
3#[cfg(feature = "async")]
4use crate::{WasmtimeEngineProviderAsync, WasmtimeEngineProviderAsyncPre};
5
6#[allow(missing_debug_implementations)]
8#[derive(Default)]
9pub struct WasmtimeEngineProviderBuilder<'a> {
10 engine: Option<wasmtime::Engine>,
11 module: Option<wasmtime::Module>,
12 module_bytes: Option<&'a [u8]>,
13 #[cfg(feature = "cache")]
14 cache_enabled: bool,
15 #[cfg(feature = "cache")]
16 cache_path: Option<std::path::PathBuf>,
17 #[cfg(feature = "wasi")]
18 wasi_params: Option<wapc::WasiParams>,
19 epoch_deadlines: Option<crate::EpochDeadlines>,
20}
21
22#[allow(deprecated)]
23impl<'a> WasmtimeEngineProviderBuilder<'a> {
24 #[must_use]
26 pub fn new() -> Self {
27 Default::default()
28 }
29
30 #[must_use]
32 pub fn module_bytes(mut self, module_bytes: &'a [u8]) -> Self {
33 self.module_bytes = Some(module_bytes);
34 self
35 }
36
37 #[must_use]
43 pub fn module(mut self, module: wasmtime::Module) -> Self {
44 self.module = Some(module);
45 self
46 }
47
48 #[must_use]
56 pub fn engine(mut self, engine: wasmtime::Engine) -> Self {
57 self.engine = Some(engine);
58 self
59 }
60
61 #[cfg(feature = "wasi")]
63 #[cfg_attr(docsrs, doc(cfg(feature = "wasi")))]
64 #[must_use]
65 pub fn wasi_params(mut self, wasi: wapc::WasiParams) -> Self {
66 self.wasi_params = Some(wasi);
67 self
68 }
69
70 #[cfg(feature = "cache")]
76 #[cfg_attr(docsrs, doc(cfg(feature = "cache")))]
77 #[must_use]
78 pub fn enable_cache(mut self, path: Option<&std::path::Path>) -> Self {
79 self.cache_enabled = true;
80 self.cache_path = path.map(|p| p.to_path_buf());
81 self
82 }
83
84 #[must_use]
104 pub fn enable_epoch_interruptions(mut self, wapc_init_deadline: u64, wapc_func_deadline: u64) -> Self {
105 self.epoch_deadlines = Some(crate::EpochDeadlines {
106 wapc_init: wapc_init_deadline,
107 wapc_func: wapc_func_deadline,
108 });
109 self
110 }
111
112 pub fn build_pre(&self) -> Result<WasmtimeEngineProviderPre> {
116 if self.module_bytes.is_some() && self.module.is_some() {
117 return Err(Error::BuilderInvalidConfig(
118 "`module_bytes` and `module` cannot be provided at the same time".to_owned(),
119 ));
120 }
121 if self.module_bytes.is_none() && self.module.is_none() {
122 return Err(Error::BuilderInvalidConfig(
123 "Neither `module_bytes` nor `module` have been provided".to_owned(),
124 ));
125 }
126
127 let pre = match &self.engine {
128 Some(e) => {
129 let module = self.module_bytes.as_ref().map_or_else(
130 || Ok(self.module.as_ref().unwrap().clone()),
131 |module_bytes| wasmtime::Module::new(e, module_bytes),
132 )?;
133
134 cfg_if::cfg_if! {
141 if #[cfg(feature = "wasi")] {
142 WasmtimeEngineProviderPre::new(e.clone(), module, self.wasi_params.clone(), self.epoch_deadlines)
143 } else {
144 WasmtimeEngineProviderPre::new(e.clone(), module, self.epoch_deadlines)
145 }
146 }
147 }
148 None => {
149 let mut config = wasmtime::Config::default();
150 if self.epoch_deadlines.is_some() {
151 config.epoch_interruption(true);
152 }
153
154 cfg_if::cfg_if! {
155 if #[cfg(feature = "cache")] {
156 if self.cache_enabled {
157 config.strategy(wasmtime::Strategy::Cranelift);
158 let cache = self.cache_path.as_ref().map_or_else(
159 || wasmtime::CacheConfig::from_file(None).and_then(wasmtime::Cache::new),
160 |cache_path| {
161 let mut cache_config = wasmtime::CacheConfig::new();
162 cache_config.with_directory(cache_path);
163 wasmtime::Cache::new(cache_config)
164 }
165 ).map_or_else(
166 |e| {
167 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);
168 None
169 },
170 Some,
171 );
172 config.cache(cache);
173 }
174 }
175 }
176
177 let engine = wasmtime::Engine::new(&config)?;
178
179 let module = self.module_bytes.as_ref().map_or_else(
180 || Ok(self.module.as_ref().unwrap().clone()),
181 |module_bytes| wasmtime::Module::new(&engine, module_bytes),
182 )?;
183
184 cfg_if::cfg_if! {
185 if #[cfg(feature = "wasi")] {
186 WasmtimeEngineProviderPre::new(engine, module, self.wasi_params.clone(), self.epoch_deadlines)
187 } else {
188 WasmtimeEngineProviderPre::new(engine, module, self.epoch_deadlines)
189
190 }
191 }
192 }
193 }?;
194
195 Ok(pre)
196 }
197
198 pub fn build(&self) -> Result<WasmtimeEngineProvider> {
200 let pre = self.build_pre()?;
201 pre.rehydrate()
202 }
203
204 #[cfg(feature = "async")]
211 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
212 pub fn build_async_pre(&self) -> Result<WasmtimeEngineProviderAsyncPre> {
213 if self.module_bytes.is_some() && self.module.is_some() {
214 return Err(Error::BuilderInvalidConfig(
215 "`module_bytes` and `module` cannot be provided at the same time".to_owned(),
216 ));
217 }
218 if self.module_bytes.is_none() && self.module.is_none() {
219 return Err(Error::BuilderInvalidConfig(
220 "Neither `module_bytes` nor `module` have been provided".to_owned(),
221 ));
222 }
223
224 let pre = match &self.engine {
225 Some(e) => {
226 let module = self.module_bytes.as_ref().map_or_else(
227 || Ok(self.module.as_ref().unwrap().clone()),
228 |module_bytes| wasmtime::Module::new(e, module_bytes),
229 )?;
230
231 cfg_if::cfg_if! {
238 if #[cfg(feature = "wasi")] {
239 WasmtimeEngineProviderAsyncPre::new(e.clone(), module, self.wasi_params.clone(), self.epoch_deadlines)
240 } else {
241 WasmtimeEngineProviderAsyncPre::new(e.clone(), module, self.epoch_deadlines)
242 }
243 }
244 }
245 None => {
246 let mut config = wasmtime::Config::default();
247 config.async_support(true);
248
249 if self.epoch_deadlines.is_some() {
250 config.epoch_interruption(true);
251 }
252
253 cfg_if::cfg_if! {
254 if #[cfg(feature = "cache")] {
255 if self.cache_enabled {
256 config.strategy(wasmtime::Strategy::Cranelift);
257 let cache = self.cache_path.as_ref().map_or_else(
258 || wasmtime::CacheConfig::from_file(None).and_then(wasmtime::Cache::new),
259 |cache_path| {
260 let mut cache_config = wasmtime::CacheConfig::new();
261 cache_config.with_directory(cache_path);
262 wasmtime::Cache::new(cache_config)
263 }
264 ).map_or_else(
265 |e| {
266 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);
267 None
268 },
269 Some,
270 );
271 config.cache(cache);
272 }
273 }
274 }
275
276 let engine = wasmtime::Engine::new(&config)?;
277
278 let module = self.module_bytes.as_ref().map_or_else(
279 || Ok(self.module.as_ref().unwrap().clone()),
280 |module_bytes| wasmtime::Module::new(&engine, module_bytes),
281 )?;
282
283 cfg_if::cfg_if! {
284 if #[cfg(feature = "wasi")] {
285 WasmtimeEngineProviderAsyncPre::new(engine, module, self.wasi_params.clone(), self.epoch_deadlines)
286 } else {
287 WasmtimeEngineProviderAsyncPre::new(engine, module, self.epoch_deadlines)
288 }
289 }
290 }
291 }?;
292
293 Ok(pre)
294 }
295
296 #[cfg(feature = "async")]
298 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
299 pub fn build_async(&self) -> Result<WasmtimeEngineProviderAsync> {
300 let pre = self.build_async_pre()?;
301 pre.rehydrate()
302 }
303}