Skip to main content

polymorph_webcrypto_wasmtime/
standalone.rs

1//! Ready-made embedding for hosts whose component imports only
2//! `polymorph:webcrypto`: the canonical store state and the engine/linker/store
3//! setup this repository's drivers share (the demo host and the
4//! conformance adapter), so the engine configuration the async imports
5//! require has one definition.
6//!
7//! Hosts with store state of their own implement [`WasiWebcryptoView`] on
8//! their own type and call [`add_to_linker`](crate::add_to_linker)
9//! directly instead.
10
11use std::path::Path;
12
13use wasmtime::component::{Component, HasData, Linker, ResourceTable};
14use wasmtime::error::Context as _;
15use wasmtime::{Config, Engine, Store};
16
17use crate::{WasiWebcryptoCtx, WasiWebcryptoCtxView, WasiWebcryptoView};
18
19/// The store state: the WebCrypto host context plus the resource table its
20/// keys and computations live in.
21pub struct Ctx {
22    /// The WebCrypto host context.
23    pub webcrypto: WasiWebcryptoCtx,
24    /// The table the host's resources live in.
25    pub table: ResourceTable,
26}
27
28impl HasData for Ctx {
29    type Data<'a> = &'a mut Self;
30}
31
32impl WasiWebcryptoView for Ctx {
33    fn webcrypto(&mut self) -> WasiWebcryptoCtxView<'_> {
34        WasiWebcryptoCtxView {
35            ctx: &mut self.webcrypto,
36            table: &mut self.table,
37        }
38    }
39}
40
41/// An engine configured for the component-model async ABI the
42/// `polymorph:webcrypto` imports use.
43pub fn engine() -> wasmtime::Result<Engine> {
44    let mut config = Config::new();
45    config.wasm_component_model(true);
46    config.wasm_component_model_async(true);
47    Engine::new(&config)
48}
49
50/// Load the component at `path` and prepare everything an instantiation
51/// needs: a linker with the `polymorph:webcrypto` imports added, and a store
52/// whose state carries `webcrypto`.
53pub fn load(
54    path: &Path,
55    webcrypto: WasiWebcryptoCtx,
56) -> wasmtime::Result<(Component, Linker<Ctx>, Store<Ctx>)> {
57    let engine = engine()?;
58    let component = Component::from_file(&engine, path)
59        .with_context(|| format!("loading component {}", path.display()))?;
60    let mut linker: Linker<Ctx> = Linker::new(&engine);
61    // The canned embedding is the demo and conformance-driver path, and
62    // the conformance manifest declares the wasmtime target missing no
63    // features — so the `@unstable`-gated interfaces are all served here,
64    // unlike `add_to_linker`'s default.
65    crate::add_to_linker_with_options(
66        &mut linker,
67        crate::LinkOptions::default()
68            .sha1_checked(true)
69            .rsa_sign(true)
70            .rsa_oaep_decrypt(true),
71    )?;
72    let store = Store::new(
73        &engine,
74        Ctx {
75            webcrypto,
76            table: ResourceTable::new(),
77        },
78    );
79    Ok((component, linker, store))
80}