Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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()
    }
}
}