Skip to content

Commit 3ad66a5

Browse files
committed
no_std support in the Rust guest bindings.
This adds no_std support in the Rust guest bindings. Mostly this involves using `core` and `alloc` instead of `std`, but it also involves adding `extern crate alloc;` in a few places, and also adding a `"std"` cargo feature to gen-guest-rust so that the `impl std::error::Error` can be made conditional. This will eventually be useful for generating bindings from the WASI wit files for std itself to use. And, it's useful for experimenting with generating minimal bindings.
1 parent fc35377 commit 3ad66a5

File tree

8 files changed

+63
-29
lines changed

8 files changed

+63
-29
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ wat = "1.0.49"
3333

3434
wit-bindgen-core = { path = 'crates/bindgen-core', version = '0.2.0' }
3535
wit-bindgen-gen-guest-c = { path = 'crates/gen-guest-c', version = '0.2.0' }
36-
wit-bindgen-gen-guest-rust = { path = "crates/gen-guest-rust", version = "0.2.0" }
36+
wit-bindgen-gen-guest-rust = { path = "crates/gen-guest-rust", version = "0.2.0", default-features = false }
3737
wit-bindgen-gen-guest-teavm-java = { path = 'crates/gen-guest-teavm-java', version = '0.2.0' }
3838
wit-bindgen-gen-host-js = { path = 'crates/gen-host-js', version = '0.2.0' }
3939
wit-bindgen-gen-host-wasmtime-py = { path = 'crates/gen-host-wasmtime-py', version = '0.2.0' }
4040
wit-bindgen-gen-host-wasmtime-rust = { path = 'crates/gen-host-wasmtime-rust', version = '0.2.0' }
4141
wit-bindgen-gen-markdown = { path = 'crates/gen-markdown', version = '0.2.0' }
42-
wit-bindgen-gen-rust-lib = { path = 'crates/gen-rust-lib', version = '0.2.0' }
43-
wit-bindgen-guest-rust = { path = 'crates/guest-rust', version = '0.2.0' }
42+
wit-bindgen-gen-rust-lib = { path = 'crates/gen-rust-lib', version = '0.2.0', default-features = false }
43+
wit-bindgen-guest-rust = { path = 'crates/guest-rust', version = '0.2.0', default-features = false }
4444
wit-bindgen-host-wasmtime-rust = { path = 'crates/host-wasmtime-rust', version = '0.2.0' }
4545
wit-parser = { path = 'crates/wit-parser', version = '0.2.0' }
4646
wit-component = { path = 'crates/wit-component', version = '0.2.0' }

crates/gen-guest-rust/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ clap = { workspace = true, optional = true }
1717
[dev-dependencies]
1818
wit-bindgen-guest-rust = { path = '../guest-rust' }
1919
test-helpers = { path = '../test-helpers', features = ['guest-rust'] }
20+
21+
[features]
22+
default = ["std"]
23+
std = ["wit-bindgen-gen-rust-lib/std"]

crates/gen-guest-rust/src/lib.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ impl Generator for RustWasm {
510510
} = f;
511511

512512
if needs_cleanup_list {
513-
self.src.push_str("let mut cleanup_list = Vec::new();\n");
513+
self.src.push_str("extern crate alloc;\n");
514+
self.src
515+
.push_str("let mut cleanup_list = alloc::vec::Vec::new();\n");
514516
}
515517
self.src.push_str(&String::from(src));
516518

