One thing that is a bit noisy is that you have to specify the bit index when you name the individual bits, as in (from that article):
static let secondDay = ShippingOptions(rawValue: 1 << 1)
Upside from that is that it makes it clear what bit each value specifies, and won’t easily accidentally change them when you reorder definitions, or insert or remove them. I can see why they made that choice.I also guess OptionSet could have been implemented in Swift in a third party library, whereas this Zig feature cannot.
I also think/guess neither language guarantees multiple bits would get read or written in one instruction. If your hardware needs that, you probably have to go down a level, or look at the disassembly of your code to check what your compiler did.
Making a Zig BitSet would probably be doable, for those cases where bitfields are overkill.
https://www.scattered-thoughts.net/writing/mmio-in-zig/
It gets tricky if you need more control over loads and stores, or if there are different address spaces.
> this would require that unions can work on the 'bit level' in packed structs
Just as Zig has packed structs, it also has packed unions. So that part shouldn't be an issue.
const std = @import("std");
const expect = std.testing.expect;
test {
const group1: P = .{ .a = true, .b = true };
const group2: P = .{ .c = true };
const group3 = @bitCast(P, @bitCast(u4, group1) | @bitCast(u4, group2));
try expect(group3.a);
try expect(group3.b);
try expect(group3.c);
try expect(!group3.d);
}
const P = packed struct {
a: bool = false,
b: bool = false,
c: bool = false,
d: bool = false,
};
Maybe Zig can handle this case with unions though, I haven't tried this yet (this would require that unions can work on the 'bit level' in packed structs).