TUTORIAL / 03
Pass data and handle errors
Use records, enums, sets and tuples from Haxe, then catch a typed Rust error.
1. Pass a record
The pantry example marks plain values with #[hxn::data]. Haxe gets a record class and an enum; the Rust library stays independent of the runtime.
#[hxn::data]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Unit {
Each,
Kilo,
Litre,
}
/// An item on a shelf. Haxe gets a class with these fields.
#[hxn::data]
#[derive(Clone)]
pub struct Item {
pub name: String,
pub quantity: i32,
#[hxn(default = "Item::default_unit")]
pub unit: Unit,
/// An optional field can be omitted in Haxe.
pub note: Option<String>,
}
var pantry = new Pantry();
// Rust fills the omitted unit with Item::default_unit; note is null.
pantry.stock({name: "eggs", quantity: 12});
pantry.stock({name: "flour", quantity: 2, unit: Unit.Kilo, note: "wholemeal"});
var rice:Item = {name: "rice", quantity: 1, unit: Unit.Kilo};
Sys.println('${pantry.stock(rice)} items stocked');
Omitted unit uses Item::default_unit(); omitted note becomes null. Rust stores a copy. Changing rice.quantity in Haxe after stocking leaves the pantry unchanged.
2. Use tuples and sets
var quantities = pantry.quantities();
Sys.println('shelves: ${[for (pair in quantities) '${pair[0]}=${pair[1]}'].join(", ")}');
var wanted = new hxn.Set(["rice", "salt"]);
wanted.add("salt");
wanted.add("oil");
Sys.println('to buy: ${pantry.missing(wanted).toArray().join(" and ")}');
Rust’s Vec<(String, i32)> arrives as an array of hxn.Tuple values. Indexed access returns Dynamic; pair.at(0) preserves the position’s static type. hxn.Set supports membership and insertion. This example returns a BTreeSet, so the result is sorted by Rust.
3. Catch a typed error
#[hxn::data]
#[derive(Clone, Debug)]
pub enum PantryError {
/// No item has that name.
Unknown(String),
/// Fewer are in stock than requested.
Short { name: String, left: i32 },
}
for (wanted in ["eggs", "salt"]) {
try {
pantry.take(wanted, 50);
} catch (refused:PantryException) {
switch (refused.error) {
case Short(name, left):
Sys.println('only $left of $name');
case Unknown(name):
Sys.println('no $name at all');
}
Sys.println(' ${refused.message}');
}
}
take returns Result<Item, PantryError>. Haxe catches PantryException: its error field is the enum, and its message comes from Rust’s Display implementation. Call pantry.close() when finished.
Run the example
From the repository root, run the complete example:
cd examples/pantry
hxn run hl
Full Rust and Haxe source ↗ · Use hxn run cpp for hxcpp.