1e069bdd3SNick Fitzgerald use super::*;
2c3a6060bSNick Fitzgerald use crate::ToWasmtimeResult as _;
3e069bdd3SNick Fitzgerald 
4e069bdd3SNick Fitzgerald impl<'a> CodeBuilder<'a> {
get_compile_time_builtins(&self) -> &HashMap<Cow<'a, str>, Cow<'a, [u8]>>5e069bdd3SNick Fitzgerald     pub(crate) fn get_compile_time_builtins(&self) -> &HashMap<Cow<'a, str>, Cow<'a, [u8]>> {
6e069bdd3SNick Fitzgerald         &self.compile_time_builtins
7e069bdd3SNick Fitzgerald     }
8e069bdd3SNick Fitzgerald 
compose_compile_time_builtins<'b>( &self, main_wasm: &'b [u8], ) -> Result<Cow<'b, [u8]>>9e069bdd3SNick Fitzgerald     pub(super) fn compose_compile_time_builtins<'b>(
10e069bdd3SNick Fitzgerald         &self,
11e069bdd3SNick Fitzgerald         main_wasm: &'b [u8],
12e069bdd3SNick Fitzgerald     ) -> Result<Cow<'b, [u8]>> {
13e069bdd3SNick Fitzgerald         if self.get_compile_time_builtins().is_empty() {
14e069bdd3SNick Fitzgerald             return Ok(main_wasm.into());
15e069bdd3SNick Fitzgerald         }
16e069bdd3SNick Fitzgerald 
17e069bdd3SNick Fitzgerald         let imports = self.check_imports_for_compile_time_builtins(&main_wasm)?;
18e069bdd3SNick Fitzgerald         if imports.is_empty() {
19e069bdd3SNick Fitzgerald             drop(imports);
20e069bdd3SNick Fitzgerald             return Ok(main_wasm.into());
21e069bdd3SNick Fitzgerald         }
22e069bdd3SNick Fitzgerald 
23e069bdd3SNick Fitzgerald         let tempdir = tempfile::TempDir::new().context("failed to create a temporary directory")?;
24e069bdd3SNick Fitzgerald         let deps = tempdir.path().join("_deps");
25e069bdd3SNick Fitzgerald         std::fs::create_dir(&deps)
26e069bdd3SNick Fitzgerald             .with_context(|| format!("failed to create directory: {}", deps.display()))?;
27e069bdd3SNick Fitzgerald 
28e069bdd3SNick Fitzgerald         let main_wasm_path = tempdir.path().join("_main.wasm");
29e069bdd3SNick Fitzgerald         std::fs::write(&main_wasm_path, &main_wasm)
30e069bdd3SNick Fitzgerald             .with_context(|| format!("failed to write to file: {}", main_wasm_path.display()))?;
31e069bdd3SNick Fitzgerald 
32e069bdd3SNick Fitzgerald         let mut config = wasm_compose::config::Config::default();
33e069bdd3SNick Fitzgerald         for (name, bytes) in self.get_compile_time_builtins() {
34e069bdd3SNick Fitzgerald             let name: &str = &*name;
35e069bdd3SNick Fitzgerald             if !imports.contains(&name) {
36e069bdd3SNick Fitzgerald                 continue;
37e069bdd3SNick Fitzgerald             }
38e069bdd3SNick Fitzgerald 
39e069bdd3SNick Fitzgerald             let mut path = deps.join(Path::new(name));
40e069bdd3SNick Fitzgerald             path.set_extension("wasm");
41e069bdd3SNick Fitzgerald 
42e069bdd3SNick Fitzgerald             std::fs::write(&path, &bytes)
43e069bdd3SNick Fitzgerald                 .with_context(|| format!("failed to write to file: {}", path.display()))?;
44e069bdd3SNick Fitzgerald 
45e069bdd3SNick Fitzgerald             config
46e069bdd3SNick Fitzgerald                 .dependencies
47e069bdd3SNick Fitzgerald                 .insert(name.to_string(), wasm_compose::config::Dependency { path });
48e069bdd3SNick Fitzgerald         }
49e069bdd3SNick Fitzgerald 
50e069bdd3SNick Fitzgerald         let composer = wasm_compose::composer::ComponentComposer::new(&main_wasm_path, &config);
51c3a6060bSNick Fitzgerald         let composed = composer.compose().to_wasmtime_result()?;
52e069bdd3SNick Fitzgerald         Ok(composed.into())
53e069bdd3SNick Fitzgerald     }
54e069bdd3SNick Fitzgerald 
55e069bdd3SNick Fitzgerald     /// Check that the main Wasm doesn't import unsafe intrinsics, keeping the
56e069bdd3SNick Fitzgerald     /// TCB to just the compile-time builtins' implementation.
57e069bdd3SNick Fitzgerald     ///
58e069bdd3SNick Fitzgerald     /// Returns the Wasm's top-level instance imports for `wasm-compose`
59e069bdd3SNick Fitzgerald     /// configuration.
check_imports_for_compile_time_builtins<'b>( &self, main_wasm: &'b [u8], ) -> Result<crate::hash_set::HashSet<&'b str>, Error>60e069bdd3SNick Fitzgerald     fn check_imports_for_compile_time_builtins<'b>(
61e069bdd3SNick Fitzgerald         &self,
62e069bdd3SNick Fitzgerald         main_wasm: &'b [u8],
63e069bdd3SNick Fitzgerald     ) -> Result<crate::hash_set::HashSet<&'b str>, Error> {
64e069bdd3SNick Fitzgerald         let intrinsics_import = self.unsafe_intrinsics_import.as_deref().ok_or_else(|| {
65ff33e949SNick Fitzgerald             format_err!(
66ff33e949SNick Fitzgerald                 "must configure the unsafe-intrinsics import when using compile-time builtins"
67ff33e949SNick Fitzgerald             )
68e069bdd3SNick Fitzgerald         })?;
69e069bdd3SNick Fitzgerald 
70e069bdd3SNick Fitzgerald         let mut instance_imports = crate::hash_set::HashSet::new();
71e069bdd3SNick Fitzgerald         let parser = wasmparser::Parser::new(0);
72e069bdd3SNick Fitzgerald         let mut level = 0;
73e069bdd3SNick Fitzgerald 
74e069bdd3SNick Fitzgerald         for payload in parser.parse_all(main_wasm) {
75e069bdd3SNick Fitzgerald             match payload? {
76e069bdd3SNick Fitzgerald                 wasmparser::Payload::Version { .. } => {
77e069bdd3SNick Fitzgerald                     level += 1;
78e069bdd3SNick Fitzgerald                 }
79e069bdd3SNick Fitzgerald                 wasmparser::Payload::End(_) => {
80e069bdd3SNick Fitzgerald                     level -= 1;
81e069bdd3SNick Fitzgerald                 }
82e069bdd3SNick Fitzgerald                 wasmparser::Payload::ComponentImportSection(imports) if level == 1 => {
83e069bdd3SNick Fitzgerald                     for imp in imports.into_iter() {
84e069bdd3SNick Fitzgerald                         let imp = imp?;
85e069bdd3SNick Fitzgerald                         // Ideally we would simply choose a new import name that
86e069bdd3SNick Fitzgerald                         // doesn't conflict with the main Wasm's imports and
87e069bdd3SNick Fitzgerald                         // plumb that through to the compile-time builtins
88e069bdd3SNick Fitzgerald                         // regardless of the import name that they use, but
89e069bdd3SNick Fitzgerald                         // unfortunately the `wasm-compose` API is not powerful
90e069bdd3SNick Fitzgerald                         // enough for us to do all that.
91e069bdd3SNick Fitzgerald                         ensure!(
92e069bdd3SNick Fitzgerald                             imp.name.0 != intrinsics_import,
93e069bdd3SNick Fitzgerald                             "main Wasm cannot import the unsafe intrinsics (`{intrinsics_import}`) \
94e069bdd3SNick Fitzgerald                              when using compile-time builtins"
95e069bdd3SNick Fitzgerald                         );
96e069bdd3SNick Fitzgerald 
97e069bdd3SNick Fitzgerald                         if let wasmparser::ComponentTypeRef::Instance(_) = imp.ty {
98e069bdd3SNick Fitzgerald                             instance_imports.insert(imp.name.0);
99e069bdd3SNick Fitzgerald                         }
100e069bdd3SNick Fitzgerald                     }
101e069bdd3SNick Fitzgerald                 }
102e069bdd3SNick Fitzgerald                 _ => {}
103e069bdd3SNick Fitzgerald             }
104e069bdd3SNick Fitzgerald         }
105e069bdd3SNick Fitzgerald 
106e069bdd3SNick Fitzgerald         Ok(instance_imports)
107e069bdd3SNick Fitzgerald     }
108e069bdd3SNick Fitzgerald 
109e069bdd3SNick Fitzgerald     /// Define a compile-time builtin component, via its Wasm bytes.
110e069bdd3SNick Fitzgerald     ///
111e069bdd3SNick Fitzgerald     /// Compile-time builtins enable you to build safe, zero-copy, and (with
112e069bdd3SNick Fitzgerald     /// [inlining][crate::Config::compiler_inlining])
113e069bdd3SNick Fitzgerald     /// zero-function-call-overhead Wasm APIs for accessing host data, buffers,
114e069bdd3SNick Fitzgerald     /// and objects.
115e069bdd3SNick Fitzgerald     ///
116e069bdd3SNick Fitzgerald     /// A compile-time builtin is a component that is
117e069bdd3SNick Fitzgerald     ///
118e069bdd3SNick Fitzgerald     /// * authored by the host (Wasmtime embedder),
119e069bdd3SNick Fitzgerald     ///
120e069bdd3SNick Fitzgerald     /// * whose implementation (though not necessarily its interface!) is
121e069bdd3SNick Fitzgerald     ///   host-specific,
122e069bdd3SNick Fitzgerald     ///
123e069bdd3SNick Fitzgerald     /// * has access to unsafe intrinsics (and is therefore part of the host's
124e069bdd3SNick Fitzgerald     ///   [trusted compute base]), and
125e069bdd3SNick Fitzgerald     ///
126e069bdd3SNick Fitzgerald     /// * is linked into guest Wasm programs at compile-time.
127e069bdd3SNick Fitzgerald     ///
128e069bdd3SNick Fitzgerald     /// Any imports satisfied by a compile-time builtin during compilation will
129e069bdd3SNick Fitzgerald     /// not show up in the resulting component's
130e069bdd3SNick Fitzgerald     /// [imports][crate::component::types::Component::imports], and they can no
131e069bdd3SNick Fitzgerald     /// longer be customized by a [`Linker`][crate::component::Linker]
132e069bdd3SNick Fitzgerald     /// definition at instantiation time.[^0]
133e069bdd3SNick Fitzgerald     ///
134e069bdd3SNick Fitzgerald     /// [^0]: If linking compile-time builtins into a component at compile-time
135e069bdd3SNick Fitzgerald     /// reminds you of [component composition], that is not a coincidence:
136e069bdd3SNick Fitzgerald     /// component composition is used under the covers as part of compile-time
137e069bdd3SNick Fitzgerald     /// builtins' implementation.
138e069bdd3SNick Fitzgerald     ///
139e069bdd3SNick Fitzgerald     /// Comparing compile-time builtins with
140e069bdd3SNick Fitzgerald     /// [`Linker`][crate::component::Linker]s is informative:
141e069bdd3SNick Fitzgerald     ///
142e069bdd3SNick Fitzgerald     /// * Both mechanisms define APIs to satisfy a Wasm program's imports.
143e069bdd3SNick Fitzgerald     ///
144e069bdd3SNick Fitzgerald     /// * A `Linker` satisfies those imports at instantiation-time, while
145e069bdd3SNick Fitzgerald     ///   compile-time builtins do it during compilation.
146e069bdd3SNick Fitzgerald     ///
147e069bdd3SNick Fitzgerald     /// * APIs defined by a `Linker` are implemented in Rust, and hosts can
148e069bdd3SNick Fitzgerald     ///   build safe, sandboxed Wasm APIs on top of raw, un-sandboxed primitives
149e069bdd3SNick Fitzgerald     ///   via Rust's `unsafe`. APIs defined by compile-time builtins are
150e069bdd3SNick Fitzgerald     ///   implemented as Wasm components, and hosts can build safe, sandboxed
151e069bdd3SNick Fitzgerald     ///   Wasm APIs on top of raw, un-sandboxed primitives via [unsafe
152e069bdd3SNick Fitzgerald     ///   intrinsics][CodeBuilder::expose_unsafe_intrinsics].
153e069bdd3SNick Fitzgerald     ///
154e069bdd3SNick Fitzgerald     /// * Imports satisfied via `Linker`-defined APIs are implemented with
155e069bdd3SNick Fitzgerald     ///   [PLT/GOT]-style function table lookups and indirect calls in the
156e069bdd3SNick Fitzgerald     ///   Wasm's compiled native code. On the other hand, Wasmtime implements
157e069bdd3SNick Fitzgerald     ///   calls to imports satisfied via compile-time builtins with direct calls
158e069bdd3SNick Fitzgerald     ///   in the Wasm's compiled native code. Wasmtime's compiler can also
159e069bdd3SNick Fitzgerald     ///   [inline][crate::Config::compiler_inlining] these direct calls,
160e069bdd3SNick Fitzgerald     ///   removing function call overheads and enabling further, cascading
161e069bdd3SNick Fitzgerald     ///   compiler optimizations.
162e069bdd3SNick Fitzgerald     ///
163e069bdd3SNick Fitzgerald     /// If you are familiar with Wasm on the Web, you can think of compile-time
164e069bdd3SNick Fitzgerald     /// builtins as the rough equivalent of [the `js-string-builtins` proposal]
165e069bdd3SNick Fitzgerald     /// but for arbitrary host-defined APIs in a Wasmtime embedding environment
166e069bdd3SNick Fitzgerald     /// rather than JS string APIs in a Web browser environment.
167e069bdd3SNick Fitzgerald     ///
168e069bdd3SNick Fitzgerald     /// [trusted compute base]: https://en.wikipedia.org/wiki/Trusted_computing_base
169e069bdd3SNick Fitzgerald     /// [the `js-string-builtins` proposal]: https://github.com/WebAssembly/js-string-builtins/blob/main/proposals/js-string-builtins/Overview.md
170e069bdd3SNick Fitzgerald     /// [component composition]: https://component-model.bytecodealliance.org/composing-and-distributing/composing.html
171e069bdd3SNick Fitzgerald     /// [PLT/GOT]: https://reverseengineering.stackexchange.com/a/1993
172e069bdd3SNick Fitzgerald     ///
173e069bdd3SNick Fitzgerald     /// # Safety
174e069bdd3SNick Fitzgerald     ///
175e069bdd3SNick Fitzgerald     /// Compile-time builtins are part of your [trusted compute base] and should
176e069bdd3SNick Fitzgerald     /// be authored by trusted, first-party developers with extreme care. You
177e069bdd3SNick Fitzgerald     /// should never use compile-time builtins authored by untrusted,
178e069bdd3SNick Fitzgerald     /// third-party developers.
179e069bdd3SNick Fitzgerald     ///
180e069bdd3SNick Fitzgerald     /// Compile-time builtins are given access to Wasmtime's [unsafe
181e069bdd3SNick Fitzgerald     /// intrinsics][CodeBuilder::expose_unsafe_intrinsics], and the same safety
182e069bdd3SNick Fitzgerald     /// invariants and portability concerns apply. However, when compile-time
183e069bdd3SNick Fitzgerald     /// builtins are defined on a `CodeBuilder`, unsafe intrinsics are *only*
184e069bdd3SNick Fitzgerald     /// exposed to the compile-time builtins, and they are *not* exposed to the
185e069bdd3SNick Fitzgerald     /// main guest Wasm program. This means that — assuming your compile-time
186e069bdd3SNick Fitzgerald     /// builtins only exposing safe APIs, encapsulating the intrinsics'
187e069bdd3SNick Fitzgerald     /// unsafety, and modulo bugs in your implementation of those safe APIs —
188e069bdd3SNick Fitzgerald     /// that the main guest Wasm program is not part of your trusted compute
189e069bdd3SNick Fitzgerald     /// base.
190e069bdd3SNick Fitzgerald     ///
191e069bdd3SNick Fitzgerald     /// # Example
192e069bdd3SNick Fitzgerald     ///
193e069bdd3SNick Fitzgerald     /// See the example in [CodeBuilder::expose_unsafe_intrinsics].
compile_time_builtins_binary( &mut self, name: impl Into<Cow<'a, str>>, wasm_bytes: impl Into<Cow<'a, [u8]>>, ) -> &mut Self194e069bdd3SNick Fitzgerald     pub unsafe fn compile_time_builtins_binary(
195e069bdd3SNick Fitzgerald         &mut self,
196e069bdd3SNick Fitzgerald         name: impl Into<Cow<'a, str>>,
197e069bdd3SNick Fitzgerald         wasm_bytes: impl Into<Cow<'a, [u8]>>,
198e069bdd3SNick Fitzgerald     ) -> &mut Self {
199e069bdd3SNick Fitzgerald         self.compile_time_builtins
200e069bdd3SNick Fitzgerald             .insert(name.into(), wasm_bytes.into());
201e069bdd3SNick Fitzgerald         self
202e069bdd3SNick Fitzgerald     }
203e069bdd3SNick Fitzgerald 
204e069bdd3SNick Fitzgerald     /// Equivalent of [`CodeBuilder::compile_time_builtins_binary`] that also
205e069bdd3SNick Fitzgerald     /// accepts the WebAssembly text format.
206e069bdd3SNick Fitzgerald     ///
207e069bdd3SNick Fitzgerald     /// This method will configure the WebAssembly binary to be compiled and
208e069bdd3SNick Fitzgerald     /// used to satisfy the `name` instance import. The input `wasm_bytes` may
209e069bdd3SNick Fitzgerald     /// either be the wasm text format or the binary format. If the `wat` crate
210e069bdd3SNick Fitzgerald     /// feature is enabled, which is enabled by default, then the text format
211e069bdd3SNick Fitzgerald     /// will automatically be converted to the binary format.
212e069bdd3SNick Fitzgerald     ///
213e069bdd3SNick Fitzgerald     /// # Errors
214e069bdd3SNick Fitzgerald     ///
215e069bdd3SNick Fitzgerald     /// This method will also return an error if `wasm_bytes` is the wasm text
216e069bdd3SNick Fitzgerald     /// format and the text syntax is not valid.
217e069bdd3SNick Fitzgerald     ///
218e069bdd3SNick Fitzgerald     /// # Safety
219e069bdd3SNick Fitzgerald     ///
220e069bdd3SNick Fitzgerald     /// See [`CodeBuilder::compile_time_builtins_binary`].
221e069bdd3SNick Fitzgerald     ///
222e069bdd3SNick Fitzgerald     /// # Example
223e069bdd3SNick Fitzgerald     ///
224e069bdd3SNick Fitzgerald     /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses
225e069bdd3SNick Fitzgerald     /// compile-time builtins.
226*7a4f53a3SPiotr Sikora     #[allow(unused_variables, reason = "`wasm_path` only used with `wat` feature")]
compile_time_builtins_binary_or_text( &mut self, name: impl Into<Cow<'a, str>>, wasm_bytes: impl Into<Cow<'a, [u8]>>, wasm_path: Option<&Path>, ) -> Result<&mut Self>227e069bdd3SNick Fitzgerald     pub unsafe fn compile_time_builtins_binary_or_text(
228e069bdd3SNick Fitzgerald         &mut self,
229e069bdd3SNick Fitzgerald         name: impl Into<Cow<'a, str>>,
230e069bdd3SNick Fitzgerald         wasm_bytes: impl Into<Cow<'a, [u8]>>,
231e069bdd3SNick Fitzgerald         wasm_path: Option<&Path>,
232e069bdd3SNick Fitzgerald     ) -> Result<&mut Self> {
233e069bdd3SNick Fitzgerald         let wasm_bytes = wasm_bytes.into();
234e069bdd3SNick Fitzgerald 
235e069bdd3SNick Fitzgerald         #[cfg(feature = "wat")]
236e069bdd3SNick Fitzgerald         if let Cow::Owned(wasm_bytes) = wat::parse_bytes(&wasm_bytes).map_err(|mut e| {
237e069bdd3SNick Fitzgerald             if let Some(path) = wasm_path {
238e069bdd3SNick Fitzgerald                 e.set_path(path);
239e069bdd3SNick Fitzgerald             }
240e069bdd3SNick Fitzgerald             e
241e069bdd3SNick Fitzgerald         })? {
242e069bdd3SNick Fitzgerald             // SAFETY: Same as our unsafe contract.
243e069bdd3SNick Fitzgerald             return Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) });
244e069bdd3SNick Fitzgerald         }
245e069bdd3SNick Fitzgerald 
246e069bdd3SNick Fitzgerald         // SAFETY: Same as our unsafe contract.
247e069bdd3SNick Fitzgerald         Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) })
248e069bdd3SNick Fitzgerald     }
249e069bdd3SNick Fitzgerald 
250e069bdd3SNick Fitzgerald     /// Like [`CodeBuilder::compile_time_builtins_binary`], but reads the `file`
251e069bdd3SNick Fitzgerald     /// specified for the bytes that will define the compile-time builtin.
252e069bdd3SNick Fitzgerald     ///
253e069bdd3SNick Fitzgerald     /// # Safety
254e069bdd3SNick Fitzgerald     ///
255e069bdd3SNick Fitzgerald     /// See [`CodeBuilder::compile_time_builtins_binary`].
256e069bdd3SNick Fitzgerald     ///
257e069bdd3SNick Fitzgerald     /// # Example
258e069bdd3SNick Fitzgerald     ///
259e069bdd3SNick Fitzgerald     /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses
260e069bdd3SNick Fitzgerald     /// compile-time builtins.
compile_time_builtins_binary_file( &mut self, name: impl Into<Cow<'a, str>>, file: &Path, ) -> Result<&mut Self>261e069bdd3SNick Fitzgerald     pub unsafe fn compile_time_builtins_binary_file(
262e069bdd3SNick Fitzgerald         &mut self,
263e069bdd3SNick Fitzgerald         name: impl Into<Cow<'a, str>>,
264e069bdd3SNick Fitzgerald         file: &Path,
265e069bdd3SNick Fitzgerald     ) -> Result<&mut Self> {
266e069bdd3SNick Fitzgerald         let wasm_bytes = std::fs::read(file)
267e069bdd3SNick Fitzgerald             .with_context(|| format!("failed to read file: {}", file.display()))?;
268e069bdd3SNick Fitzgerald         // SAFETY: Same as our unsafe contract.
269e069bdd3SNick Fitzgerald         Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) })
270e069bdd3SNick Fitzgerald     }
271e069bdd3SNick Fitzgerald 
272e069bdd3SNick Fitzgerald     /// Equivalent of [`CodeBuilder::compile_time_builtins_binary_file`] that
273e069bdd3SNick Fitzgerald     /// also accepts the WebAssembly text format.
274e069bdd3SNick Fitzgerald     ///
275e069bdd3SNick Fitzgerald     /// This method is will read the file at the given path and interpret the
276e069bdd3SNick Fitzgerald     /// contents to determine if it's the Wasm text format or binary format. The
277e069bdd3SNick Fitzgerald     /// file extension is not consulted. The text format is automatically
278e069bdd3SNick Fitzgerald     /// converted to the binary format if the crate feature `wat` is active.
279e069bdd3SNick Fitzgerald     ///
280e069bdd3SNick Fitzgerald     /// # Errors
281e069bdd3SNick Fitzgerald     ///
282e069bdd3SNick Fitzgerald     /// In addition to the errors returned by
283e069bdd3SNick Fitzgerald     /// [`CodeBuilder::compile_time_builtins_binary_file`] this may also fail if
284e069bdd3SNick Fitzgerald     /// the text format is read and the syntax is invalid.
285e069bdd3SNick Fitzgerald     ///
286e069bdd3SNick Fitzgerald     /// # Safety
287e069bdd3SNick Fitzgerald     ///
288e069bdd3SNick Fitzgerald     /// See [`CodeBuilder::compile_time_builtins_binary`].
289e069bdd3SNick Fitzgerald     ///
290e069bdd3SNick Fitzgerald     /// # Example
291e069bdd3SNick Fitzgerald     ///
292e069bdd3SNick Fitzgerald     /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses
293e069bdd3SNick Fitzgerald     /// compile-time builtins.
compile_time_builtins_binary_or_text_file( &mut self, name: impl Into<Cow<'a, str>>, file: &Path, ) -> Result<&mut Self>294e069bdd3SNick Fitzgerald     pub unsafe fn compile_time_builtins_binary_or_text_file(
295e069bdd3SNick Fitzgerald         &mut self,
296e069bdd3SNick Fitzgerald         name: impl Into<Cow<'a, str>>,
297e069bdd3SNick Fitzgerald         file: &Path,
298e069bdd3SNick Fitzgerald     ) -> Result<&mut Self> {
299e069bdd3SNick Fitzgerald         #[cfg(feature = "wat")]
300e069bdd3SNick Fitzgerald         {
301e069bdd3SNick Fitzgerald             let wasm = wat::parse_file(file)
302e069bdd3SNick Fitzgerald                 .with_context(|| format!("error parsing file: {}", file.display()))?;
303e069bdd3SNick Fitzgerald             // SAFETY: Same as our unsafe contract.
304e069bdd3SNick Fitzgerald             Ok(unsafe { self.compile_time_builtins_binary(name, wasm) })
305e069bdd3SNick Fitzgerald         }
306e069bdd3SNick Fitzgerald 
307e069bdd3SNick Fitzgerald         #[cfg(not(feature = "wat"))]
308e069bdd3SNick Fitzgerald         {
309e069bdd3SNick Fitzgerald             // SAFETY: Same as our unsafe contract.
310e069bdd3SNick Fitzgerald             unsafe { self.compile_time_builtins_binary_file(name, file) }
311e069bdd3SNick Fitzgerald         }
312e069bdd3SNick Fitzgerald     }
313e069bdd3SNick Fitzgerald }
314