kj4tmp
December 23, 2024, 7:50am
1
How do I obtain the union payload from a union provided as an anytype parameter?
fn foo (my_union: anytype) void {
const payload = ???;
std.debug.print("{}", .{payload});
}
test "union payload" {
const MyUnion = union(enum) {
num: u8,
num2: u16,
};
// this should print 3
foo(MyUnion{.num= 3});
}
dimdin
December 23, 2024, 8:32am
2
switch for the type first and then for the union.
const std = @import("std");
const MyUnion = union(enum) {
num: u8,
num2: u16,
};
fn foo(my_union: anytype) void {
const payload = switch (@TypeOf(my_union)) {
MyUnion => switch (@as(MyUnion, my_union)) {
.num => |num| num,
.num2 => |num2| num2,
},
else => unreachable,
};
std.debug.print("{}", .{payload});
}
test "union payload" {
// this should print 3
foo(MyUnion{ .num = 3 });
}
kj4tmp
December 23, 2024, 8:37am
3
In my use case, foo cannot know the types it may be called with. foo is part of the library and users call foo with their own unions.
Travis
December 23, 2024, 8:47am
4
You can switch with inline else to get the payload. You might not need it but i’ve also shown how you can capture tag.
const std = @import("std");
const MyUnion = union(enum) {
num: u8,
num2: u16,
};
fn foo(my_union: anytype) void {
switch (my_union) {
// tag is comptime known and may be used in @field(my_union, @tagName(tag))
// or @unionInit(MyUnion, @tagName(tag), payload)
inline else => |payload, tag| {
std.debug.print("{s} {}\n", .{ @tagName(tag), payload });
},
}
}
test "union payload" {
foo(MyUnion{ .num = 3 }); // prints 'num 3'
foo(MyUnion{ .num2 = 4 }); // prints 'num2 4'
}
More info https://ziglang.org/documentation/0.13.0/#Inline-Switch-Prongs
5 Likes
dimdin
December 23, 2024, 8:53am
5
That’s great!
If restructured to the requested form, it becomes:
const std = @import("std");
fn foo(my_union: anytype) void {
const payload = switch (my_union) {
inline else => |payload| payload,
};
std.debug.print("{}", .{payload});
}
test "union payload" {
const MyUnion = union(enum) {
num: u8,
num2: u16,
};
// this should print 3
foo(MyUnion{ .num = 3 });
}
2 Likes
Travis
December 23, 2024, 11:54pm
6
You’ll have problems with this if you add more types to the union which don’t coerce such as a []const u8 field. Thats why i moved the print within switch prong.
2 Likes