Skip to content

Commit 20ac32f

Browse files
committed
This works actually kinda nicely but runs into a bit of a disaster with WIT merging
Signed-off-by: itowlson <[email protected]>
1 parent 0a558bc commit 20ac32f

File tree

3 files changed

+34
-41
lines changed

3 files changed

+34
-41
lines changed

src/commands/add.rs

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ impl AddCommand {
165165
// manifest: &manifest,
166166
root_dir,
167167
target_component,
168-
component_id: &selected_component,
169168
package_name: &package,
170169
interfaces: &interfaces,
171170
rel_wit_path: &output_wit_path
@@ -356,17 +355,15 @@ fn qualified_itf_name(package_name: &wit_parser::PackageName, interface_name: &s
356355
}
357356

358357
struct BindOMatic<'a> {
359-
// manifest: &'a AppManifest,
360358
root_dir: &'a Path,
361359
target_component: &'a spin_manifest::schema::v2::Component,
362-
component_id: &'a str,
363360
package_name: &'a wit_parser::PackageName,
364361
interfaces: &'a [String],
365362
rel_wit_path: &'a Path,
366363
}
367364

368365
enum Language {
369-
Rust { cargo_toml: PathBuf },
366+
Rust,
370367
#[allow(dead_code)] // for now
371368
TypeScript { package_json: PathBuf },
372369
}
@@ -385,7 +382,7 @@ impl<'a> BindOMatic<'a> {
385382

386383
let cargo_toml = build_dir.join("Cargo.toml");
387384
if cargo_toml.is_file() {
388-
return Ok(Language::Rust { cargo_toml });
385+
return Ok(Language::Rust);
389386
}
390387
let package_json = build_dir.join("package.json");
391388
if package_json.is_file() {
@@ -399,50 +396,33 @@ impl<'a> BindOMatic<'a> {
399396

400397
async fn try_generate_bindings<'a>(target: &'a BindOMatic<'a>) -> anyhow::Result<()> {
401398
match target.try_infer_language()? {
402-
Language::Rust { cargo_toml } => generate_rust_bindings(target.root_dir, &cargo_toml, target.component_id, target.package_name, target.interfaces, target.rel_wit_path).await,
399+
Language::Rust => generate_rust_bindings(target.root_dir, target.package_name, target.interfaces, target.rel_wit_path).await,
403400
Language::TypeScript { package_json: _ } => todo!(),
404401
}
405402
}
406403

407-
async fn generate_rust_bindings(root_dir: &Path, cargo_toml: &Path, _component_id: &str, package_name: &wit_parser::PackageName, interfaces: &[String], rel_wit_path: &Path) -> anyhow::Result<()> {
408-
// add wit-bindgen to cargo.toml if needed
409-
let mut did_change = false;
410-
let cargo_text = std::fs::read_to_string(cargo_toml)?;
411-
let mut cargo_doc: toml_edit::DocumentMut = cargo_text.parse()?;
412-
let deps = cargo_doc.entry("dependencies");
413-
match deps {
414-
toml_edit::Entry::Occupied(mut occupied_entry) => {
415-
let Some(deps_table) = occupied_entry.get_mut().as_table_mut() else {
416-
return Err(anyhow!("existing dependencies table is... not a table"));
417-
};
418-
if !deps_table.contains_key("wit-bindgen") {
419-
let wbg_ver = toml_edit::Formatted::new("0.34.0".to_owned());
420-
deps_table.insert("wit-bindgen", toml_edit::Item::Value(toml_edit::Value::String(wbg_ver)));
421-
did_change = true;
422-
}
423-
},
424-
toml_edit::Entry::Vacant(vacant_entry) => {
425-
let mut deps_table = toml_edit::Table::new();
426-
let wbg_ver = toml_edit::Formatted::new("0.34.0".to_owned());
427-
deps_table.insert("wit-bindgen", toml_edit::Item::Value(toml_edit::Value::String(wbg_ver)));
428-
vacant_entry.insert(toml_edit::Item::Table(deps_table));
429-
did_change = true;
430-
},
431-
};
432-
let new_cargo_text = cargo_doc.to_string();
433-
if did_change {
434-
std::fs::write(cargo_toml, new_cargo_text)?;
435-
}
436-
404+
async fn generate_rust_bindings(root_dir: &Path, package_name: &wit_parser::PackageName, interfaces: &[String], rel_wit_path: &Path) -> anyhow::Result<()> {
437405
// now set up the bindings
438406
let deps_rs_dir = root_dir.join("src/deps");
439407
fs::create_dir_all(&deps_rs_dir).await?;
440408
let dep_module_name = crate::language::rust::identifier_safe(package_name);
441409

442410
// step 1: create a module with the generate! macro
443-
let imps = interfaces.iter().filter(|itf| !crate::language::rust::is_stdlib_known(itf)).map(|i| format!(r#" import {i};"#)).collect::<Vec<_>>();
411+
let imps = interfaces.iter()
412+
.filter(|itf| !crate::language::rust::is_stdlib_known(itf))
413+
.map(|i| format!(r#" import {i};"#)).collect::<Vec<_>>();
444414
let imps = imps.join("\n");
445-
let gens = interfaces.iter().filter(|itf| !crate::language::rust::is_stdlib_known(itf)).map(|i| format!(r#" "{i}": generate,"#)).collect::<Vec<_>>();
415+
let gens = interfaces.iter()
416+
.filter(|itf| !crate::language::rust::is_stdlib_known(itf))
417+
.map(|i| if crate::language::rust::is_sdk_known(i) {
418+
let (qname, _) = i.split_once("@").unwrap(); // foo:bar/baz
419+
let rust_qname = qname.replace(":", "::").replace("/", "::").replace("-", "_");
420+
let sdk_form = format!("spin_sdk::wit::{rust_qname}"); // TODO: this doesn't allow for when multiple versions are present! when that happens, but ONLY when that happens, bindgen version-mangles the name
421+
format!(r#" "{i}": {sdk_form},"#)
422+
} else {
423+
format!(r#" "{i}": generate,"#)
424+
}
425+
).collect::<Vec<_>>();
446426
let gens = gens.join("\n");
447427
let gen_name = format!("{}-{}", package_name.namespace, package_name.name);
448428

src/commands/gen.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
wit_bindgen::generate!({
1+
::spin_sdk::wit_bindgen::generate!({
22
inline: r#"
33
package imported:{!gen_name!};
44
world imports {

src/language/rust.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ pub fn identifier_safe(package_name: &wit_parser::PackageName) -> String {
44

55
// TODO: moar
66
const STDLIB_INTERFACES: &[&str] = &[
7-
"wasi:io/[email protected]",
8-
"wasi:io/[email protected]",
97
"wasi:cli/[email protected]",
108
"wasi:cli/[email protected]",
119
"wasi:cli/[email protected]",
@@ -14,6 +12,17 @@ const STDLIB_INTERFACES: &[&str] = &[
1412
"wasi:clocks/[email protected]",
1513
"wasi:filesystem/[email protected]",
1614
"wasi:filesystem/[email protected]",
15+
"wasi:io/[email protected]",
16+
"wasi:io/[email protected]",
17+
"wasi:random/[email protected]",
18+
];
19+
20+
const SPIN_SDK_INTERFACES: &[&str] = &[
21+
"wasi:http/[email protected]", // TODO: or maybe this is different again
22+
"wasi:keyvalue/[email protected]",
23+
"wasi:keyvalue/[email protected]",
24+
"wasi:keyvalue/[email protected]",
25+
"wasi:config/[email protected]",
1726
];
1827

1928
// Interfaces that are implemented by stdlib and shouldn't be bound explicitly
@@ -22,3 +31,7 @@ const STDLIB_INTERFACES: &[&str] = &[
2231
pub fn is_stdlib_known(interface_name: &str) -> bool {
2332
STDLIB_INTERFACES.contains(&interface_name)
2433
}
34+
35+
pub fn is_sdk_known(interface_name: &str) -> bool {
36+
SPIN_SDK_INTERFACES.contains(&interface_name) || interface_name.starts_with("spin:")
37+
}

0 commit comments

Comments
 (0)