authorgravatar for sebastiancasper3@gmail.comSteven Casper <sebastiancasper3@gmail.com> 2025-12-29 02:36:11+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-29 02:36:11+01:00
log8d4a9119b80fd263ce4c8b5745b88953914acdb9
tree4af7e1a465863426a1d77b67297ef5cc2e134442
parente8a2e6578a3f5e4cd82eb59388e49e152728791e

Properly support passing a packed struct to byteSwapAllFields (#30571)

Reopening [#25698](https://github.com/ziglang/zig/pull/25698) Closes [#25054](https://github.com/ziglang/zig/issues/25054) Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30571 Reviewed-by: Andrew Kelley <andrewrk@noreply.codeberg.org> Co-authored-by: Steven Casper <sebastiancasper3@gmail.com> Co-committed-by: Steven Casper <sebastiancasper3@gmail.com>

1 files changed, 40 insertions(+), 8 deletions(-)

lib/std/mem.zig+40-8
......@@ -2252,16 +2252,20 @@ test writeVarPackedInt {
22522252/// Swap the byte order of all the members of the fields of a struct
22532253/// (Changing their endianness)
22542254pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
2255 byteSwapAllFieldsAligned(S, @alignOf(S), ptr);
2256}
2257
2258/// Swap the byte order of all the members of the fields of a struct
2259/// (Changing their endianness)
2260pub fn byteSwapAllFieldsAligned(comptime S: type, comptime A: comptime_int, ptr: *align(A) S) void {
22552261 switch (@typeInfo(S)) {
2256 .@"struct" => {
2257 inline for (std.meta.fields(S)) |f| {
2262 .@"struct" => |struct_info| {
2263 if (struct_info.backing_integer) |Int| {
2264 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2265 } else inline for (std.meta.fields(S)) |f| {
22582266 switch (@typeInfo(f.type)) {
2259 .@"struct" => |struct_info| if (struct_info.backing_integer) |Int| {
2260 @field(ptr, f.name) = @bitCast(@byteSwap(@as(Int, @bitCast(@field(ptr, f.name)))));
2261 } else {
2262 byteSwapAllFields(f.type, &@field(ptr, f.name));
2263 },
2264 .@"union", .array => byteSwapAllFields(f.type, &@field(ptr, f.name)),
2267 .@"struct" => byteSwapAllFieldsAligned(f.type, f.alignment, &@field(ptr, f.name)),
2268 .@"union", .array => byteSwapAllFieldsAligned(f.type, f.alignment, &@field(ptr, f.name)),
22652269 .@"enum" => {
22662270 @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));
22672271 },
......@@ -2317,6 +2321,20 @@ test byteSwapAllFields {
23172321 f4: bool,
23182322 f5: f32,
23192323 };
2324 const P = packed struct(u32) {
2325 f0: u1,
2326 f1: u7,
2327 f2: u4,
2328 f3: u4,
2329 f4: u16,
2330 };
2331 const A = extern struct {
2332 f0: u32,
2333 f1: extern struct {
2334 f0: u64,
2335 } align(4),
2336 f2: u32,
2337 };
23202338 var s = T{
23212339 .f0 = 0x12,
23222340 .f1 = 0x1234,
......@@ -2334,8 +2352,16 @@ test byteSwapAllFields {
23342352 .f4 = false,
23352353 .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),
23362354 };
2355 var p: P = @bitCast(@as(u32, 0x01234567));
2356 var a: A = A{
2357 .f0 = 0x12345678,
2358 .f1 = .{ .f0 = 0x123456789ABCDEF0 },
2359 .f2 = 0x87654321,
2360 };
23372361 byteSwapAllFields(T, &s);
23382362 byteSwapAllFields(K, &k);
2363 byteSwapAllFields(P, &p);
2364 byteSwapAllFields(A, &a);
23392365 try std.testing.expectEqual(T{
23402366 .f0 = 0x12,
23412367 .f1 = 0x3412,
......@@ -2353,6 +2379,12 @@ test byteSwapAllFields {
23532379 .f4 = false,
23542380 .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),
23552381 }, k);
2382 try std.testing.expectEqual(@as(P, @bitCast(@as(u32, 0x67452301))), p);
2383 try std.testing.expectEqual(A{
2384 .f0 = 0x78563412,
2385 .f1 = .{ .f0 = 0xF0DEBC9A78563412 },
2386 .f2 = 0x21436587,
2387 }, a);
23562388}
23572389
23582390/// Reverses the byte order of all elements in a slice.