Skip to content

std.mem.byteSwapAllFields not working with packed structs. #25054

@AndrewKraevskii

Description

@AndrewKraevskii

Zig Version

0.16.0-dev.43+99b2b6151

Steps to Reproduce and Observed Behavior

const std = @import("std");

const A = packed struct(u8) {
    a: u4,
    b: u4,
};

test {
    var foo: A = undefined;
    std.mem.byteSwapAllFields(A, &foo);
}
/home/andrewkraevskii/.zvm/master/lib/std/mem.zig:2159:57: error: @byteSwap requires the number of bits to be evenly divisible by 8, but u4 has 4 bits
                        @field(ptr, f.name) = @byteSwap(@field(ptr, f.name));
                                                        ^~~~~~~~~~~~~~~~~~~
referenced by:
    test_0: main.zig:10:30

Provided example by itself is not really useful but I encountered this issue while porting to writergate. std.Io.Reader.readSliceEndianAlloc uses this function internally and it prevents me from been able to read Slices of packed structs.

Mentioned code looked something like these:

const std = @import("std");
const A = packed struct(u32) {
    block_metadata: u4,
    block_id: u12,
    y_coordinate: u8,
    /// relative to chunk
    z_coordinate: u4,
    /// relative to chunk
    x_coordinate: u4,
};
test {
    var in: [0x100]u8 = undefined;
    var fixed: std.Io.Reader = .fixed(&in);

    std.testing.allocator.free(try fixed.readSliceEndianAlloc(std.testing.allocator, A, 100, .big));
}

Expected Behavior

I expect this code to compile successfully. packed struct is just a number so handling of endians shouldn't go through fields one by one and instead flip entire packed struct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions