zig
zig copied to clipboard
std.mem.writeInt doesn't handle non-standard int sizes
Zig Version
0.12.0
Steps to Reproduce and Observed Behavior
test "writeInt error" {
const buffer: [16]u8 = undefined;
std.mem.writeInt( u2, &buffer, 1, .little );
}
Output:
/nix/store/vf2rryw77159s12x867whp05ayb7icpj-zig-0.12.0/lib/std/mem.zig:1807:52: error: exact division produced remainder
pub inline fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T, endian: Endian) void {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/nairou/Downloads/test_error.zig:5:21: note: called from here
std.mem.writeInt( u2, &buffer, 1, .little );
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
Expected Behavior
Previous writeIntLittle()
behavior, where the calculated number of bytes gets rounded up to the next whole byte, rather than assumed to already be a multiple of 8 bits.
The docs say that integers passed to writeInt
must have a bit width divisible by 8.
I believe the function for this case is now writePackedInt
: https://ziglang.org/documentation/0.12.0/std/#std.mem.writePackedInt
I considered writePackedInt
, but that would give a different result. If I have, say, a u21
field in a struct, I'd like it padded out to 32-bits in the stream, rather than offsetting the rest of the stream by an arbitrary number of bits.
I've gotten around the issue by wrapping the int in std.math.ByteAlignedInt
before writing, but it seems like a weird/arbitrary restriction to require this.
I agree with Nairou, this makes it harder to use the function for no reason. Plus, it's not clear how you can do this. Maybe better documentation is the solution.
Imagine you have the following:
var out_buffer: []u8 = try allocator.alloc(u8, some_length);
var some_number: u64 = 999;
var some_position: usize = <unknown at comptime>;
std.mem.writeInt(u64, out[some_position..some_position+8], some_number, .big);
That example throws:
expected type '*const [8]u8', found '[]u8'
What is the correct way to fix this?
Edit: Nairou's solution of using std.math.ByteAlignedInt
does not work here because you need to know the size at compile time.