Crates.io | golem-rust-macro |
lib.rs | golem-rust-macro |
version | |
source | src |
created_at | 2024-04-13 07:40:18.505379 |
updated_at | 2024-12-03 18:23:49.300805 |
description | Golem Rust tooling library that facilitates writing Golem backends in Rust |
homepage | https://golem.cloud |
repository | https://github.com/golemcloud/golem-rust |
max_upload_size | |
id | 1207422 |
Cargo.toml error: | TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This crate contains couple of Rust macros that facilitate writing Golem Cloud backends in Rust:
From<>
and Into<>
typeclasses between wit-bindgen derived data types and custom domain model data types.$ cargo add golem-rust
When working with WIT files in Golem, wit-bindgen library generates data types based on the wit file. There are few drawbacks when using these data types, so very often, user would create its own data types. In order to easily convert between generated and domain data types, programmer needs to implement boilerplate-y From<>
and Into<>
typeclasses.
This project contains macro that would automatically implement those typeclasses.
Let's say we have
pub struct Person {
pub name: String,
pub age: i32,
}
pub struct WitPerson {
pub name: String,
pub age: i32,
}
We can use macro help in implementing From
and Into
typeclasses by annotating Person with #[derive(golem_rust::WIT_From_Into))]
#[derive(golem_rust::WIT_From_Into))]
pub struct Person {
pub name: String,
pub age: i32,
}
then the following code compiles without problems
let me = Person {
name: "Jaro".to_owned(),
age: 32,
};
let converted: WitPerson = me.into();
The above macro assumed that the data type for which we are deriving From<>
and Into<>
is called WitPerson
. By default macro assumes that the name of the data type is Wit
+ annotated data type name. In case the name is different, we need to add #[wit_type_name(DerivedName)]
attribute.
#[derive(golem_rust::WIT_From_Into))]
#[wit_type_name(DerivedName)]
pub struct Person {
pub name: String,
pub age: i32,
}
In case the field names in derived data type are different we can use field attribute #[rename_field("")]
#[derive(golem_rust::WIT_From_Into))]
#[wit_type_name(WitPerson)]
pub struct Person {
#[rename_field("name2")]
pub name: String,
#[rename_field("age2")]
pub age: i32,
}
Very similar to structs, let's say we have the following enum data type:
#[derive(golem_rust::WIT_From_Into))]
#[wit_type_name(SimilarColors)]
pub enum Colors {
Red,
White,
#[rename_field("Yellow2")]
Yellow,
}
pub enum SimilarColors {
Red,
White,
Yellow2,
}
Then very simply we can use .into()
and it will compile.
let yellow = Colors::Yellow;
let wit_collors: SimilarColors = yellow.into();
More examples can be found in golem-rust-example/src/main.rs
Let's say we are building auction app powered by Golem Cloud. We would like to support some basic functionality like:
The WIT file itself could look like this:
package auction:app
interface api {
record bidder-id {
bidder-id: string,
}
record auction-id {
auction-id: string,
}
record auction {
auction-id: auction-id,
name: string,
description: string,
starting-price: float32,
deadline: deadline,
}
variant bid-result {
failure(string),
success
}
type deadline = u64
initialize: func(auction: auction)
bid: func(bidder-id: bidder-id, price: float32) -> bid-result
close-auction: func() -> option<bidder-id>
create-bidder: func(name: string, address: string) -> bidder-id
create-auction: func(name: string, description: string, starting-price: float32, deadline: u64) -> auction-id
get-auctions: func() -> list<auction>
}
world golem-service {
export api
}
There are many things that could go wrong when writing this, especially if you're not familiar with WIT. But mostly, it's just a boilerplate that can now be avoided.
Simply annotate your inner module with #[golem_rust::create_wit_file]
macro.
#[golem_rust::create_wit_file]
mod auction_app {
struct BidderId {
bidder_id: String
}
struct AuctionId {
auction_id: String
}
struct Auction {
auction_id: AuctionId,
name: String,
description: String,
starting_price: f32,
deadline: Deadline,
}
enum BidResult {
Failure(String),
Success
}
type Deadline = u64;
trait AuctionService {
fn initialize(auction: Auction);
fn bid(bidder_id: BidderId, price: f32) -> BidResult;
fn close_auction() -> Option<BidderId>;
fn create_bidder(name: String, address: String) -> BidderId;
fn create_auction(name: String, description: String, starting_price: f32, deadline: u64) -> AuctionId;
fn get_auctions() -> Vec<Auction>;
}
}
and this will generate generated.wit
file in the root of your project.
If you want your generated file to have custom name, add the name to the attribute e.g. #[golem_rust::create_wit_file("auction_app_file.wit")]
The following empty inner module
#[golem_rust::create_wit_file]
mod package_name {
}
translates to the empty with file with package name derived from module name:
package package:name
interface api {
}
world golem-service {
export api
}
So interface name is always api
which is exported from world geolem-service
Other rules of wit file generation:
struct
is translated into WIT record
.Enum
is translated into either variant
or enum
depending on whether enum has associated data.Option<>
is option<>
.vec<>
is list<>
.type Name = String
becomes type name = string
Box<>
is ignored and inner type is taken care of.Contributions very are welcome. If you find a bug, use case that is not supported or you simply think that error message is not good enough, please open an issue or submit a PR. This library is still at an early stage of development and although some use cases are covered, feedback would be very helpful for polishing this library.
Inner binary project which depends on golem-rust. Here you can find more examples on how to use golem-rust.