I’m trying to do more DoD, but struggling with some ergonomic issues.
I have a const Spec = enum(u4) {...} and I want to store 8 of it. What is the best option ? [8]Spec seems to defeat the purpose of packing stuff in a u4 in the first place, @Vector(Spec, 8) doesn’t compile because Spec isn’t an int.
I think in 0.17 you can make use of @bitCast to make the implementation smaller, because bitcast will look at the “logical bit layout” instead of the actual size
Another idea I played with was to also have a struct where each member is accessed by @“number” so first element would be accessed by @“0”, I don’t see any real uses for it but here it is
const fieldNames: [N][]const u8 = comptime D: {
var ans: [N][]const u8 = undefined;
@setEvalBranchQuota(10000);
for (0..N) |i| {
ans[i] = std.fmt.comptimePrint("{}", .{i});
}
break :D ans;
};
return packed union {
num: BackingInt,
structType: StructType,
pub const StructType = @Struct(.@"packed", null, &fieldNames, &@splat(T), &@splat(.{}));
// Rest of the code is the same
I think a “packed [N]T” type would be nice, where the language guaranteed packs it for you, it wouldn’t add any keywords to the language and it’s clear what it does.
If you meant why I did so instead of initializing it to undefined, it’s because undefined is infectious; any undefined bit leaves the whole value undefined. Zig doesn’t track it to the bit-level so, for example:
const Foo = packed struct(u8) { x: u1, y: u7 };
const foo: Foo = undefined;
foo.y = 20; // The value will still be undefined, you must modify `foo` as a whole.
This is because packed struct field access is just syntax sugar for reading, ANDing/ORing and shifting the bits in the integer and writing. Removing that syntax sugar would make it look like this:
var foo: u8 = undefined;
foo = (foo & 0x80) | 20; // which is basically `(undefined & 0x80) | 20`
Thanks, so the issue is LLVM tracking undefined at the byte level only. So having undefinded bits, may trigger optimizations that discard all the content of the packed struct.