Skip to main content

add_named_to_linker

Function add_named_to_linker 

Source
pub fn add_named_to_linker<T>(
    linker: &mut Linker<T>,
    component: &Component,
    lookup: impl FnMut(Interface, &str) -> Result<NamedId>,
) -> Result<()>
Available on crate feature p3 only.
Expand description

Add all interfaces from this module into the linker provided for any named imports that a component has.

This function is similar to add_to_linker except that it’s specifically designed to work with named imports of wasi:http interfaces that components may have. This requires a Component parameter to be passed in when populating the Linker provided to see what the Component actually imports.

If this isn’t low level enough you can invoke the bindgen-generated add_to_linker functions within the named_imports module directly instead.

The lookup function provided here is invoked for every named import found for a particular interface. The Interface given is what’s being bound, and the &str argument is the name that the component imports it as. The embedder can then decide how it would like to allocate a NamedId for this import. If Ok is returned then the linker is populated with this name, and imported functions will pass the NamedId later to the implementation of WasiHttpNamedView on T when invoked. If Err is returned then the error will cause this entire function to fail and this function call will return the same error.

§Example

use std::collections::HashMap;
use wasmtime::component::{Component, Linker, ResourceTable};
use wasmtime::{Engine, Result, Store, Config};
use wasmtime_wasi::NamedId;
use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpCtxView, WasiHttpNamedView};

fn main() -> Result<()> {
    let mut config = Config::new();
    config.wasm_component_model_async(true);
    let engine = Engine::new(&config)?;
    let component = Component::new(&engine, "(component)")?;

    let mut linker = Linker::<MyState>::new(&engine);

    // ... add default functionality to `linker` as needed ...

    // and then additionally fill in any specific named imports `component`
    // might have for `wasi:http` interfaces.
    let mut name_map = HashMap::new();
    wasmtime_wasi_http::p3::add_named_to_linker(&mut linker, &component, |_i, name| {
        let len = name_map.len();
        Ok(NamedId(*name_map.entry(name.to_string()).or_insert(len)))
    })?;

    // Here a `WasiHttpCtx` is allocated per-named-import and will then be
    // referred to internally by the [`NamedId`] allocated above. You could
    // also use `name_map` to configure each context differently.
    let mut my_state = MyState::default();
    for _ in 0..name_map.len() {
        my_state.contexts.push(WasiHttpCtx::default());
    }
    let mut store = Store::new(&engine, my_state);

    // ... use `linker` to instantiate within `store` ...

    Ok(())
}

#[derive(Default)]
struct MyState {
    table: ResourceTable,
    contexts: Vec<WasiHttpCtx>,
}

impl WasiHttpNamedView for MyState {
    fn http(&mut self, id: NamedId) -> WasiHttpCtxView<'_> {
        WasiHttpCtxView {
            ctx: &mut self.contexts[id.0],
            table: &mut self.table,
            hooks: Default::default(),
        }
    }
}