Skip to content

Commit

Permalink
Support wasm32-wasip2 (#44)
Browse files Browse the repository at this point in the history
* Support wasm32-wasip2

* Fix random unit test
  • Loading branch information
eliabieri authored Dec 5, 2024
1 parent b12ca7b commit c588414
Show file tree
Hide file tree
Showing 13 changed files with 1,345 additions and 710 deletions.
1,818 changes: 1,215 additions & 603 deletions app/Cargo.lock

Large diffs are not rendered by default.

33 changes: 17 additions & 16 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,34 @@ license-file = "LICENSE"
common = { path = "../common" }

# General
anyhow = "1.0.68"
tokio = { version = "1.28.1", features = ["full"] }
anyhow = "1.0.89"
tokio = { version = "1.40.0", features = ["full"] }

# Widgets
openssl = { version = "0.10", features = ["vendored"] }
async-trait = "0.1.58"
futures = "0.3.25"
wasmtime = { version = "12.0.1", features = ["component-model"] }
log = "0.4.17"
simple_logger = "4.1.0"
reqwest = { version = "0.11.16", features = ["blocking", "json"] }
serde_json = "1.0.96"
openssl = { version = "0.10.67", features = ["vendored"] }
async-trait = "0.1.83"
futures = "0.3.31"
wasmtime = { version = "27.0.0", features = ["component-model"] }
wasmtime-wasi = "27.0.0"
log = "0.4.22"
simple_logger = "5.0.0"
reqwest = { version = "0.12.8", features = ["blocking", "json"] }
serde_json = "1.0.128"
bincode = "1.3.3"
rand = "0.8.5"

# Rendering
cursive = { git = "https://github.com/gyscos/cursive", features = [
"termion-backend",
], default-features = false }
hostname = "0.3.1"
hostname = "0.4.0"

# Server
time = { version = "0.3.17", features = ["serde-well-known"] }
rocket = { version = "0.5.0-rc.3", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
rust-embed = { version = "8.0.0", features = ["include-exclude"] }
time = { version = "0.3.36", features = ["serde-well-known"] }
rocket = { version = "0.5.1", features = ["json"] }
serde = { version = "1.0.210", features = ["derive"] }
rust-embed = { version = "8.5.0", features = ["include-exclude"] }

# Persistence
sled = "0.34.7"
lazy_static = "1.4.0"
lazy_static = "1.5.0"
3 changes: 1 addition & 2 deletions app/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ async fn install_widget(action: json::Json<InstallAction>) -> Result<(), Custom<
Err(err) => {
let err = format!(
"Could not install widget from URL {}: {}",
download_url,
err.root_cause()
download_url, err
);
log::error!("{}", err);
Err(Custom(rocket::http::Status::InternalServerError, err))
Expand Down
6 changes: 3 additions & 3 deletions app/src/widgets/host_api/clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::widgets::running::runtime::widget::widget::clocks;
use crate::widgets::running::runtime::WidgetState;

impl clocks::Host for WidgetState {
fn now(&mut self) -> wasmtime::Result<clocks::Datetime> {
fn now(&mut self) -> clocks::Datetime {
let now = std::time::SystemTime::now();
let now = now.duration_since(UNIX_EPOCH).unwrap();
Ok(clocks::Datetime {
clocks::Datetime {
seconds: now.as_secs(),
nanoseconds: now.subsec_nanos(),
})
}
}
}
13 changes: 8 additions & 5 deletions app/src/widgets/host_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ impl http::Host for WidgetState {
method: http::Method,
url: String,
body: Option<Vec<u8>>,
) -> wasmtime::Result<Result<http::Response, ()>> {
) -> Result<http::Response, ()> {
let client = reqwest::blocking::Client::new();
let response = match method {
http::Method::Get => client.get(url).send(),
Expand All @@ -23,12 +23,15 @@ impl http::Host for WidgetState {
http::Method::Delete => client.delete(url).send(),
};
match response {
Ok(response) => Ok(Ok(http::Response {
Ok(response) => Ok(http::Response {
content_length: response.content_length(),
status: response.status().as_u16(),
bytes: response.bytes()?.to_vec(),
})),
Err(_) => Ok(Err(())),
bytes: match response.bytes() {
Ok(bytes) => bytes.to_vec(),
Err(_) => Vec::new(),
},
}),
Err(_) => Err(()),
}
}
}
3 changes: 1 addition & 2 deletions app/src/widgets/host_api/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ impl logging::Host for WidgetState {
level: logging::Level,
context: String,
message: String,
) -> wasmtime::Result<()> {
) {
const PREFIX: &str = "WIDGET";
match level {
logging::Level::Debug => log::debug!("{}: {}: {}", PREFIX, context, message),
logging::Level::Info => log::info!("{}: {}: {}", PREFIX, context, message),
logging::Level::Warn => log::warn!("{}: {}: {}", PREFIX, context, message),
logging::Level::Error => log::error!("{}: {}: {}", PREFIX, context, message),
}
Ok(())
}
}
14 changes: 8 additions & 6 deletions app/src/widgets/host_api/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@ use crate::widgets::running::runtime::widget::widget::random;
use crate::widgets::running::runtime::WidgetState;
use rand::prelude::*;

fn get_random() -> u64 {
let mut rng = thread_rng();
rng.next_u64()
}

impl random::Host for WidgetState {
fn get_random(&mut self) -> wasmtime::Result<u64> {
let mut rng = thread_rng();
Ok(rng.next_u64())
fn get_random(&mut self) -> u64 {
get_random()
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::widgets::running::runtime::widget::widget::random::Host;

#[test]
fn test_get_random() {
let mut widget_state = WidgetState {};
let result = widget_state.get_random().unwrap();
let result = get_random();
assert!(result > 0);
}
}
25 changes: 20 additions & 5 deletions app/src/widgets/running/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,28 @@ use wasmtime::{
component::{Component, Linker},
Config, Engine, Store,
};
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiView};

use crate::widgets::running::runtime::widget::widget::clocks::Datetime;
use crate::widgets::utils::logging::LOGGING_PREFIX;

wasmtime::component::bindgen!({ path: "../wg_display_widget_wit/wit", world: "widget" });
wasmtime::component::bindgen!({ path: "../wg_display_widget_wit/wit" });

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct CompiledWidget {
pub data: Vec<u8>,
compatibility_hash: u64,
}

pub struct WidgetState;
pub struct WidgetState {
ctx: WasiCtx,
table: ResourceTable,
}

impl WasiView for WidgetState {
fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}

pub struct Runtime {
engine: Engine,
Expand All @@ -38,8 +47,14 @@ impl Runtime {
Config::wasm_component_model(&mut config, true);

let engine = Engine::new(&config).expect("Could not create engine");
let store = Store::new(&engine, WidgetState {});
let mut linker = Linker::new(&engine);
let mut linker = Linker::<WidgetState>::new(&engine);
wasmtime_wasi::add_to_linker_sync(&mut linker).expect("Could not link WASI functions");
let mut builder = WasiCtxBuilder::new();
let state = WidgetState {
ctx: builder.build(),
table: ResourceTable::new(),
};
let store = Store::new(&engine, state);
Widget::add_to_linker(&mut linker, |state: &mut WidgetState| state)
.expect("Could not link host API");

Expand Down Expand Up @@ -87,7 +102,7 @@ impl Runtime {
// https://docs.rs/wasmtime/9.0.2/wasmtime/component/struct.Component.html#method.deserialize
let start = std::time::Instant::now();
let component = unsafe { Component::deserialize(&self.engine, &widget.data) }?;
let (widget, _) = Widget::instantiate(&mut self.store, &component, &self.linker)?;
let widget = Widget::instantiate(&mut self.store, &component, &self.linker)?;
let duration = start.elapsed();
log::info!(
"{}: Deserialized and instantiated widget in {} ms",
Expand Down
Loading

0 comments on commit c588414

Please sign in to comment.