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 {...@@ -2252,16 +2252,20 @@ test writeVarPackedInt {
2252/// Swap the byte order of all the members of the fields of a struct2252/// Swap the byte order of all the members of the fields of a struct
2253/// (Changing their endianness)2253/// (Changing their endianness)
2254pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {2254pub 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 {
2255 switch (@typeInfo(S)) {2261 switch (@typeInfo(S)) {
2256 .@"struct" => {2262 .@"struct" => |struct_info| {
2257 inline for (std.meta.fields(S)) |f| {2263 if (struct_info.backing_integer) |Int| {
2264 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2265 } else inline for (std.meta.fields(S)) |f| {
2258 switch (@typeInfo(f.type)) {2266 switch (@typeInfo(f.type)) {
2259 .@"struct" => |struct_info| if (struct_info.backing_integer) |Int| {2267 .@"struct" => byteSwapAllFieldsAligned(f.type, f.alignment, &@field(ptr, f.name)),
2260 @field(ptr, f.name) = @bitCast(@byteSwap(@as(Int, @bitCast(@field(ptr, f.name)))));2268 .@"union", .array => byteSwapAllFieldsAligned(f.type, f.alignment, &@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)),
2265 .@"enum" => {2269 .@"enum" => {
2266 @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));2270 @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));
2267 },2271 },
...@@ -2317,6 +2321,20 @@ test byteSwapAllFields {...@@ -2317,6 +2321,20 @@ test byteSwapAllFields {
2317 f4: bool,2321 f4: bool,
2318 f5: f32,2322 f5: f32,
2319 };2323 };
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 };
2320 var s = T{2338 var s = T{
2321 .f0 = 0x12,2339 .f0 = 0x12,
2322 .f1 = 0x1234,2340 .f1 = 0x1234,
...@@ -2334,8 +2352,16 @@ test byteSwapAllFields {...@@ -2334,8 +2352,16 @@ test byteSwapAllFields {
2334 .f4 = false,2352 .f4 = false,
2335 .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),2353 .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),
2336 };2354 };
2355 var p: P = @bitCast(@as(u32, 0x01234567));
2356 var a: A = A{
2357 .f0 = 0x12345678,
2358 .f1 = .{ .f0 = 0x123456789ABCDEF0 },
2359 .f2 = 0x87654321,
2360 };
2337 byteSwapAllFields(T, &s);2361 byteSwapAllFields(T, &s);
2338 byteSwapAllFields(K, &k);2362 byteSwapAllFields(K, &k);
2363 byteSwapAllFields(P, &p);
2364 byteSwapAllFields(A, &a);
2339 try std.testing.expectEqual(T{2365 try std.testing.expectEqual(T{
2340 .f0 = 0x12,2366 .f0 = 0x12,
2341 .f1 = 0x3412,2367 .f1 = 0x3412,
...@@ -2353,6 +2379,12 @@ test byteSwapAllFields {...@@ -2353,6 +2379,12 @@ test byteSwapAllFields {
2353 .f4 = false,2379 .f4 = false,
2354 .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),2380 .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),
2355 }, k);2381 }, 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);
2356}2388}
23572389
2358/// Reverses the byte order of all elements in a slice.2390/// Reverses the byte order of all elements in a slice.