-
Notifications
You must be signed in to change notification settings - Fork 0
/
smoke.rs
152 lines (123 loc) · 4 KB
/
smoke.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use anyhow::Result;
use wasmtime::component::{Component, Linker};
use wasmtime::{Config, Engine, Store};
use wasmtime_wasi::preview2::wasi;
use wasmtime_wasi::preview2::{Table, WasiCtx, WasiCtxBuilder, WasiView};
// Use the WIT world named smoke at ./wit
wasmtime::component::bindgen!({
path: "wit",
world: "smoke",
async: true
});
lazy_static::lazy_static! {
static ref ENGINE: Engine = {
let mut config = Config::new();
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
config.wasm_component_model(true);
config.async_support(true);
Engine::new(&config).unwrap()
};
}
/// Struct to hold the data we want to pass in
/// plus the WASI properties in order to use WASI
pub struct MyImports {
hit: bool,
wasi_ctx: Context,
}
struct Context {
table: Table,
wasi: WasiCtx,
}
// We need to impl to be able to use the WASI linker add_to_linker
impl WasiView for MyImports {
fn table(&self) -> &Table {
&self.wasi_ctx.table
}
fn table_mut(&mut self) -> &mut Table {
&mut self.wasi_ctx.table
}
fn ctx(&self) -> &WasiCtx {
&self.wasi_ctx.wasi
}
fn ctx_mut(&mut self) -> &mut WasiCtx {
&mut self.wasi_ctx.wasi
}
}
/// Implementations of the host functions
#[async_trait::async_trait]
impl mypackage::smoke::imports::Host for MyImports {
async fn thunk(&mut self, msg: String) -> Result<String> {
self.hit = true;
println!("in the host");
let new_msg = format!("{} ({})", msg, "from the host");
Ok(new_msg)
}
async fn prnt(&mut self, msg: String) -> Result<()> {
println!("in the host: {msg}");
Ok(())
}
}
/// Helper function to abstract the instantiation of the WASM module
/// [`Smoke`] is the name of the WIT world we're using
pub async fn instantiate(
component: Component,
wasi_ctx: MyImports,
) -> Result<(Store<MyImports>, Smoke)> {
let mut linker = Linker::new(&ENGINE);
// add wasi io, filesystem, clocks, cli_base, random, poll
wasi::command::add_to_linker(&mut linker)?;
// link OUR imports
Smoke::add_to_linker(&mut linker, |x| x)?;
let mut store = Store::new(&ENGINE, wasi_ctx);
let (reactor, _instance) = Smoke::instantiate_async(&mut store, &component, &linker).await?;
Ok((store, reactor))
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> wasmtime::Result<()> {
// time execution
let wasm = std::env::var("CARGO_PKG_NAME")?.replace('-', "_");
let start = std::time::Instant::now();
let component = Component::from_file(&ENGINE, format!("dist/{wasm}.component.wasm"))?;
// time to read file
let last = start.elapsed();
eprintln!("Time elapsed in reading file is: {:?}", last);
let mut table = Table::new();
let wasi = WasiCtxBuilder::new()
.set_args(&["gussie", "sparky", "willa"])
.build(&mut table)?;
let (mut store, smoke_reactor) = instantiate(
component,
MyImports {
hit: false,
wasi_ctx: Context { table, wasi },
},
)
.await?;
// time to load
eprintln!(
"Time elapsed in loading is: {:?} (+{:?})",
start.elapsed(),
start.elapsed() - last
);
let last = start.elapsed();
let out = smoke_reactor
.call_think(&mut store, "original message")
.await?;
println!("{out}");
let thx = smoke_reactor
.mypackage_smoke_demo()
.call_thank(&mut store, "god")
.await?;
eprintln!("Wut: {thx}");
smoke_reactor.direct().call_pank(&mut store).await?;
assert!(store.data().hit);
// time to execute
eprintln!(
"Time elapsed in executing is: {:?} (+{:?})",
start.elapsed(),
start.elapsed() - last
);
// total time
eprintln!("Total time elapsed is: {:?}", start.elapsed());
Ok(())
}