ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
35.02k stars 2.56k forks source link

`readPackedIntBig` reads from end of array #19953

Open apwadkar opened 6 months ago

apwadkar commented 6 months ago

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));
qwerasd205 commented 4 months ago

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.

tgschultz commented 1 month ago

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?