1 #![allow(dead_code)] 2 3 macro_rules! gentest { 4 ($id:ident $name:tt $path:tt) => { 5 mod $id { 6 mod sugar { 7 wasmtime::component::bindgen!(in $path); 8 } 9 mod async_ { 10 wasmtime::component::bindgen!({ 11 path: $path, 12 async: true, 13 }); 14 } 15 mod tracing { 16 wasmtime::component::bindgen!({ 17 path: $path, 18 tracing: true, 19 ownership: Borrowing { 20 duplicate_if_necessary: true 21 } 22 }); 23 } 24 } 25 }; 26 } 27 28 component_macro_test_helpers::foreach!(gentest); 29 30 mod with_key_and_resources { 31 use anyhow::Result; 32 use wasmtime::component::Resource; 33 34 wasmtime::component::bindgen!({ 35 inline: " 36 package demo:pkg; 37 38 interface bar { 39 resource a; 40 resource b; 41 } 42 43 world foo { 44 resource a; 45 resource b; 46 47 import foo: interface { 48 resource a; 49 resource b; 50 } 51 52 import bar; 53 } 54 ", 55 with: { 56 "a": MyA, 57 "b": MyA, 58 "foo/a": MyA, 59 "foo/b": MyA, 60 "demo:pkg/bar/a": MyA, 61 "demo:pkg/bar/b": MyA, 62 }, 63 }); 64 65 pub struct MyA; 66 67 struct MyComponent; 68 69 impl FooImports for MyComponent {} 70 71 impl HostA for MyComponent { 72 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 73 loop {} 74 } 75 } 76 77 impl HostB for MyComponent { 78 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 79 loop {} 80 } 81 } 82 83 impl foo::Host for MyComponent {} 84 85 impl foo::HostA for MyComponent { 86 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 87 loop {} 88 } 89 } 90 91 impl foo::HostB for MyComponent { 92 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 93 loop {} 94 } 95 } 96 97 impl demo::pkg::bar::Host for MyComponent {} 98 99 impl demo::pkg::bar::HostA for MyComponent { 100 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 101 loop {} 102 } 103 } 104 105 impl demo::pkg::bar::HostB for MyComponent { 106 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 107 loop {} 108 } 109 } 110 } 111 112 mod trappable_errors_with_versioned_and_unversioned_packages { 113 wasmtime::component::bindgen!({ 114 inline: " 115 package foo:[email protected]; 116 117 interface a { 118 variant error { 119 other(string), 120 } 121 122 f: func() -> result<_, error>; 123 } 124 125 world foo { 126 import a; 127 } 128 ", 129 path: "tests/codegen/unversioned-foo.wit", 130 trappable_error_type: { 131 "foo:foo/[email protected]/error" => MyX, 132 }, 133 }); 134 135 #[allow(dead_code)] 136 type MyX = u64; 137 } 138 139 mod trappable_errors { 140 wasmtime::component::bindgen!({ 141 inline: " 142 package demo:pkg; 143 144 interface a { 145 type b = u64; 146 147 z1: func() -> result<_, b>; 148 z2: func() -> result<_, b>; 149 } 150 151 interface b { 152 use a.{b}; 153 z: func() -> result<_, b>; 154 } 155 156 interface c { 157 type b = u64; 158 } 159 160 interface d { 161 use c.{b}; 162 z: func() -> result<_, b>; 163 } 164 165 world foo { 166 import a; 167 import b; 168 import d; 169 } 170 ", 171 trappable_error_type: { 172 "demo:pkg/a/b" => MyX, 173 "demo:pkg/c/b" => MyX, 174 }, 175 }); 176 177 #[allow(dead_code)] 178 type MyX = u32; 179 } 180 181 mod interface_name_with_rust_keyword { 182 wasmtime::component::bindgen!({ 183 inline: " 184 package foo:foo; 185 186 interface crate { } 187 188 world foo { 189 export crate; 190 } 191 " 192 }); 193 } 194 195 mod with_works_with_hierarchy { 196 mod bindings { 197 wasmtime::component::bindgen!({ 198 inline: " 199 package foo:foo; 200 201 interface a { 202 record t { 203 x: u32, 204 } 205 x: func() -> t; 206 } 207 208 interface b { 209 use a.{t}; 210 x: func() -> t; 211 } 212 213 interface c { 214 use b.{t}; 215 x: func() -> t; 216 } 217 218 world foo { 219 import c; 220 } 221 " 222 }); 223 } 224 225 mod with_just_one_interface { 226 wasmtime::component::bindgen!({ 227 inline: " 228 package foo:foo; 229 230 interface a { 231 record t { 232 x: u32, 233 } 234 x: func() -> t; 235 } 236 237 interface b { 238 use a.{t}; 239 x: func() -> t; 240 } 241 242 interface c { 243 use b.{t}; 244 x: func() -> t; 245 } 246 247 world foo { 248 use c.{t}; 249 250 import x: func() -> t; 251 } 252 ", 253 with: { "foo:foo/a": super::bindings::foo::foo::a } 254 }); 255 256 struct X; 257 258 impl FooImports for X { 259 fn x(&mut self) -> super::bindings::foo::foo::a::T { 260 loop {} 261 } 262 } 263 } 264 265 mod with_whole_package { 266 wasmtime::component::bindgen!({ 267 inline: " 268 package foo:foo; 269 270 interface a { 271 record t { 272 x: u32, 273 } 274 x: func() -> t; 275 } 276 277 interface b { 278 use a.{t}; 279 x: func() -> t; 280 } 281 282 interface c { 283 use b.{t}; 284 x: func() -> t; 285 } 286 287 world foo { 288 use c.{t}; 289 290 import x: func() -> t; 291 } 292 ", 293 with: { "foo:foo": super::bindings::foo::foo } 294 }); 295 296 struct X; 297 298 impl FooImports for X { 299 fn x(&mut self) -> super::bindings::foo::foo::a::T { 300 loop {} 301 } 302 } 303 } 304 305 mod with_whole_namespace { 306 wasmtime::component::bindgen!({ 307 inline: " 308 package foo:foo; 309 310 interface a { 311 record t { 312 x: u32, 313 } 314 x: func() -> t; 315 } 316 317 interface b { 318 use a.{t}; 319 x: func() -> t; 320 } 321 322 interface c { 323 use b.{t}; 324 x: func() -> t; 325 } 326 327 world foo { 328 use c.{t}; 329 330 import x: func() -> t; 331 } 332 ", 333 with: { "foo": super::bindings::foo } 334 }); 335 336 struct X; 337 338 impl FooImports for X { 339 fn x(&mut self) -> super::bindings::foo::foo::a::T { 340 loop {} 341 } 342 } 343 } 344 } 345 346 mod trappable_imports { 347 mod none { 348 wasmtime::component::bindgen!({ 349 inline: " 350 package foo:foo; 351 352 world foo { 353 import foo: func(); 354 } 355 ", 356 trappable_imports: false, 357 }); 358 struct X; 359 360 impl FooImports for X { 361 fn foo(&mut self) {} 362 } 363 } 364 365 mod all { 366 wasmtime::component::bindgen!({ 367 inline: " 368 package foo:foo; 369 370 world foo { 371 import foo: func(); 372 } 373 ", 374 trappable_imports: true, 375 }); 376 struct X; 377 378 impl FooImports for X { 379 fn foo(&mut self) -> wasmtime::Result<()> { 380 Ok(()) 381 } 382 } 383 } 384 385 mod some { 386 wasmtime::component::bindgen!({ 387 inline: " 388 package foo:foo; 389 390 world foo { 391 import foo: func(); 392 import bar: func(); 393 } 394 ", 395 trappable_imports: ["foo"], 396 }); 397 struct X; 398 399 impl FooImports for X { 400 fn foo(&mut self) -> wasmtime::Result<()> { 401 Ok(()) 402 } 403 fn bar(&mut self) {} 404 } 405 } 406 407 mod across_interfaces { 408 use wasmtime::component::Resource; 409 410 wasmtime::component::bindgen!({ 411 inline: " 412 package foo:foo; 413 414 interface a { 415 foo: func(); 416 bar: func(); 417 418 resource r { 419 constructor(); 420 foo: func(); 421 bar: static func(); 422 } 423 } 424 425 world foo { 426 import a; 427 import foo: func(); 428 import bar: func(); 429 import i: interface { 430 foo: func(); 431 bar: func(); 432 } 433 434 } 435 ", 436 trappable_imports: ["foo"], 437 with: { "foo:foo/a/r": R }, 438 }); 439 440 struct X; 441 pub struct R; 442 443 impl FooImports for X { 444 fn foo(&mut self) -> wasmtime::Result<()> { 445 Ok(()) 446 } 447 fn bar(&mut self) {} 448 } 449 450 impl i::Host for X { 451 fn foo(&mut self) -> wasmtime::Result<()> { 452 Ok(()) 453 } 454 fn bar(&mut self) {} 455 } 456 457 impl foo::foo::a::Host for X { 458 fn foo(&mut self) -> wasmtime::Result<()> { 459 Ok(()) 460 } 461 fn bar(&mut self) {} 462 } 463 464 impl foo::foo::a::HostR for X { 465 fn new(&mut self) -> Resource<R> { 466 loop {} 467 } 468 fn foo(&mut self, _: Resource<R>) {} 469 fn bar(&mut self) {} 470 fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 471 Ok(()) 472 } 473 } 474 } 475 476 mod resources { 477 use wasmtime::component::Resource; 478 479 wasmtime::component::bindgen!({ 480 inline: " 481 package foo:foo; 482 483 interface a { 484 resource r { 485 constructor(); 486 foo: func(); 487 bar: static func(); 488 } 489 } 490 491 world foo { 492 import a; 493 494 } 495 ", 496 trappable_imports: [ 497 "[constructor]r", 498 "[method]r.foo", 499 "[static]r.bar", 500 ], 501 with: { "foo:foo/a/r": R }, 502 }); 503 504 struct X; 505 pub struct R; 506 507 impl foo::foo::a::Host for X {} 508 509 impl foo::foo::a::HostR for X { 510 fn new(&mut self) -> wasmtime::Result<Resource<R>> { 511 loop {} 512 } 513 fn foo(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 514 Ok(()) 515 } 516 fn bar(&mut self) -> wasmtime::Result<()> { 517 Ok(()) 518 } 519 fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 520 Ok(()) 521 } 522 } 523 } 524 } 525 526 mod custom_derives { 527 use std::collections::{hash_map::RandomState, HashSet}; 528 529 wasmtime::component::bindgen!({ 530 inline: " 531 package my:inline; 532 533 interface blah { 534 variant abc { 535 a, 536 b, 537 c 538 } 539 540 record foo { 541 field1: string, 542 field2: list<u32>, 543 field3: abc 544 } 545 546 bar: func(cool: foo); 547 } 548 549 world baz { 550 import blah; 551 } 552 ", 553 // Clone is included by default almost everywhere, so include it here to make sure it 554 // doesn't conflict 555 additional_derives: [serde::Serialize, serde::Deserialize, Hash, Clone, PartialEq, Eq], 556 }); 557 558 use my::inline::blah::{Abc, Foo, Host}; 559 560 struct X; 561 562 impl Host for X { 563 fn bar(&mut self, cool: Foo) { 564 // Check that built in derives that I've added actually work by seeing that this hashes 565 let _blah: HashSet<Foo, RandomState> = HashSet::from_iter([Foo { 566 field1: "hello".to_string(), 567 field2: vec![1, 2, 3], 568 field3: Abc::B, 569 }]); 570 571 // Check that the attributes from an external crate actually work. If they don't work, 572 // compilation will fail here 573 let _ = serde_json::to_string(&cool); 574 } 575 } 576 } 577