I have expected that packed structs would behave like, for example, packed structs in GCC. I was very surprised to see uninitialized memory read from valgrind referencing io.Writer.writeStructEndian, so I investigated more and it seems that Zig packed structs can be actually way bigger than the sum of its fields, and at the same time, Zig only initializes the fields, not the remaining padding, which makes it unsafe for use in I/O.
This struct should be 20 bytes long, but Zig considers is to be 32 bytes. Is this intended or a bug?
I’m currently resorting to using custom read/write functions using std.mem.asBytes() and then truncating the slice according to @bitSizeOf() to avoid touching the uninitialized bytes, but it still seems like a bug to me.
Ah, ok, so packed struct will be always backed by n^2 bytes. That makes me wonder if writeStruct should not be removed from std, since it’s unsafe with the uninitialized memory and extremely surprising.
At first, I was excited about the packed structs in Zig, because if I could have bit-level precision over the individual fields, and have the memory layout stable, I thought could actually use this for internal data files.
Yesterday, after I discovered know the API is really not stable and if this bug is to be fixed, like in the PR you mentioned, the format will be broken, I started working on a static msgpack package, that will be able to serialize structs into a known format that will not change.
Thanks to the compile-time type information, it’s actually quite nice to be able to write these structs into msgpack precisely, without having a second compilation step like with protobuf.