Unions

    A Union in Cyrus is a composite data type similar to C-style unions. It allows multiple fields to share the same memory location, so only one of its fields can hold a valid value at any given time.

    Unlike structs, writing to one field will overwrite the memory for all others.



    Defining a Union

    union DataUnion {
        a: int;
        b: float64;
    }
    
    fn main() {
        var un = DataUnion;
        un.b = 3.14;
    }
    

    Using a Union

    You can create a union instance and assign fields directly:

    fn main() {
        var un = DataUnion;
        un.a = 42;       // set the integer field
        un.b = 3.14;     // overwrites the same memory with a float
    }
    

    After un.b = 3.14, the value of un.a is no longer valid.


    Union Initialization

    Unions can be initialized using a Union Initializer, specifying which field to set at creation:

    var un: DataUnion = DataUnion { a: 10 };
    

    Rules:

    • Only one field should be initialized.
    • The union's memory will be set according to that field.

    Practical Use Cases

    Unions are low-level tools, mainly used in systems programming:

    • Type punning: reinterpret the same memory as different types.
    • Interfacing with C libraries: many C APIs expose unions in their structs.
    • Memory efficiency: when you know only one of several large fields will be used at once.

    Example: Interpreting the same 32-bit data as either an integer or raw bytes.

    import std::libc{printf};
    
    union IntBytes {
        value: int;
        bytes: uint8[4];
    }
    
    fn main() {
        var data = IntBytes { value: 0x12345678 };
    
        printf("%x %x %x %x\n", data.bytes[0], data.bytes[1], data.bytes[2], data.bytes[3]);
    }
    

    Output (on little-endian systems):

    78 56 34 12