/// Runs a WebAssembly workload.
// TODO: refactor this into multiple steps
// Since we're not bundling the launch/deployment config into `bytes`, the
// naive solution would just be to add new arguments for those things, like
// WasmFeatures, stdio handling, etc - but that gets messy quick.
// Instead we should probably refactor this into distinct steps, each with
// its own config options (and error variants - see above).
Runs a WebAssembly workload.
TODO: refactor this into multiple steps
Since we're not bundling the launch/deployment config into `bytes`, the
naive solution would just be to add new arguments for those things, like
WasmFeatures, stdio handling, etc - but that gets messy quick.
Instead we should probably refactor this into distinct steps, each with
its own config options (and error variants - see above).
Runs a WebAssembly workload . TODO : refactor this into multiple steps Since we ' re not bundling the launch / deployment config into ` bytes ` the naive solution would just be to add new arguments for those things like WasmFeatures stdio handling etc - but that gets messy quick . Instead we should probably refactor this into distinct steps each with its own config options ( and error variants - see above ) .
pub fn run(bytes: impl AsRef<[u8]>, ldr_config: &config::Config) -> Result<Vec<wasmtime::Val>> {
    debug!("configuring wasmtime engine");
    let mut config = wasmtime::Config::new();
    // Support module-linking (https://github.com/webassembly/module-linking)
    config.wasm_module_linking(true);
    // module-linking requires multi-memory
    config.wasm_multi_memory(true);
    // Prefer dynamic memory allocation style over static memory
    config.static_memory_maximum_size(0);
    config.static_memory_guard_size(0);
    config.dynamic_memory_guard_size(0);
    config.dynamic_memory_reserved_for_growth(16 * 1024 * 1024);
    let engine = wasmtime::Engine::new(&config).or(Err(Error::ConfigurationError))?;
    debug!("instantiating wasmtime linker");
    let mut linker = wasmtime::Linker::new(&engine);
    // TODO: read config, set up filehandles & sockets, etc etc
    debug!("adding WASI to linker");
    wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;
    debug!("creating WASI context");
    let mut wasi = WasiCtxBuilder::new();
    debug!("Processing loader config {:#?}", &ldr_config);
    if let Some(ref files) = ldr_config.files {
        for file in files {
            match (file.type_.as_ref(), file.name.as_ref()) {
                ("stdio", "stdin") => wasi = wasi.inherit_stdin(),
                ("stdio", "stdout") => wasi = wasi.inherit_stdout(),
                ("stdio", "stderr") => wasi = wasi.inherit_stderr(),
                _ => {}
            }
        }
    }
    let mut num_fd = 3;
    let mut fd_names: Vec<String> = Vec::new();
    if let Some(ref files) = ldr_config.files {
        for file in files {
            match file.type_.as_ref() {
                "tcp_listen" => {
                    let port = file
                        .port
                        .expect("Config file `tcp_listen` has no `port` field set");
                    let addr = file.addr.clone().unwrap_or_else(|| ":::".to_string());
                    let stdlistener = std::net::TcpListener::bind((addr.as_str(), port))
                        .unwrap_or_else(|e| panic!("Could not bind to {addr}:{port}: {e}"));
                    stdlistener
                        .set_nonblocking(true)
                        .expect("Could not set nonblocking on TcpListener");
                    wasi = wasi.preopened_socket(num_fd, TcpListener::from_std(stdlistener))?;
                    num_fd += 1;
                    wasi = wasi.env("LISTEN_FDS", &(num_fd - 3).to_string())?;
                    fd_names.push(file.name.clone())
                }
                "stdio" => {}
                field => {
                    panic!("Unknown field '{field}' in config file");
                }
            }
        }
        if !fd_names.is_empty() {
            wasi = wasi.env("LISTEN_FDNAMES", &fd_names.join(":"))?;
        }
    }
    debug!("creating wasmtime Store");
    let mut store = wasmtime::Store::new(&engine, wasi.build());
    debug!("instantiating module from bytes");
    let module = wasmtime::Module::from_binary(&engine, bytes.as_ref())?;
    debug!("adding module to store");
    linker
        .module(&mut store, "", &module)
        .or(Err(Error::InstantiationFailed))?;
    // TODO: use the --invoke FUNCTION name, if any
    debug!("getting module's default function");
    let func = linker
        .get_default(&mut store, "")
        .or(Err(Error::ExportNotFound))?;
    debug!("calling function");
    let mut results = vec![wasmtime::Val::null(); func.ty(&store).results().len()];
    func.call(store, Default::default(), &mut results)
        .or(Err(Error::CallFailed))?;
    Ok(results)
}
pub fn run ( bytes : impl AsRef < [ u8 ] > , ldr_config : & config :: Config ) -> Result < Vec < wasmtime :: Val > > { debug ! ( " " ) ; let mut config = wasmtime :: Config :: new ( ) ; // Support module-linking (https://github.com/webassembly/module-linking) config . wasm_module_linking ( true ) ; // module-linking requires multi-memory config . wasm_multi_memory ( true ) ; // Prefer dynamic memory allocation style over static memory config . static_memory_maximum_size ( 0 ) ; config . static_memory_guard_size ( 0 ) ; config . dynamic_memory_guard_size ( 0 ) ; config . dynamic_memory_reserved_for_growth ( 16 * 1024 * 1024 ) ; let engine = wasmtime :: Engine :: new ( & config ) . or ( Err ( Error :: ConfigurationError ) ) ? ; debug ! ( " " ) ; let mut linker = wasmtime :: Linker :: new ( & engine ) ; // TODO: read config, set up filehandles & sockets, etc etc debug ! ( " " ) ; wasmtime_wasi :: add_to_linker ( & mut linker , | s | s ) ? ; debug ! ( " " ) ; let mut wasi = WasiCtxBuilder :: new ( ) ; debug ! ( " " ldr_config ) ; if let Some ( ref files ) = ldr_config . files { for file in files { match ( file . type_ . as_ref ( ) , file . name . as_ref ( ) ) { ( " " , " " ) => wasi = wasi . inherit_stdin ( ) , ( " " , " " ) => wasi = wasi . inherit_stdout ( ) , ( " " , " " ) => wasi = wasi . inherit_stderr ( ) , _ => { } } } } let mut num_fd = 3 ; let mut fd_names : Vec < String > = Vec :: new ( ) ; if let Some ( ref files ) = ldr_config . files { for file in files { match file . type_ . as_ref ( ) { " " => { let port = file . port . expect ( " " ) ; let addr = file . addr . clone ( ) . unwrap_or_else ( | | " " . to_string ( ) ) ; let stdlistener = std :: net :: TcpListener :: bind ( ( addr . as_str ( ) , port ) ) . unwrap_or_else ( | e | panic ! ( " " ) ) ; stdlistener . set_nonblocking ( true ) . expect ( " " ) ; wasi = wasi . preopened_socket ( num_fd , TcpListener :: from_std ( stdlistener ) ) ? ; num_fd += 1 ; wasi = wasi . env ( " " , & ( num_fd - 3 ) . to_string ( ) ) ? ; fd_names . push ( file . name . clone ( ) ) } " " => { } field => { panic ! ( " " ) ; } } } if ! fd_names . is_empty ( ) { wasi = wasi . env ( " " , & fd_names . join ( " " ) ) ? ; } } debug ! ( " " ) ; let mut store = wasmtime :: Store :: new ( & engine , wasi . build ( ) ) ; debug ! ( " " ) ; let module = wasmtime :: Module :: from_binary ( & engine , bytes . as_ref ( ) ) ? ; debug ! ( " " ) ; linker . module ( & mut store , " " , & module ) . or ( Err ( Error :: InstantiationFailed ) ) ? ; // TODO: use the --invoke FUNCTION name, if any debug ! ( " " ) ; let func = linker . get_default ( & mut store , " " ) . or ( Err ( Error :: ExportNotFound ) ) ? ; debug ! ( " " ) ; let mut results = vec ! [ wasmtime Val null ( ) func ty ( store ) results ( ) len ( ) ] ; func . call ( store , Default :: default ( ) , & mut results ) . or ( Err ( Error :: CallFailed ) ) ? ; Ok ( results ) }
Runs a WebAssembly workload.
Runs a WebAssembly workload .
bytes
impl AsRef<[u8]>
ldr_config
&config::Config