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