# smithy-bindgen This crate provides macros for generating rust bindings from smithy interfaces. For most uses of smithy interfaces used to generate rust sources, this can eliminate the need for [`build.rs` and `codegen.toml` files](https://wasmcloud.dev/interfaces/codegen-toml/). `codegen.toml` is still needed to generate bindings for other languages. > ### Feedback welcome! > This is a first pass at code generation macro, inspired by `wit-bindgen`. If you have used `codegen.toml`, please let us know if this works as a replacement. (one known omission: the `params` setting from codegen.toml is not yet available in this macro) > Other variations may be introduced in the future: one for actor-specific interfaces, provider-specific interfaces, etc. ## Quick-start We recommend that the `smithy_bindgen!` macro is used inside a `mod` declaration, or by itself in a separate rust source file, to avoid symbol conflicts with your code. If you're using a wasmcloud first-party interface, you can specify its path name (relative to the wasmcloud/interfaces repo), followed by its namespace: ``` // [dependencies] // smithy-bindgen = "0.1" mod httpserver { smithy_bindgen::smithy_bindgen!("httpserver/httpserver.smithy","org.wasmcloud.interfaces.httpserver"); } use httpserver::{HttpRequest,HttpResponse}; ``` If you have a smithy interface defined locally, you can load it ``` mod amazing_foo { smithy_bindgen::smithy_bindgen!( { path: "./amazing_foo.smithy" }, "org.example.interfaces.foo" ); } use amazing_foo::{Bazinga, Wowza}; ``` Additional syntax forms are listed below. > **Note** This doesn't replace all the functionality of wasmCloud's interface crates. A few of the wasmCloud interface crates have hand-generated helper functions that are not part of the smithy files. For example, `wasmcloud-interface-httpserver` contains `impl Default` and a few constructors for `HttpResponse`. Those are not generated by `smithy_bindgen!`. We are planning to move those extra helper functions into a future wasmcloud sdk. ## Syntax The first parameter of the `smithy_bindgen!` macro can take one of three forms. The second parameter is the namespace used for code generation. - one wasmcloud first-party interface The single-file parameter is a path relative to the wasmcloud interfaces git repo `wasmcloud/interfaces` ``` smithy_bindgen!("httpserver/httpserver.smithy", "org.wasmcloud.interfaces.httpserver"); ```` The above is shorthand for the following: ``` smithy_bindgen!({ url: "https://cdn.jsdelivr.net/gh/wasmcloud/interfaces", files: ["httpserver/httpserver.smithy"] }, "org.wasmcloud.interfaces.httpserver" ); ``` - one Model Source ``` smithy-bindgen!({ path: "../interfaces/foo.smithy", }, "org.example.interfaces.foo" ); ```` - array of Model Sources ``` smithy-bindgen!([ { path: "../interfaces/foo.smithy" }, { url: "keyvalue/keyvalue.smithy" }, ], "org.example.interfaces.foo" ); ``` ## Model Source Specification A model source contains a `url`, for http(s) downloads, or a `path`, for local fs access, that serves as a base, plus `files`, an optional list of file paths that are appended to the base to build complete url download paths and local file paths. When joining the sub-paths from the `files` array, '/' is inserted or removed as needed, so that there is exactly one between the base and the sub-path. `url` must begin with either 'http://' or 'https://'. If `path` is a relative fs path, it is relative to the folder containing `Cargo.toml`. `files` may be omitted if the `url` or `path` contains the full path to the `.smithy` file. All the following are (syntactically) valid model sources: ``` { url: "https://example.com/interfaces/foo.smithy" } { url: "https://example.com/interfaces", files: [ "foo.smithy", "bar.smithy" ]} { path: "../interfaces/foo.smithy" } { path: "../interfaces", files: ["foo.smithy", "bar.smithy"]} ``` These are all equivalent: ``` { path: "/usr/share/interfaces/timer.smithy" } { path: "/usr/share/interfaces", files: [ "timer.smithy" ] } { path: "/usr/share/interfaces/", files: [ "timer.smithy" ] } ``` If a model source structure contains no url base and no path base, the url for the github wasmcloud interface repo is used: ``` url: "https://cdn.jsdelivr.net/gh/wasmcloud/interfaces" ``` Why would the code generator need to load more than one smithy file? So that interfaces can share common symbols for data structures. Most smithy interfaces already import symbols from the namespace `org.wasmcloud.model`, defined in `wasmcloud-model.smithy`. The bindgen tool resolves all symbols by assembling an in-memory schema model from all the smithy sources and namespaces, then traversing through the in-memory model, generating code only for the schema elements in the namespace declared in the second parameter of `smithy_bindgen!`. ## jsdelivr.net urls `cdn.jsdelivr.net` mirrors open source github repositories. The [url syntax](https://www.jsdelivr.com/?docs=gh) can optionally include a github branch, tag, or commit sha. ## Common files Wasmcloud common model files are always automatically included when compiling models (If you've used `codegen.toml` files, you may remember that they required all base models to be specified explicitly.) ## Namespace Models may include symbols defined in other models via the `use` command. Only the symbols defined in the namespace (`smithy_bindgen!`'s second parameter) will be included in the generated code.