Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-config/src/lib.rs
1692 views
1
//! # Wasmtime's [wasi-config] Implementation
2
//!
3
//! This crate provides a Wasmtime host implementation of the [wasi-config]
4
//! API. With this crate, the runtime can run components that call APIs in
5
//! [wasi-config] and provide configuration variables for the component.
6
//!
7
//! # Examples
8
//!
9
//! The usage of this crate is very similar to other WASI API implementations
10
//! such as [wasi:cli] and [wasi:http].
11
//!
12
//! A common scenario is getting runtime-passed configurations in a [wasi:cli]
13
//! component. A standalone example of doing all this looks like:
14
//!
15
//! ```
16
//! use wasmtime::{
17
//! component::{Linker, ResourceTable},
18
//! Config, Engine, Result, Store,
19
//! };
20
//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
21
//! use wasmtime_wasi_config::{WasiConfig, WasiConfigVariables};
22
//!
23
//! #[tokio::main]
24
//! async fn main() -> Result<()> {
25
//! let mut config = Config::new();
26
//! config.async_support(true);
27
//! let engine = Engine::new(&config)?;
28
//!
29
//! let mut store = Store::new(&engine, Ctx {
30
//! table: ResourceTable::new(),
31
//! wasi_ctx: WasiCtx::builder().build(),
32
//! wasi_config_vars: WasiConfigVariables::from_iter(vec![
33
//! ("config_key1", "value1"),
34
//! ("config_key2", "value2"),
35
//! ]),
36
//! });
37
//!
38
//! let mut linker = Linker::<Ctx>::new(&engine);
39
//! wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
40
//! // add `wasi-config` world's interfaces to the linker
41
//! wasmtime_wasi_config::add_to_linker(&mut linker, |h: &mut Ctx| {
42
//! WasiConfig::from(&h.wasi_config_vars)
43
//! })?;
44
//!
45
//! // ... use `linker` to instantiate within `store` ...
46
//!
47
//! Ok(())
48
//! }
49
//!
50
//! struct Ctx {
51
//! table: ResourceTable,
52
//! wasi_ctx: WasiCtx,
53
//! wasi_config_vars: WasiConfigVariables,
54
//! }
55
//!
56
//! impl WasiView for Ctx {
57
//! fn ctx(&mut self) -> WasiCtxView<'_> {
58
//! WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }
59
//! }
60
//! }
61
//! ```
62
//!
63
//! [wasi-config]: https://github.com/WebAssembly/wasi-config
64
//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest
65
//! [wasi:http]: https://docs.rs/wasmtime-wasi-http/latest
66
67
#![deny(missing_docs)]
68
69
use anyhow::Result;
70
use std::collections::HashMap;
71
use wasmtime::component::HasData;
72
73
mod gen_ {
74
wasmtime::component::bindgen!({
75
path: "wit",
76
world: "wasi:config/imports",
77
imports: { default: trappable },
78
});
79
}
80
use self::gen_::wasi::config::store as generated;
81
82
/// Capture the state necessary for use in the `wasi-config` API implementation.
83
#[derive(Default)]
84
pub struct WasiConfigVariables(HashMap<String, String>);
85
86
impl<S: Into<String>> FromIterator<(S, S)> for WasiConfigVariables {
87
fn from_iter<I: IntoIterator<Item = (S, S)>>(iter: I) -> Self {
88
Self(
89
iter.into_iter()
90
.map(|(k, v)| (k.into(), v.into()))
91
.collect(),
92
)
93
}
94
}
95
96
impl WasiConfigVariables {
97
/// Create a new runtime configuration.
98
pub fn new() -> Self {
99
Default::default()
100
}
101
102
/// Insert a key-value pair into the configuration map.
103
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) -> &mut Self {
104
self.0.insert(key.into(), value.into());
105
self
106
}
107
}
108
109
/// A wrapper capturing the needed internal `wasi-config` state.
110
pub struct WasiConfig<'a> {
111
vars: &'a WasiConfigVariables,
112
}
113
114
impl<'a> From<&'a WasiConfigVariables> for WasiConfig<'a> {
115
fn from(vars: &'a WasiConfigVariables) -> Self {
116
Self { vars }
117
}
118
}
119
120
impl<'a> WasiConfig<'a> {
121
/// Create a new view into the `wasi-config` state.
122
pub fn new(vars: &'a WasiConfigVariables) -> Self {
123
Self { vars }
124
}
125
}
126
127
impl generated::Host for WasiConfig<'_> {
128
fn get(&mut self, key: String) -> Result<Result<Option<String>, generated::Error>> {
129
Ok(Ok(self.vars.0.get(&key).map(|s| s.to_owned())))
130
}
131
132
fn get_all(&mut self) -> Result<Result<Vec<(String, String)>, generated::Error>> {
133
Ok(Ok(self
134
.vars
135
.0
136
.iter()
137
.map(|(k, v)| (k.to_string(), v.to_string()))
138
.collect()))
139
}
140
}
141
142
/// Add all the `wasi-config` world's interfaces to a [`wasmtime::component::Linker`].
143
pub fn add_to_linker<T: 'static>(
144
l: &mut wasmtime::component::Linker<T>,
145
f: fn(&mut T) -> WasiConfig<'_>,
146
) -> Result<()> {
147
generated::add_to_linker::<T, HasWasiConfig>(l, f)?;
148
Ok(())
149
}
150
151
struct HasWasiConfig;
152
153
impl HasData for HasWasiConfig {
154
type Data<'a> = WasiConfig<'a>;
155
}
156
157