zig icon indicating copy to clipboard operation
zig copied to clipboard

`readPackedIntBig` reads from end of array

Open apwadkar opened this issue 1 year ago • 2 comments
trafficstars

Zig Version

0.13.0-dev.73+db890dbae

Steps to Reproduce and Observed Behavior

Godbolt: https://godbolt.org/z/EK87ob593

const std = @import("std");

test "readParsedInt" {
    const slice = [10]u8{0, 0, 0, 1, 0, 0, 0, 2, 3, 1};
    const val = std.mem.readPackedInt(u32, &slice, 0, .big);
    try std.testing.expectEqual(1, val);
}

It reads the last 4 bytes and returns 0x00020301.

Expected Behavior

I was expecting this to read the first 4 bytes of the slice as big-endian (0x00000001), but it seems that this function reads from the back of the array instead.

I've pinpointed the cause to here.

const read_bytes = bytes[(end - byte_count)..end];
const val = @as(uN, @truncate(readInt(LoadInt, bytes[(end - load_size)..end][0..load_size], .big) >> bit_shift));

apwadkar avatar May 12 '24 20:05 apwadkar

Big endian packed memory layouts start from the end of the buffer. A bit offset of 0 means 0 bits from the end of the buffer. Afaict this is correct behavior.

qwerasd205 avatar Jul 15 '24 17:07 qwerasd205

This is not the behavior I would expect when working with big endian. The "first" bit of any given buffer would, to my reckoning, be the highest bit of the most significant byte. This is how it works in BitReader and it is how streams of big-endian bits work when I've encountered them in the wild.

@topolarity can you explain the reasoning behind this behavior? I'm guessing that the idea is that Zig packs bit fields low-to-high regardless of architecture and is this is designed to match that?

tgschultz avatar Oct 14 '24 21:10 tgschultz