@@ -758,14 +760,15 @@ impl FunctionBindgen<'_> {
758760
fn emit_cleanup(&mut self) {
759761
for (ptr, layout) in mem::take(&mut self.cleanup) {
760762
self.push_str(&format!(
761-
"if {layout}.size() != 0 {{\nstd::alloc::dealloc({ptr}, {layout});\n}}\n"
763+
"if {layout}.size() != 0 {{\nextern crate alloc;\nalloc::alloc::dealloc({ptr}, {layout});\n}}\n"
762764
));
763765
}
764766
if self.needs_cleanup_list {
765767
self.push_str(
766768
"for (ptr, layout) in cleanup_list {\n
767769
if layout.size() != 0 {\n
768-
std::alloc::dealloc(ptr, layout);\n
770+
extern crate alloc;\n
771+
alloc::alloc::dealloc(ptr, layout);\n
769772
}\n
770773
}\n",
771774
);
@@ -1231,7 +1234,7 @@ impl Bindgen for FunctionBindgen<'_> {
12311234
assert_eq!(none, "()");
12321235
let operand = &operands[0];
12331236
let invalid = if unchecked {
1234-
"std::hint::unreachable_unchecked()"
1237+
"core::hint::unreachable_unchecked()"
12351238
} else {
12361239
"panic!(\"invalid enum discriminant\")"
12371240
};
@@ -1268,7 +1271,7 @@ impl Bindgen for FunctionBindgen<'_> {
12681271
let ok = self.blocks.pop().unwrap();
12691272
let operand = &operands[0];
12701273
let invalid = if unchecked {
1271-
"std::hint::unreachable_unchecked()"
1274+
"core::hint::unreachable_unchecked()"
12721275
} else {
12731276
"panic!(\"invalid enum discriminant\")"
12741277
};
@@ -1343,8 +1346,9 @@ impl Bindgen for FunctionBindgen<'_> {
13431346
let tmp = self.tmp();
13441347
let len = format!("len{}", tmp);
13451348
self.push_str(&format!("let {} = {} as usize;\n", len, operands[1]));
1349+
self.push_str("extern crate alloc;\n");
13461350
let result = format!(
1347-
"Vec::from_raw_parts({} as *mut _, {1}, {1})",
1351+
"alloc::vec::Vec::from_raw_parts({} as *mut _, {1}, {1})",
13481352
operands[0], len
13491353
);
13501354
results.push(result);
@@ -1374,14 +1378,21 @@ impl Bindgen for FunctionBindgen<'_> {
13741378
let tmp = self.tmp();
13751379
let len = format!("len{}", tmp);
13761380
self.push_str(&format!("let {} = {} as usize;\n", len, operands[1]));
1381+
self.push_str("extern crate alloc;\n");
13771382
let result = format!(
1378-
"Vec::from_raw_parts({} as *mut _, {1}, {1})",
1383+
"alloc::vec::Vec::from_raw_parts({} as *mut _, {1}, {1})",
13791384
operands[0], len
13801385
);
13811386
if unchecked {
1382-
results.push(format!("String::from_utf8_unchecked({})", result));
1387+
results.push(format!(
1388+
"alloc::string::String::from_utf8_unchecked({})",
1389+
result
1390+
));
13831391
} else {
1384-
results.push(format!("String::from_utf8({}).unwrap()", result));
1392+
results.push(format!(
1393+
"alloc::string::String::from_utf8({}).unwrap()",
1394+
result
1395+
));
13851396
}
13861397
}
13871398

@@ -1403,12 +1414,12 @@ impl Bindgen for FunctionBindgen<'_> {
14031414
"let {layout} = core::alloc::Layout::from_size_align_unchecked({vec}.len() * {size}, {align});\n",
14041415
));
14051416
self.push_str(&format!(
1406-
"let {result} = if {layout}.size() != 0\n{{\nlet ptr = std::alloc::alloc({layout});\n",
1417+
"let {result} = if {layout}.size() != 0\n{{\nextern crate alloc;\nlet ptr = alloc::alloc::alloc({layout});\n",
14071418
));
14081419
self.push_str(&format!(
1409-
"if ptr.is_null()\n{{\nstd::alloc::handle_alloc_error({layout});\n}}\nptr\n}}",
1420+
"if ptr.is_null()\n{{\nextern crate alloc;\nalloc::alloc::handle_alloc_error({layout});\n}}\nptr\n}}",
14101421
));
1411-
self.push_str(&format!("else {{\nstd::ptr::null_mut()\n}};\n",));
1422+
self.push_str(&format!("else {{\ncore::ptr::null_mut()\n}};\n",));
14121423
self.push_str(&format!("for (i, e) in {vec}.into_iter().enumerate() {{\n",));
14131424
self.push_str(&format!(
14141425
"let base = {result} as i32 + (i as i32) * {size};\n",
@@ -1442,8 +1453,9 @@ impl Bindgen for FunctionBindgen<'_> {
14421453
"let {len} = {operand1};\n",
14431454
operand1 = operands[1]
14441455
));
1456+
self.push_str("extern crate alloc;\n");
14451457
self.push_str(&format!(
1446-
"let mut {result} = Vec::with_capacity({len} as usize);\n",
1458+
"let mut {result} = alloc::vec::Vec::with_capacity({len} as usize);\n",
14471459
));
14481460

