Mapping for Union Types
Unions in IDL are mapped to Rust enums where each case label maps to an enum
variant. Enums are easier to use and are better suited for pattern matching.
The value of the discriminator is inferred during serialization by looking at
the populated field.
In the event that a union has multiple switch cases mapped to a single value, the name of the case label is appended to the end of the member value. If not all cases are covered by the union, an implicit default case will be inserted.
Each union has a disc function which returns the corresponding enum value of
the would-be discriminator, deduced from the populated variant. Similarly, each
union implements the From<T> trait, where T is the type of the discriminant.
The derived traits for unions depend on their variant types. Unions containing
heap-allocated types (like String) will not derive Copy. Unions containing
floating-point types will not derive Eq, Ord, or Hash. See
Derived Traits for the complete derivation rules.
// IDL
enum MyEnum {
ONE,
TWO,
THREE,
FOUR
};
union MyUnion switch(MyEnum) {
case ONE:
string my_string;
case TWO:
case THREE:
int32 my_int;
default:
string default_value;
};
#![allow(unused)]
fn main() {
// Rust
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum MyEnum {
One,
Two,
Three,
Four,
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum MyUnion {
MyString(String),
MyIntTwo(i32),
MyIntThree(i32),
DefaultValue(String),
}
impl MyUnion {
pub fn new() -> Self {
Self::MyString(String::new())
}
pub const fn disc(&self) -> MyEnum {
match self {
Self::MyString(_) => MyEnum::One,
Self::MyIntTwo(_) => MyEnum::Two,
Self::MyIntThree(_) => MyEnum::Three,
Self::DefaultValue(_) => MyEnum::Four,
}
}
}
impl From<MyEnum> for MyUnion {
fn from(disc: MyEnum) -> Self {
// maps the discriminant to the correct variant
}
}
impl Default for MyUnion {
fn default() -> Self {
Self::new()
}
}
}