about summary refs log tree commit diff
path: root/lang/zig/union-tag.zig
blob: 6954c736bd6cecff98ea46db6a020b921afb5f8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const eql = std.mem.eql;
const expect = std.testing.expect;
const std = @import("std");

const ComplexTypeTag = enum { ok, not_ok };
const ComplexType = union(ComplexTypeTag) { ok: u8, not_ok: void };

test "switch on tagged union" {
    const c = ComplexType{ .ok = 42 };
    expect(@as(ComplexTypeTag, c) == ComplexTypeTag.ok);

    switch (c) {
        ComplexTypeTag.ok => |value| expect(value == 42),
        ComplexTypeTag.not_ok => unreachable,
    }
}

test "@TagType" {
    expect(@TagType(ComplexType) == ComplexTypeTag);
}

test "coerce to enum" {
    const c1: ComplexType = ComplexType{ .ok = 42 };
    const c2: ComplexTypeTag = ComplexType.not_ok;
    expect(c1 == .ok);
    expect(c2 == .not_ok);
}

test "modify tagged union in switch" {
    var c = ComplexType{ .ok = 42 };
    expect(c == .ok);

    switch (c) {
        ComplexTypeTag.ok => |*value| value.* += 1,
        ComplexTypeTag.not_ok => unreachable,
    }

    expect(c.ok == 43);
}

const Variant = union(enum) {
    int: i32,
    boolean: bool,

    // void can be omitted when inferring enum tag type.
    none,

    fn truthy(self: Variant) bool {
        return switch (self) {
            Variant.int => |x_int| x_int != 0,
            Variant.boolean => |x_bool| x_bool,
            Variant.none => false,
        };
    }
};

test "union method" {
    var v1 = Variant{ .int = 420 };
    var v2 = Variant{ .boolean = false };

    expect(v1.truthy());
    expect(!v2.truthy());
}

const Small2 = union(enum) { a: i32, b: bool, c: u8 };
test "@tagName" {
    expect(eql(u8, @tagName(Small2.a), "a"));
}