14491461
self.push_str("for i in 0..");

crates/gen-rust-lib/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ test = false
1111
[dependencies]
1212
wit-bindgen-core = { workspace = true }
1313
heck = { workspace = true }
14+
15+
[features]
16+
default = ["std"]
17+
std = []

crates/gen-rust-lib/src/lib.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ pub trait RustGenerator {
213213
TypeMode::AllBorrowed(lt) | TypeMode::LeafBorrowed(lt) => {
214214
self.print_borrowed_str(lt)
215215
}
216-
TypeMode::Owned | TypeMode::HandlesBorrowed(_) => self.push_str("String"),
216+
TypeMode::Owned | TypeMode::HandlesBorrowed(_) => {
217+
self.push_str("alloc::string::String")
218+
}
217219
},
218220
}
219221
}
@@ -335,13 +337,13 @@ pub trait RustGenerator {
335337
if iface.all_bits_valid(ty) {
336338
self.print_borrowed_slice(iface, false, ty, lt);
337339
} else {
338-
self.push_str("Vec<");
340+
self.push_str("alloc::vec::Vec<");
339341
self.print_ty(iface, ty, mode);
340342
self.push_str(">");
341343
}
342344
}
343345
TypeMode::HandlesBorrowed(_) | TypeMode::Owned => {
344-
self.push_str("Vec<");
346+
self.push_str("alloc::vec::Vec<");
345347
self.print_ty(iface, ty, mode);
346348
self.push_str(">");
347349
}
@@ -828,9 +830,11 @@ pub trait RustGenerator {
828830
self.push_str("}\n");
829831
self.push_str("}\n");
830832
self.push_str("\n");
831-
self.push_str("impl std::error::Error for ");
832-
self.push_str(&name);
833-
self.push_str("{}\n");
833+
if cfg!(feature = "std") {
834+
self.push_str("impl std::error::Error for ");
835+
self.push_str(&name);
836+
self.push_str("{}\n");
837+
}
834838
} else {
835839
self.print_rust_enum_debug(
836840
id,

crates/guest-rust-macro/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ proc-macro2 = "1.0"
1414
syn = "1.0"
1515
wit-bindgen-core = { workspace = true }
1616
wit-bindgen-gen-guest-rust = { workspace = true }
17+
18+
[features]
19+
default = ["std"]
20+
std = ["wit-bindgen-gen-guest-rust/std"]

crates/guest-rust/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ version.workspace = true
55
edition.workspace = true
66

77
[dependencies]
8-
wit-bindgen-guest-rust-macro = { path = "../guest-rust-macro", optional = true }
8+
wit-bindgen-guest-rust-macro = { path = "../guest-rust-macro", optional = true, default-features = false }
99
bitflags = { workspace = true }
1010

1111
[features]
12-
default = ["macros"]
12+
default = ["macros", "std"]
1313
macros = ["wit-bindgen-guest-rust-macro"]
14+
std = ["wit-bindgen-guest-rust-macro/std"]

crates/guest-rust/src/lib.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
use std::fmt;
2-
use std::marker;
3-
use std::mem;
4-
use std::ops::Deref;
1+
#![no_std]
2+
3+
extern crate alloc;
4+
5+
use alloc::boxed::Box;
6+
use core::fmt;
7+
use core::marker;
8+
use core::mem;
9+
use core::ops::Deref;
510

611
#[cfg(feature = "macros")]
712
pub use wit_bindgen_guest_rust_macro::{export, import};
@@ -123,7 +128,7 @@ pub unsafe trait LocalHandle: HandleType {
123128

124129
#[doc(hidden)]
125130
pub mod rt {
126-
use std::alloc::{self, Layout};
131+
use ::alloc::alloc::{self, Layout};
127132

128133
#[no_mangle]
129134
unsafe extern "C" fn cabi_realloc(

0 commit comments

Comments
 (0)