Add a wasmtime::component::bindgen! macro (#5317)
* Import Wasmtime support from the `wit-bindgen` repo This commit imports the `wit-bindgen-gen-host-wasmtime-rust` crate from the `wit-bindgen` repository into the upstream Wasmtime repository. I've chosen to not import the full history here since the crate is relatively small and doesn't have a ton of complexity. While the history of the crate is quite long the current iteration of the crate's history is relatively short so there's not a ton of import there anyway. The thinking is that this can now continue to evolve in-tree. * Refactor `wasmtime-component-macro` a bit Make room for a `wit_bindgen` macro to slot in. * Add initial support for a `bindgen` macro * Add tests for `wasmtime::component::bindgen!` * Improve error forgetting `async` feature * Add end-to-end tests for bindgen * Add an audit of `unicase` * Add a license to the test-helpers crate * Add vet entry for `pulldown-cmark` * Update publish script with new crate * Try to fix publish script * Update audits * Update lock file
This commit is contained in:
130
crates/wit-bindgen/src/source.rs
Normal file
130
crates/wit-bindgen/src/source.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
use std::fmt::{self, Write};
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Helper structure to maintain indentation automatically when printing.
|
||||
#[derive(Default)]
|
||||
pub struct Source {
|
||||
s: String,
|
||||
indent: usize,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
pub fn push_str(&mut self, src: &str) {
|
||||
let lines = src.lines().collect::<Vec<_>>();
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with('}') && self.s.ends_with(" ") {
|
||||
self.s.pop();
|
||||
self.s.pop();
|
||||
}
|
||||
self.s.push_str(if lines.len() == 1 {
|
||||
line
|
||||
} else {
|
||||
line.trim_start()
|
||||
});
|
||||
if trimmed.ends_with('{') {
|
||||
self.indent += 1;
|
||||
}
|
||||
if trimmed.starts_with('}') {
|
||||
// Note that a `saturating_sub` is used here to prevent a panic
|
||||
// here in the case of invalid code being generated in debug
|
||||
// mode. It's typically easier to debug those issues through
|
||||
// looking at the source code rather than getting a panic.
|
||||
self.indent = self.indent.saturating_sub(1);
|
||||
}
|
||||
if i != lines.len() - 1 || src.ends_with('\n') {
|
||||
self.newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indent(&mut self, amt: usize) {
|
||||
self.indent += amt;
|
||||
}
|
||||
|
||||
pub fn deindent(&mut self, amt: usize) {
|
||||
self.indent -= amt;
|
||||
}
|
||||
|
||||
fn newline(&mut self) {
|
||||
self.s.push('\n');
|
||||
for _ in 0..self.indent {
|
||||
self.s.push_str(" ");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_mut_string(&mut self) -> &mut String {
|
||||
&mut self.s
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Source {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.push_str(s);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Source {
|
||||
type Target = str;
|
||||
fn deref(&self) -> &str {
|
||||
&self.s
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Source> for String {
|
||||
fn from(s: Source) -> String {
|
||||
s.s
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Source;
|
||||
|
||||
#[test]
|
||||
fn simple_append() {
|
||||
let mut s = Source::default();
|
||||
s.push_str("x");
|
||||
assert_eq!(s.s, "x");
|
||||
s.push_str("y");
|
||||
assert_eq!(s.s, "xy");
|
||||
s.push_str("z ");
|
||||
assert_eq!(s.s, "xyz ");
|
||||
s.push_str(" a ");
|
||||
assert_eq!(s.s, "xyz a ");
|
||||
s.push_str("\na");
|
||||
assert_eq!(s.s, "xyz a \na");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newline_remap() {
|
||||
let mut s = Source::default();
|
||||
s.push_str("function() {\n");
|
||||
s.push_str("y\n");
|
||||
s.push_str("}\n");
|
||||
assert_eq!(s.s, "function() {\n y\n}\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_else() {
|
||||
let mut s = Source::default();
|
||||
s.push_str("if() {\n");
|
||||
s.push_str("y\n");
|
||||
s.push_str("} else if () {\n");
|
||||
s.push_str("z\n");
|
||||
s.push_str("}\n");
|
||||
assert_eq!(s.s, "if() {\n y\n} else if () {\n z\n}\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trim_ws() {
|
||||
let mut s = Source::default();
|
||||
s.push_str(
|
||||
"function() {
|
||||
x
|
||||
}",
|
||||
);
|
||||
assert_eq!(s.s, "function() {\n x\n}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user