├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── build.rs ├── index.html ├── some-c-code ├── gcd.c ├── gcd.h └── main.c └── src ├── bindings.rs ├── lib.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /bin 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anstream" 16 | version = "0.6.11" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" 19 | dependencies = [ 20 | "anstyle", 21 | "anstyle-parse", 22 | "anstyle-query", 23 | "anstyle-wincon", 24 | "colorchoice", 25 | "utf8parse", 26 | ] 27 | 28 | [[package]] 29 | name = "anstyle" 30 | version = "1.0.6" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" 33 | 34 | [[package]] 35 | name = "anstyle-parse" 36 | version = "0.2.3" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" 39 | dependencies = [ 40 | "utf8parse", 41 | ] 42 | 43 | [[package]] 44 | name = "anstyle-query" 45 | version = "1.0.2" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" 48 | dependencies = [ 49 | "windows-sys 0.52.0", 50 | ] 51 | 52 | [[package]] 53 | name = "anstyle-wincon" 54 | version = "3.0.2" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" 57 | dependencies = [ 58 | "anstyle", 59 | "windows-sys 0.52.0", 60 | ] 61 | 62 | [[package]] 63 | name = "anyhow" 64 | version = "1.0.79" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" 67 | 68 | [[package]] 69 | name = "autocfg" 70 | version = "1.1.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 73 | 74 | [[package]] 75 | name = "bindgen" 76 | version = "0.69.4" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" 79 | dependencies = [ 80 | "bitflags 2.4.2", 81 | "cexpr", 82 | "clang-sys", 83 | "itertools", 84 | "lazy_static", 85 | "lazycell", 86 | "log", 87 | "prettyplease", 88 | "proc-macro2", 89 | "quote", 90 | "regex", 91 | "rustc-hash", 92 | "shlex", 93 | "syn", 94 | "which 4.4.2", 95 | ] 96 | 97 | [[package]] 98 | name = "bitflags" 99 | version = "1.3.2" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 102 | 103 | [[package]] 104 | name = "bitflags" 105 | version = "2.4.2" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" 108 | 109 | [[package]] 110 | name = "camino" 111 | version = "1.1.6" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" 114 | dependencies = [ 115 | "serde", 116 | ] 117 | 118 | [[package]] 119 | name = "cargo-options" 120 | version = "0.7.2" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "cad71bf996c8e5b9d28ef3472d7ee41f277edf4e38cd597f51ad0438d05d76ea" 123 | dependencies = [ 124 | "anstyle", 125 | "clap", 126 | ] 127 | 128 | [[package]] 129 | name = "cargo-platform" 130 | version = "0.1.7" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" 133 | dependencies = [ 134 | "serde", 135 | ] 136 | 137 | [[package]] 138 | name = "cargo-zigbuild" 139 | version = "0.18.3" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "cb76e6ab558f9138291c7e1fa954ffd58e060712eab13f97a317da712218ca24" 142 | dependencies = [ 143 | "anyhow", 144 | "cargo-options", 145 | "cargo_metadata", 146 | "clap", 147 | "dirs", 148 | "fat-macho", 149 | "fs-err", 150 | "path-slash", 151 | "rustc_version", 152 | "semver", 153 | "serde", 154 | "serde_json", 155 | "shlex", 156 | "target-lexicon", 157 | "which 6.0.0", 158 | ] 159 | 160 | [[package]] 161 | name = "cargo_metadata" 162 | version = "0.18.1" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" 165 | dependencies = [ 166 | "camino", 167 | "cargo-platform", 168 | "semver", 169 | "serde", 170 | "serde_json", 171 | "thiserror", 172 | ] 173 | 174 | [[package]] 175 | name = "cc" 176 | version = "1.0.83" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 179 | dependencies = [ 180 | "libc", 181 | ] 182 | 183 | [[package]] 184 | name = "cexpr" 185 | version = "0.6.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 188 | dependencies = [ 189 | "nom", 190 | ] 191 | 192 | [[package]] 193 | name = "cfg-if" 194 | version = "1.0.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 197 | 198 | [[package]] 199 | name = "clang-sys" 200 | version = "1.7.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" 203 | dependencies = [ 204 | "glob", 205 | "libc", 206 | "libloading", 207 | ] 208 | 209 | [[package]] 210 | name = "clap" 211 | version = "4.5.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" 214 | dependencies = [ 215 | "clap_builder", 216 | "clap_derive", 217 | ] 218 | 219 | [[package]] 220 | name = "clap_builder" 221 | version = "4.5.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" 224 | dependencies = [ 225 | "anstream", 226 | "anstyle", 227 | "clap_lex", 228 | "strsim", 229 | "terminal_size", 230 | ] 231 | 232 | [[package]] 233 | name = "clap_derive" 234 | version = "4.5.0" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" 237 | dependencies = [ 238 | "heck", 239 | "proc-macro2", 240 | "quote", 241 | "syn", 242 | ] 243 | 244 | [[package]] 245 | name = "clap_lex" 246 | version = "0.7.0" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" 249 | 250 | [[package]] 251 | name = "colorchoice" 252 | version = "1.0.0" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 255 | 256 | [[package]] 257 | name = "dirs" 258 | version = "5.0.1" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" 261 | dependencies = [ 262 | "dirs-sys", 263 | ] 264 | 265 | [[package]] 266 | name = "dirs-sys" 267 | version = "0.4.1" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" 270 | dependencies = [ 271 | "libc", 272 | "option-ext", 273 | "redox_users", 274 | "windows-sys 0.48.0", 275 | ] 276 | 277 | [[package]] 278 | name = "either" 279 | version = "1.10.0" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" 282 | 283 | [[package]] 284 | name = "errno" 285 | version = "0.3.8" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" 288 | dependencies = [ 289 | "libc", 290 | "windows-sys 0.52.0", 291 | ] 292 | 293 | [[package]] 294 | name = "fat-macho" 295 | version = "0.4.8" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "0d4c93f393add03d72bc10dd3dea43a1610ecb29e0c0a6459c70b53b82931adf" 298 | dependencies = [ 299 | "goblin", 300 | ] 301 | 302 | [[package]] 303 | name = "fs-err" 304 | version = "2.11.0" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" 307 | dependencies = [ 308 | "autocfg", 309 | ] 310 | 311 | [[package]] 312 | name = "getrandom" 313 | version = "0.2.12" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 316 | dependencies = [ 317 | "cfg-if", 318 | "libc", 319 | "wasi", 320 | ] 321 | 322 | [[package]] 323 | name = "glob" 324 | version = "0.3.1" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 327 | 328 | [[package]] 329 | name = "goblin" 330 | version = "0.8.0" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "bb07a4ffed2093b118a525b1d8f5204ae274faed5604537caf7135d0f18d9887" 333 | dependencies = [ 334 | "log", 335 | "plain", 336 | "scroll", 337 | ] 338 | 339 | [[package]] 340 | name = "heck" 341 | version = "0.4.1" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 344 | 345 | [[package]] 346 | name = "home" 347 | version = "0.5.9" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 350 | dependencies = [ 351 | "windows-sys 0.52.0", 352 | ] 353 | 354 | [[package]] 355 | name = "itertools" 356 | version = "0.12.1" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 359 | dependencies = [ 360 | "either", 361 | ] 362 | 363 | [[package]] 364 | name = "itoa" 365 | version = "1.0.10" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 368 | 369 | [[package]] 370 | name = "lazy_static" 371 | version = "1.4.0" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 374 | 375 | [[package]] 376 | name = "lazycell" 377 | version = "1.3.0" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 380 | 381 | [[package]] 382 | name = "libc" 383 | version = "0.2.153" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 386 | 387 | [[package]] 388 | name = "libloading" 389 | version = "0.8.1" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" 392 | dependencies = [ 393 | "cfg-if", 394 | "windows-sys 0.48.0", 395 | ] 396 | 397 | [[package]] 398 | name = "libredox" 399 | version = "0.0.1" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" 402 | dependencies = [ 403 | "bitflags 2.4.2", 404 | "libc", 405 | "redox_syscall", 406 | ] 407 | 408 | [[package]] 409 | name = "linux-raw-sys" 410 | version = "0.4.13" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" 413 | 414 | [[package]] 415 | name = "log" 416 | version = "0.4.20" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 419 | 420 | [[package]] 421 | name = "memchr" 422 | version = "2.7.1" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 425 | 426 | [[package]] 427 | name = "minimal-lexical" 428 | version = "0.2.1" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 431 | 432 | [[package]] 433 | name = "nom" 434 | version = "7.1.3" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 437 | dependencies = [ 438 | "memchr", 439 | "minimal-lexical", 440 | ] 441 | 442 | [[package]] 443 | name = "once_cell" 444 | version = "1.19.0" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 447 | 448 | [[package]] 449 | name = "option-ext" 450 | version = "0.2.0" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 453 | 454 | [[package]] 455 | name = "path-slash" 456 | version = "0.2.1" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" 459 | 460 | [[package]] 461 | name = "plain" 462 | version = "0.2.3" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" 465 | 466 | [[package]] 467 | name = "prettyplease" 468 | version = "0.2.16" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" 471 | dependencies = [ 472 | "proc-macro2", 473 | "syn", 474 | ] 475 | 476 | [[package]] 477 | name = "proc-macro2" 478 | version = "1.0.78" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 481 | dependencies = [ 482 | "unicode-ident", 483 | ] 484 | 485 | [[package]] 486 | name = "quote" 487 | version = "1.0.35" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 490 | dependencies = [ 491 | "proc-macro2", 492 | ] 493 | 494 | [[package]] 495 | name = "redox_syscall" 496 | version = "0.4.1" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 499 | dependencies = [ 500 | "bitflags 1.3.2", 501 | ] 502 | 503 | [[package]] 504 | name = "redox_users" 505 | version = "0.4.4" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" 508 | dependencies = [ 509 | "getrandom", 510 | "libredox", 511 | "thiserror", 512 | ] 513 | 514 | [[package]] 515 | name = "regex" 516 | version = "1.10.3" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" 519 | dependencies = [ 520 | "aho-corasick", 521 | "memchr", 522 | "regex-automata", 523 | "regex-syntax", 524 | ] 525 | 526 | [[package]] 527 | name = "regex-automata" 528 | version = "0.4.5" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" 531 | dependencies = [ 532 | "aho-corasick", 533 | "memchr", 534 | "regex-syntax", 535 | ] 536 | 537 | [[package]] 538 | name = "regex-syntax" 539 | version = "0.8.2" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 542 | 543 | [[package]] 544 | name = "rust-ffi-playground" 545 | version = "0.1.0" 546 | dependencies = [ 547 | "bindgen", 548 | "cargo-zigbuild", 549 | "cc", 550 | ] 551 | 552 | [[package]] 553 | name = "rustc-hash" 554 | version = "1.1.0" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 557 | 558 | [[package]] 559 | name = "rustc_version" 560 | version = "0.4.0" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 563 | dependencies = [ 564 | "semver", 565 | ] 566 | 567 | [[package]] 568 | name = "rustix" 569 | version = "0.38.31" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" 572 | dependencies = [ 573 | "bitflags 2.4.2", 574 | "errno", 575 | "libc", 576 | "linux-raw-sys", 577 | "windows-sys 0.52.0", 578 | ] 579 | 580 | [[package]] 581 | name = "ryu" 582 | version = "1.0.16" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" 585 | 586 | [[package]] 587 | name = "scroll" 588 | version = "0.12.0" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" 591 | dependencies = [ 592 | "scroll_derive", 593 | ] 594 | 595 | [[package]] 596 | name = "scroll_derive" 597 | version = "0.12.0" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" 600 | dependencies = [ 601 | "proc-macro2", 602 | "quote", 603 | "syn", 604 | ] 605 | 606 | [[package]] 607 | name = "semver" 608 | version = "1.0.21" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" 611 | dependencies = [ 612 | "serde", 613 | ] 614 | 615 | [[package]] 616 | name = "serde" 617 | version = "1.0.196" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" 620 | dependencies = [ 621 | "serde_derive", 622 | ] 623 | 624 | [[package]] 625 | name = "serde_derive" 626 | version = "1.0.196" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" 629 | dependencies = [ 630 | "proc-macro2", 631 | "quote", 632 | "syn", 633 | ] 634 | 635 | [[package]] 636 | name = "serde_json" 637 | version = "1.0.113" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" 640 | dependencies = [ 641 | "itoa", 642 | "ryu", 643 | "serde", 644 | ] 645 | 646 | [[package]] 647 | name = "shlex" 648 | version = "1.3.0" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 651 | 652 | [[package]] 653 | name = "strsim" 654 | version = "0.11.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" 657 | 658 | [[package]] 659 | name = "syn" 660 | version = "2.0.49" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" 663 | dependencies = [ 664 | "proc-macro2", 665 | "quote", 666 | "unicode-ident", 667 | ] 668 | 669 | [[package]] 670 | name = "target-lexicon" 671 | version = "0.12.13" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" 674 | 675 | [[package]] 676 | name = "terminal_size" 677 | version = "0.3.0" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" 680 | dependencies = [ 681 | "rustix", 682 | "windows-sys 0.48.0", 683 | ] 684 | 685 | [[package]] 686 | name = "thiserror" 687 | version = "1.0.57" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" 690 | dependencies = [ 691 | "thiserror-impl", 692 | ] 693 | 694 | [[package]] 695 | name = "thiserror-impl" 696 | version = "1.0.57" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" 699 | dependencies = [ 700 | "proc-macro2", 701 | "quote", 702 | "syn", 703 | ] 704 | 705 | [[package]] 706 | name = "unicode-ident" 707 | version = "1.0.12" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 710 | 711 | [[package]] 712 | name = "utf8parse" 713 | version = "0.2.1" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 716 | 717 | [[package]] 718 | name = "wasi" 719 | version = "0.11.0+wasi-snapshot-preview1" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 722 | 723 | [[package]] 724 | name = "which" 725 | version = "4.4.2" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" 728 | dependencies = [ 729 | "either", 730 | "home", 731 | "once_cell", 732 | "rustix", 733 | ] 734 | 735 | [[package]] 736 | name = "which" 737 | version = "6.0.0" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" 740 | dependencies = [ 741 | "either", 742 | "home", 743 | "once_cell", 744 | "rustix", 745 | "windows-sys 0.52.0", 746 | ] 747 | 748 | [[package]] 749 | name = "windows-sys" 750 | version = "0.48.0" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 753 | dependencies = [ 754 | "windows-targets 0.48.5", 755 | ] 756 | 757 | [[package]] 758 | name = "windows-sys" 759 | version = "0.52.0" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 762 | dependencies = [ 763 | "windows-targets 0.52.0", 764 | ] 765 | 766 | [[package]] 767 | name = "windows-targets" 768 | version = "0.48.5" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 771 | dependencies = [ 772 | "windows_aarch64_gnullvm 0.48.5", 773 | "windows_aarch64_msvc 0.48.5", 774 | "windows_i686_gnu 0.48.5", 775 | "windows_i686_msvc 0.48.5", 776 | "windows_x86_64_gnu 0.48.5", 777 | "windows_x86_64_gnullvm 0.48.5", 778 | "windows_x86_64_msvc 0.48.5", 779 | ] 780 | 781 | [[package]] 782 | name = "windows-targets" 783 | version = "0.52.0" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" 786 | dependencies = [ 787 | "windows_aarch64_gnullvm 0.52.0", 788 | "windows_aarch64_msvc 0.52.0", 789 | "windows_i686_gnu 0.52.0", 790 | "windows_i686_msvc 0.52.0", 791 | "windows_x86_64_gnu 0.52.0", 792 | "windows_x86_64_gnullvm 0.52.0", 793 | "windows_x86_64_msvc 0.52.0", 794 | ] 795 | 796 | [[package]] 797 | name = "windows_aarch64_gnullvm" 798 | version = "0.48.5" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 801 | 802 | [[package]] 803 | name = "windows_aarch64_gnullvm" 804 | version = "0.52.0" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" 807 | 808 | [[package]] 809 | name = "windows_aarch64_msvc" 810 | version = "0.48.5" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 813 | 814 | [[package]] 815 | name = "windows_aarch64_msvc" 816 | version = "0.52.0" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" 819 | 820 | [[package]] 821 | name = "windows_i686_gnu" 822 | version = "0.48.5" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 825 | 826 | [[package]] 827 | name = "windows_i686_gnu" 828 | version = "0.52.0" 829 | source = "registry+https://github.com/rust-lang/crates.io-index" 830 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" 831 | 832 | [[package]] 833 | name = "windows_i686_msvc" 834 | version = "0.48.5" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 837 | 838 | [[package]] 839 | name = "windows_i686_msvc" 840 | version = "0.52.0" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" 843 | 844 | [[package]] 845 | name = "windows_x86_64_gnu" 846 | version = "0.48.5" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 849 | 850 | [[package]] 851 | name = "windows_x86_64_gnu" 852 | version = "0.52.0" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" 855 | 856 | [[package]] 857 | name = "windows_x86_64_gnullvm" 858 | version = "0.48.5" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 861 | 862 | [[package]] 863 | name = "windows_x86_64_gnullvm" 864 | version = "0.52.0" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" 867 | 868 | [[package]] 869 | name = "windows_x86_64_msvc" 870 | version = "0.48.5" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 873 | 874 | [[package]] 875 | name = "windows_x86_64_msvc" 876 | version = "0.52.0" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" 879 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-ffi-playground" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [build-dependencies] 11 | bindgen = "0.69.4" 12 | cargo-zigbuild = "0.18.3" 13 | cc = "1.0.83" 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crosscompile a Rust project with C dependencies into Web Assembly (WASM and WASI) using Zig 2 | 3 | Easy way using [rust-bindgen](https://github.com/rust-lang/rust-bindgen) and [cargo-zigbuild](https://github.com/rust-cross/cargo-zigbuild) CLI tools. 4 | 5 | ### Generate Rust bindings for the C code 6 | 7 | We just need the C/C++ header files wit the definitions and [rust-bindgen](https://github.com/rust-lang/rust-bindgen) will generate the Rust FFI bindings. 8 | 9 | ```bash 10 | bindgen some-c-code/gcd.h -o src/bindings.rs # generate Rust FFI bindings for gcd.h 11 | ``` 12 | 13 | ### Quick WASI try out 14 | 15 | Using [zigbuild](https://github.com/rust-cross/cargo-zigbuild) we can cross compile to WASI 16 | 17 | ```bash 18 | rustup target add wasm32-wasip1 # make sure wasm32-wasi target is installed 19 | cargo zigbuild --target=wasm32-wasip1 --release # cross compile to WASI, release flag is optional 20 | ``` 21 | 22 | > [!warning] 23 | > Previously the target `wasm32-wasip1` was `wasm32-wasi` but it is now being deprecated, still you might want to use it even if you [get some warnings](https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html#renaming-wasm32-wasi-to-wasm32-wasip1). 24 | 25 | we can try it with [wasm3](https://github.com/wasm3/wasm3) engine 26 | 27 | ```bash 28 | wasm3 target/wasm32-wasip1/release/rust-ffi-playground.wasm # try it out, requires wasm3 29 | ``` 30 | 31 | or [wasmi](https://github.com/wasmi-labs/wasmi) 32 | 33 | ```bash 34 | wasmi_cli target/wasm32-wasip1/release/rust-ffi-playground.wasm # run it with wasmi runtime 35 | ``` 36 | 37 | 38 | ### Cross compile for web (WASM) 39 | 40 | Generate code for WASM with [zigbuild](https://github.com/rust-cross/cargo-zigbuild), and then use [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) to generate the js/ts bindings to the WASM code. 41 | 42 | ```bash 43 | cargo zigbuild --target=wasm32-unknown-unknown --release # cross compile to WASM, release flag is optional 44 | wasm-bindgen target/wasm32-unknown-unknown/release/rust-ffi-playground.wasm --out-dir ./dist --target web # generate JS and TS FFI bindings into WASM code 45 | ``` 46 | 47 | To try it, manually include the script tag to load and initialize the wasm module 48 | 49 | ```html 50 | 54 | ``` 55 | 56 | or use a WASM plugin like [`vite-plugin-wasm`](https://www.npmjs.com/package/vite-plugin-wasm) or use [Trunk](https://trunkrs.dev/) 57 | 58 | Note: As in this [github issue](https://github.com/rustwasm/team/issues/291#issuecomment-644946504) it can be compiled to `wasm32-unknown-emscripten`. 59 | 60 | Same [example](https://github.com/rustwasm/team/issues/291#issuecomment-645492619) but using `wasm-pack`, hence `wasm-bindgen` instead 61 | 62 | ### Going further 63 | 64 | Not a trivial project, eg. building a native library, link to a system library... 65 | 66 | Replace CLI commands with a simple `Makefile` or (even better) a `builder.rs` file, eg. use `cargo_zigbuild` and `bindgen` directly in `build.rs` by replacing `cc` with `zigbuild` 67 | 68 | ```rust 69 | use cargo_zigbuild::Zig::Cc; 70 | use std::{env, error::Error}; 71 | 72 | fn main() -> Result<(), Box> { 73 | cc::Build::new().file("some-c-code/def.c").compile("def"); 74 | 75 | let out_dir = env::var("OUT_DIR").unwrap(); 76 | 77 | let cc = Cc { 78 | args: vec![ 79 | format!("some-c-code/def.c"), 80 | "-c".to_string(), 81 | "-o".to_string(), 82 | format!("{}/def.o", out_dir), 83 | ], 84 | }; 85 | 86 | cc.execute().expect("Failed to compile def.c"); 87 | 88 | let ar = cargo_zigbuild::Zig::Ar { 89 | args: vec![ 90 | "crus".to_string(), 91 | format!("{}/libdef.a", out_dir), 92 | format!("{}/def.o", out_dir), 93 | ], 94 | }; 95 | 96 | ar.execute().expect("Failed to create def.a"); 97 | 98 | println!("cargo:rustc-link-search=native={}", out_dir); 99 | println!("cargo:rustc-link-lib=static=def"); 100 | 101 | println!("cargo:rerun-if-changed=some-c-code"); 102 | println!("cargo:rerun-if-changed=build.rs"); 103 | Ok(()) 104 | } 105 | ``` 106 | 107 | ## References 108 | 109 | - [The `cc-rs` project](https://crates.io/crates/cc) 110 | - [Official cargo reference](https://doc.rust-lang.org/cargo/reference/build-script-examples.html) 111 | - [zig.guide's Cross-compilation](https://zig.guide/build-system/cross-compilation/) 112 | - [`zig cc`: a Powerful Drop-In Replacement for GCC/Clang](https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html) 113 | - [Bindgen tutorial](https://rust-lang.github.io/rust-bindgen/tutorial-3.html) 114 | - [The embedded Rust book](https://docs.rust-embedded.org/book/interoperability/c-with-rust.html) 115 | - [Shrinking `.wasm` code size](https://rustwasm.github.io/docs/book/reference/code-size.html) 116 | 117 | ## Issues 118 | 119 | wasm-bindgen targets `wasm32-unknown-unknown` and `wasi-unknown` do not (fully) support C-ABI, only older targets like `wasm32-unknown-emscripten`. 120 | 121 | See [comment](https://github.com/rustwasm/team/issues/291#issuecomment-645482430), [comment](https://github.com/rustwasm/team/issues/291#issuecomment-645494771) and [documentation PR](https://github.com/rustwasm/wasm-bindgen/pull/2209) 122 | 123 | There is an experimental flag `--Z wasm_c_abi=spec` that [circumvents this limitation](https://github.com/rustwasm/team/issues/291#issuecomment-2138201722) 124 | 125 | ## Other tools 126 | 127 | - [c2rust](https://github.com/immunant/c2rust) - C to Rust translator produces `unsafe` Rust code from C99-compilant C code. It does not support cross compilation, but maybe it can with the help of Zig. 128 | 129 | From their website: 130 | 131 | > C source code is parsed and typechecked using clang before being translated by our tool. 132 | 133 | would it be possible to use it with Zig as a drop-in replacement for clang? 134 | 135 | From their README: 136 | 137 | > I translated code on platform X, but it didn't work correctly on platform Y. 138 | > We run the C preprocessor before translation to Rust. This specializes the code to the host platform. For this reason, we do not support cross compiling translated code at the moment. 139 | > What platforms can C2Rust be run on? 140 | > The translator and refactoring tool support both macOS and Linux. Other features, such as cross checking the functionality between C and Rust code, are currently limited to Linux hosts. 141 | 142 | ## Utils 143 | 144 | - [source](https://github.com/GoogleChromeLabs/wasm-feature-detect) 145 | 146 | --- 147 | 148 | ## Remarks 149 | 150 | > In general, a `lib.so` or `lib.a` should be referenced in the build file by ``. 151 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | fn main() -> Result<(), Box> { 4 | cc::Build::new().file("some-c-code/gcd.c").compile("def"); 5 | 6 | let bindings = bindgen::builder() 7 | .header("some-c-code/gcd.h") 8 | .allowlist_function("gcd") 9 | .generate()?; 10 | 11 | bindings.write_to_file("src/bindings.rs")?; 12 | 13 | println!("cargo:rerun-if-changed=some-c-code"); 14 | println!("cargo:rerun-if-changed=build.rs"); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | From Rust + C to Web Assembly with the help of Zig 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /some-c-code/gcd.c: -------------------------------------------------------------------------------- 1 | #include "gcd.h" 2 | 3 | int gcd(int i, Pair* ps) { 4 | int gcd; 5 | for (; i <= ps->n && i <= ps->m; ++i) { 6 | // Checks if i is factor of both integers 7 | if (ps->n % i == 0 && ps->m % i == 0) 8 | gcd = i; 9 | } 10 | 11 | return gcd; 12 | } 13 | -------------------------------------------------------------------------------- /some-c-code/gcd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file def.h 3 | * @brief This is an example header file providing functionality XYZ. 4 | * @author John Doe 5 | * @date January 1, 2024 6 | */ 7 | 8 | /** 9 | * @brief This structure represents a pair of integers 10 | */ 11 | typedef struct Pair { 12 | int n; 13 | int m; 14 | } Pair; 15 | 16 | /** 17 | * @brief This function performs the greatest common division (gcd) of a `Pair` 18 | * 19 | * @param i Minimum gcd to search for. 20 | * @param ps Pair of integers to find the gcd. 21 | * @return Greatest common divisor of `ps` that is larger or equal to `i`. 22 | */ 23 | int gcd(int i, Pair* ps); -------------------------------------------------------------------------------- /some-c-code/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gcd.h" 4 | 5 | int main() { 6 | Pair ps; 7 | printf("Enter two integers: "); 8 | scanf("%d %d", &ps.n, &ps.m); 9 | printf("G.C.D of %d and %d is %d.", ps.n, ps.m, gcd(0, &ps)); 10 | } -------------------------------------------------------------------------------- /src/bindings.rs: -------------------------------------------------------------------------------- 1 | /* automatically generated by rust-bindgen 0.69.4 */ 2 | 3 | #[doc = " @brief This structure represents a pair of integers"] 4 | #[repr(C)] 5 | #[derive(Debug, Copy, Clone)] 6 | pub struct Pair { 7 | pub n: ::std::os::raw::c_int, 8 | pub m: ::std::os::raw::c_int, 9 | } 10 | #[test] 11 | fn bindgen_test_layout_Pair() { 12 | const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); 13 | let ptr = UNINIT.as_ptr(); 14 | assert_eq!( 15 | ::std::mem::size_of::(), 16 | 8usize, 17 | concat!("Size of: ", stringify!(Pair)) 18 | ); 19 | assert_eq!( 20 | ::std::mem::align_of::(), 21 | 4usize, 22 | concat!("Alignment of ", stringify!(Pair)) 23 | ); 24 | assert_eq!( 25 | unsafe { ::std::ptr::addr_of!((*ptr).n) as usize - ptr as usize }, 26 | 0usize, 27 | concat!("Offset of field: ", stringify!(Pair), "::", stringify!(n)) 28 | ); 29 | assert_eq!( 30 | unsafe { ::std::ptr::addr_of!((*ptr).m) as usize - ptr as usize }, 31 | 4usize, 32 | concat!("Offset of field: ", stringify!(Pair), "::", stringify!(m)) 33 | ); 34 | } 35 | extern "C" { 36 | #[doc = " @brief This function performs the greatest common division (gcd) of a `Pair`\n\n @param i Minimum gcd to search for.\n @param ps Pair of integers to find the gcd.\n @return Greatest common divisor of `ps` that is larger or equal to `i`."] 37 | pub fn gcd(i: ::std::os::raw::c_int, ps: *mut Pair) -> ::std::os::raw::c_int; 38 | } 39 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod bindings; 2 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use rust_ffi_playground::bindings::{gcd, Pair}; 2 | 3 | fn main() { 4 | let ps = &mut Pair { n: 6, m: 3 }; 5 | let a = unsafe { gcd(3, ps) }; 6 | 7 | println!("Hello, world! {}", a); 8 | } 9 | --------------------------------------------------------------------------------