Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.mem.bytesAsValue does not work for non-standard integer sizes #12948

Closed
zxubian opened this issue Sep 24, 2022 · 1 comment
Closed

std.mem.bytesAsValue does not work for non-standard integer sizes #12948

zxubian opened this issue Sep 24, 2022 · 1 comment
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@zxubian
Copy link

zxubian commented Sep 24, 2022

Zig Version

0.9.1 (windows, chocolatey)

Steps to Reproduce

Compile and run the following code:

const std = @import("std");

const Test = packed struct {
    value: u48,
};

fn print_members(comptime T: type, struct_pointer: *T) void {
    var raw_bytes = @ptrCast([*]u8, std.mem.asBytes(struct_pointer));
    comptime var start_index: u32 = 0;
    inline for (std.meta.fields(T)) |field| {
        const length = @bitSizeOf(field.field_type) / 8;
        const slice = raw_bytes[start_index .. start_index + length];
        const value_ptr = std.mem.bytesAsValue(field.field_type, slice);
        std.log.info("{}", .{value_ptr.*});
        start_index += length;
    }
}

pub fn main() !void {
    var t = Test{ .value = 0 };
    print_members(Test, &t);
}

Expected Behavior

Code compiles and runs.
Log output should print out "0".

Actual Behavior

The following error is printed out:

C:\ProgramData\chocolatey\lib\zig\tools\zig-windows-x86_64-0.9.1\lib\std\mem.zig:2582:9: error: expected *[8]u8, passed *[6]u8
        @compileError(std.fmt.bufPrint(&buf, "expected *[{}]u8, passed " ++ @typeName(B), .{size}) catch unreachable);
        ^
C:\ProgramData\chocolatey\lib\zig\tools\zig-windows-x86_64-0.9.1\lib\std\mem.zig:2590:77: note: called from here
pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T, @TypeOf(bytes)) {
                                                                            ^
C:\ProgramData\chocolatey\lib\zig\tools\zig-windows-x86_64-0.9.1\lib\std\mem.zig:2590:77: note: called from here
pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T, @TypeOf(bytes)) {

This is because BytesAsValueReturnType in std.mem uses @sizeOf to obtain the size of the type. However, this will include the size of the padding, causing a size mismatch.

// std.mem
fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
    const size = @as(usize, @sizeOf(T)); /// <<<<<< here

    if (comptime !trait.is(.Pointer)(B) or
        (meta.Child(B) != [size]u8 and meta.Child(B) != [size:0]u8))
    {
        comptime var buf: [100]u8 = undefined;
        @compileError(std.fmt.bufPrint(&buf, "expected *[{}]u8, passed " ++ @typeName(B), .{size}) catch unreachable);
    }

    return CopyPtrAttrs(B, .One, T);
}

If the function is not designed to work with non-standard int sizes, a compiler check could be added to detect improper usage ( e.g. by checking if the packed size is same as size with padding).
Additionally, documentation could be improved to clearly state this (currently, the docs for the function state the following:)

/// Given a pointer to an array of bytes, returns a pointer to a value of the specified type
/// backed by those bytes, preserving pointer attributes.
@zxubian zxubian added the bug Observed behavior contradicts documented or intended behavior label Sep 24, 2022
@zxubian
Copy link
Author

zxubian commented Sep 24, 2022

Sorry, I've just noticed this is a duplicate of:
#10958

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

1 participant