Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[target.wasm32-wasip2]
# wasmtime is given:
# * p3 enabled for wasip3 component support (backwards compat with p2)
# * http enabled for wasi-http tests
# * AWS auth environment variables, for running the wstd-aws integration tests.
# * . directory is available at .
runner = "wasmtime run -Shttp --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN --dir .::."
runner = "wasmtime run -Wcomponent-model-async -Wcomponent-model-async-builtins -Wcomponent-model-async-stackful -Sp3 -Shttp --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN --dir .::."
5 changes: 4 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ jobs:
- name: check
run: cargo check --workspace --all --bins --examples

- name: wstd tests
- name: wstd tests (wasip2)
run: cargo test -p wstd -p wstd-axum --target wasm32-wasip2 -- --nocapture

- name: wstd tests (wasip3)
run: cargo test -p wstd -p wstd-axum --target wasm32-wasip2 --no-default-features --features wasip3,json -- --nocapture

- name: test-programs tests
run: cargo test -p test-programs -- --nocapture
if: steps.creds.outcome == 'success'
Expand Down
23 changes: 19 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ repository.workspace = true
rust-version.workspace = true

[features]
default = ["json"]
default = ["json", "wasip2"]
json = ["dep:serde", "dep:serde_json"]
wasip2 = ["dep:wasip2"]
wasip3 = ["dep:wasip3", "dep:wit-bindgen"]

[build-dependencies]
cfg_aliases = "0.2"

[dependencies]
anyhow.workspace = true
Expand All @@ -27,13 +32,21 @@ http.workspace = true
itoa.workspace = true
pin-project-lite.workspace = true
slab.workspace = true
wasip2.workspace = true
wasip2 = { workspace = true, optional = true }
wasip3 = { workspace = true, optional = true }
wit-bindgen = { workspace = true, optional = true }
wstd-macro.workspace = true

# optional
serde = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }

# Auto-pull wasip3 deps when targeting wasm32-wasip3 so users don't need
# to also pass --features wasip3.
[target.'cfg(all(target_os = "wasi", target_env = "p3"))'.dependencies]
wasip3 = { workspace = true }
wit-bindgen = { workspace = true }

[dev-dependencies]
anyhow.workspace = true
clap.workspace = true
Expand Down Expand Up @@ -95,13 +108,15 @@ test-programs = { path = "test-programs" }
tower-service = "0.3.3"
ureq = { version = "3.1", default-features = false, features = ["json"] }
wasip2 = "1.0"
wstd = { path = ".", version = "=0.6.6" }
wasip3 = "0.5"
wit-bindgen = { version = "0.54", default-features = false, features = ["async", "async-spawn", "inter-task-wakeup"] }
wstd = { path = ".", version = "=0.6.6", default-features = false }
wstd-axum = { path = "./axum", version = "=0.6.6" }
wstd-axum-macro = { path = "./axum/macro", version = "=0.6.6" }
wstd-macro = { path = "./macro", version = "=0.6.6" }

[package.metadata.docs.rs]
all-features = true
targets = [
"wasm32-wasip2"
"wasm32-wasip2",
]
7 changes: 6 additions & 1 deletion axum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ categories.workspace = true
repository.workspace = true
rust-version.workspace = true

[features]
default = ["wasip2"]
wasip2 = ["wstd/wasip2"]
wasip3 = ["wstd/wasip3"]

[dependencies]
axum.workspace = true
tower-service.workspace = true
wstd.workspace = true
wstd = { workspace = true, default-features = false }
wstd-axum-macro.workspace = true

[dev-dependencies]
Expand Down
13 changes: 13 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use cfg_aliases::cfg_aliases;

fn main() {
cfg_aliases! {
// True when targeting a wasip3 component, either via the explicit
// `wasip3` feature or the `wasm32-wasip3` target (`target_env = "p3"`).
wstd_p3: { any(feature = "wasip3", target_env = "p3") },
// True when targeting a wasip2 component, either via the `wasip2`
// feature (default) or the `wasm32-wasip2` target. wasip3 takes
// precedence when both apply.
wstd_p2: { all(any(feature = "wasip2", target_env = "p2"), not(wstd_p3)) },
}
}
83 changes: 23 additions & 60 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,6 @@ pub fn attr_macro_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn attr_macro_http_server(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);

let (run_async, run_await) = if input.sig.asyncness.is_some() {
(quote!(async), quote!(.await))
} else {
(quote!(), quote!())
};

let output = &input.sig.output;
let inputs = &input.sig.inputs;
let name = &input.sig.ident;
Expand All @@ -120,63 +114,32 @@ pub fn attr_macro_http_server(_attr: TokenStream, item: TokenStream) -> TokenStr
.into();
}

// Delegate to wstd's conditionally-compiled declarative macro.
// The `cfg` checks in `__http_server_export!` run in wstd's context,
// so consumers don't need to define wasip2/wasip3 features themselves.
//
// We use @async/@sync markers so the declarative macro can construct
// the handler call in its own hygiene context (avoiding variable name
// mismatches between proc macro and declarative macro scopes)
// NOTE: we can avoid this once wasm32-wasip3 is an available target
let asyncness = if input.sig.asyncness.is_some() {
quote!(@async)
} else {
quote!(@sync)
};

let run_async = if input.sig.asyncness.is_some() {
quote!(async)
} else {
quote!()
};

quote! {
struct TheServer;

impl ::wstd::__internal::wasip2::exports::http::incoming_handler::Guest for TheServer {
fn handle(
request: ::wstd::__internal::wasip2::http::types::IncomingRequest,
response_out: ::wstd::__internal::wasip2::http::types::ResponseOutparam
) {
#(#attrs)*
#vis #run_async fn __run(#inputs) #output {
#body
}

let responder = ::wstd::http::server::Responder::new(response_out);
::wstd::runtime::block_on(async move {
match ::wstd::http::request::try_from_incoming(request) {
Ok(request) => match __run(request) #run_await {
Ok(response) => { responder.respond(response).await.unwrap() },
Err(err) => responder.fail(err),
}
Err(err) => responder.fail(err),
}
})
}
::wstd::__http_server_export! {
#asyncness
{ #(#attrs)* #vis #run_async fn __run(#inputs) #output { #body } }
}

::wstd::__internal::wasip2::http::proxy::export!(TheServer with_types_in ::wstd::__internal::wasip2);

// Provide an actual function named `main`.
//
// WASI HTTP server components don't use a traditional `main` function.
// They export a function named `handle` which takes a `Request`
// argument, and which may be called multiple times on the same
// instance. To let users write a familiar `fn main` in a file
// named src/main.rs, we provide this `wstd::http_server` macro, which
// transforms the user's `fn main` into the appropriate `handle`
// function.
//
// However, when the top-level file is named src/main.rs, rustc
// requires there to be a function named `main` somewhere in it. This
// requirement can be disabled using `#![no_main]`, however we can't
// use that automatically because macros can't contain inner
// attributes, and we don't want to require users to add `#![no_main]`
// in their own code.
//
// So, we include a definition of a function named `main` here, which
// isn't intended to ever be called, and exists just to satify the
// requirement for a `main` function.
//
// Users could use `#![no_main]` if they want to. Or, they could name
// their top-level file src/lib.rs and add
// ```toml
// [lib]
// crate-type = ["cdylib"]
// ```
// to their Cargo.toml. With either of these, this "main" function will
// be ignored as dead code.
fn main() {
unreachable!("HTTP server components should be run with `handle` rather than `run`")
}
Expand Down
Loading
Loading