Path: blob/main/crates/wasi-config/src/lib.rs
1692 views
//! # Wasmtime's [wasi-config] Implementation1//!2//! This crate provides a Wasmtime host implementation of the [wasi-config]3//! API. With this crate, the runtime can run components that call APIs in4//! [wasi-config] and provide configuration variables for the component.5//!6//! # Examples7//!8//! The usage of this crate is very similar to other WASI API implementations9//! such as [wasi:cli] and [wasi:http].10//!11//! A common scenario is getting runtime-passed configurations in a [wasi:cli]12//! component. A standalone example of doing all this looks like:13//!14//! ```15//! use wasmtime::{16//! component::{Linker, ResourceTable},17//! Config, Engine, Result, Store,18//! };19//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};20//! use wasmtime_wasi_config::{WasiConfig, WasiConfigVariables};21//!22//! #[tokio::main]23//! async fn main() -> Result<()> {24//! let mut config = Config::new();25//! config.async_support(true);26//! let engine = Engine::new(&config)?;27//!28//! let mut store = Store::new(&engine, Ctx {29//! table: ResourceTable::new(),30//! wasi_ctx: WasiCtx::builder().build(),31//! wasi_config_vars: WasiConfigVariables::from_iter(vec![32//! ("config_key1", "value1"),33//! ("config_key2", "value2"),34//! ]),35//! });36//!37//! let mut linker = Linker::<Ctx>::new(&engine);38//! wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;39//! // add `wasi-config` world's interfaces to the linker40//! wasmtime_wasi_config::add_to_linker(&mut linker, |h: &mut Ctx| {41//! WasiConfig::from(&h.wasi_config_vars)42//! })?;43//!44//! // ... use `linker` to instantiate within `store` ...45//!46//! Ok(())47//! }48//!49//! struct Ctx {50//! table: ResourceTable,51//! wasi_ctx: WasiCtx,52//! wasi_config_vars: WasiConfigVariables,53//! }54//!55//! impl WasiView for Ctx {56//! fn ctx(&mut self) -> WasiCtxView<'_> {57//! WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }58//! }59//! }60//! ```61//!62//! [wasi-config]: https://github.com/WebAssembly/wasi-config63//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest64//! [wasi:http]: https://docs.rs/wasmtime-wasi-http/latest6566#![deny(missing_docs)]6768use anyhow::Result;69use std::collections::HashMap;70use wasmtime::component::HasData;7172mod gen_ {73wasmtime::component::bindgen!({74path: "wit",75world: "wasi:config/imports",76imports: { default: trappable },77});78}79use self::gen_::wasi::config::store as generated;8081/// Capture the state necessary for use in the `wasi-config` API implementation.82#[derive(Default)]83pub struct WasiConfigVariables(HashMap<String, String>);8485impl<S: Into<String>> FromIterator<(S, S)> for WasiConfigVariables {86fn from_iter<I: IntoIterator<Item = (S, S)>>(iter: I) -> Self {87Self(88iter.into_iter()89.map(|(k, v)| (k.into(), v.into()))90.collect(),91)92}93}9495impl WasiConfigVariables {96/// Create a new runtime configuration.97pub fn new() -> Self {98Default::default()99}100101/// Insert a key-value pair into the configuration map.102pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) -> &mut Self {103self.0.insert(key.into(), value.into());104self105}106}107108/// A wrapper capturing the needed internal `wasi-config` state.109pub struct WasiConfig<'a> {110vars: &'a WasiConfigVariables,111}112113impl<'a> From<&'a WasiConfigVariables> for WasiConfig<'a> {114fn from(vars: &'a WasiConfigVariables) -> Self {115Self { vars }116}117}118119impl<'a> WasiConfig<'a> {120/// Create a new view into the `wasi-config` state.121pub fn new(vars: &'a WasiConfigVariables) -> Self {122Self { vars }123}124}125126impl generated::Host for WasiConfig<'_> {127fn get(&mut self, key: String) -> Result<Result<Option<String>, generated::Error>> {128Ok(Ok(self.vars.0.get(&key).map(|s| s.to_owned())))129}130131fn get_all(&mut self) -> Result<Result<Vec<(String, String)>, generated::Error>> {132Ok(Ok(self133.vars134.0135.iter()136.map(|(k, v)| (k.to_string(), v.to_string()))137.collect()))138}139}140141/// Add all the `wasi-config` world's interfaces to a [`wasmtime::component::Linker`].142pub fn add_to_linker<T: 'static>(143l: &mut wasmtime::component::Linker<T>,144f: fn(&mut T) -> WasiConfig<'_>,145) -> Result<()> {146generated::add_to_linker::<T, HasWasiConfig>(l, f)?;147Ok(())148}149150struct HasWasiConfig;151152impl HasData for HasWasiConfig {153type Data<'a> = WasiConfig<'a>;154}155156157