Open ikskuh opened 5 months ago
(4) Introduce a new type opaquebits(N)
Whats the rationale that favors this over enum(N) { _ }
? The main difference I can see is that it does not allow == and !=.
bitpacked union(T)
can be used to explicitly specify the size of the union.
Here T
has a completely different meaning to union(T)
, where it is the union's tag type.
See also my proposal https://github.com/ziglang/zig/issues/19395 to resolve this by instead putting the backing type (T)
after the packed
/bitpacked
keyword.
Each field in a BitPacked type has an explicit bit offset and backing type:
The code instead shows backing_integer
being not in BitPackedField
but in BitPacked
- either the text or the code are incorrect (either it's per-field or per-aggregate for all fields).
@Snektron From what I understand it forces using @bitCast
instead of @intFromEnum
and @enumFromInt
.
Besides that it seems pretty much equivalent, only that the enum
can further be extended by declarations.
(It doesn't seem like opaquebits(N)
is meant to have a {}
scope after it, but that's not fully clear to me.)
I like 1-3, I don't see a need for 4, and 5 seems like a complex feature that combines unions and structs that implements #985 but only through a builtin, not syntax.
Whats the rationale that favors this over
enum(N) { _ }
? The main difference I can see is that it does not allow == and !=.I don't see a need for 4
For me, it's something that prevents accidential comparability and allows for types that must not have a defined value (thus, cannot be constructed from zig land). Use case here would be modelling microcontroller register values where some fields have the value "don't ever touch these bits, do not write anything else than what you've read"
(It doesn't seem like opaquebits(N) is meant to have a {} scope after it, but that's not fully clear to me.)
Yeah, it is similar to anyopaque
, but it has to be sizeable. Maybe opaquebit5
or something would also work.
Each field in a BitPacked type has an explicit bit offset and backing type: The code instead shows backing_integer being not in BitPackedField but in BitPacked - either the text or the code are incorrect (either it's per-field or per-aggregate for all fields).
No, both are correct. The backing type of a BitPackedField
is BitPackedField.type
, the backing type of the full struct is BitPacked.backing_integer
bitpacked union(T) can be used to explicitly specify the size of the union. Here T has a completely different meaning to union(T), where it is the union's tag type. See also my proposal https://github.com/ziglang/zig/issues/19395 to resolve this by instead putting the backing type (T) after the packed/bitpacked keyword.
True. Will adapt the original post to respect that, it's reasonable.
5 seems like a complex feature that combines unions and structs that implements https://github.com/ziglang/zig/issues/985 but only through a builtin, not syntax.
I can see that, it's not something that is necessarily needed, but would help in some cases where fields might overlap. But after some considerations, this could also be fully solved by casting between different instances of types
5 might actually be helpful for some osdev interop things where a packed struct field represents the upper bits of an address, aligned with the start of the struct but with lower bits used for other things
5 might actually be helpful for some osdev interop things where a packed struct field represents the upper bits of an address, aligned with the start of the struct but with lower bits used for other things
That was just an example, opaquebit5
is similar to u5
, so `opaquebit31
or opaquebit32
would be valid as well
That was just an example,
opaquebit5
is similar tou5
, so`opaquebit31
oropaquebit32
would be valid as well
not sure what this actually means, i meant point 5 of having something like structlayout.explicit but at bit resolution
This is a plan for hammer out the semantics for bit packed types in the Zig language.
Let's start with a tiny syntactical change:
(1) Rename
packed
tobitpacked
This change will reflect the true meaning of both
packed struct
andpacked union
more thanpacked
and reduces confusion about the type of packing that is performed (as other languages usepacked
for byte packing).This should be trivial to implement and update via
zig fmt
.(2) Improve
bitpacked union
semanticsRight now, the semantics of packed unions are kinda … underdefined:
Let's change that definition to:
This also means that not all union members share the same address, which is true for
extern union
.(3) No changes to
bitpacked struct
Except for the rename of
packed
tobitpacked
, no changes are done here.(4) Introduce a new type
opaquebits(N)
This new type
opaquebits(N)
is an opaque bit bag that has no semantics defined except for "it takes N bits of space".This type can be used for storing fully opaque data and the only way to interpret its content is by using
@bitCast
from and to it.(5) Introduce a new type class
std.builtin.Type.BitPacked
(This is definitly a stretch goal, and might require further work)
This type can be the backing type for both
bitpacked union
andbitpacked struct
, which is similar to a regular struct/union type in that it has typed fields, but lacks most other properties.The
BitPacked
type is a mix of structure and union and inspired by C#StructLayout.Explicit
andFieldOffset
, which allow construction of both structures and unions of an arbitrary layout.This means that it's also legal to allow overlapping fields. For a union type, all
bit_offset
values are 0, for a structure, allbit_offset
fields are layed out such that all fields are back-to-back.Each field in a
BitPacked
type has an explicit bit offset and backing type:It is not legal to create a type with unnamed bits.
Each
BitPacked
type behaves in codegen and on ABI boundaries as if it would beBitPacked.backing_integer
.(6) Incorporate #19395
Use
bitpacked(T) struct
/bitpacked(T) union
instead ofbitpacked struct(T)
bitpacked union
as those are more uniform in what the(T)
actually modifies.Use Case
One example where i'd like to have seen some of these features would be the EDID Video Input Definition:
For additional type safety,
config
could've been done asopaquebits(7)
and afn unpack() union(enum){…}
function could be done that returns either/or contained structure definition.Some other structures in EDID contain even more nested bit field definitions on a singular byte or integer, so a more improved support for bitpacked data can help for sure.
Summary
For me, (1) to (4) are things that are definitly useful and would improve language semantics. (5) is definitly more of a stretch goal.