pub fn byteSwapAligned(
comptime S: type,
comptime a: Alignment,
ptr: *align(a.toByteUnits()) S,
) void {
switch (@typeInfo(S)) {
.@"struct" => |@"struct"| {
if (@"struct".backing_integer) |Int| {
ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
} else {
if (@"struct".layout != .@"extern") {
@compileError("byteSwapAligned expects a packed or extern struct");
}
inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
switch (@typeInfo(f_type)) {
.@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"enum" => {
@field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name))));
},
.bool => {},
.float => |float| {
@field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));
},
else => {
@field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
},
}
}
}
},
.@"union" => |@"union"| if (@"union".backing_integer) |Int| {
ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
} else {
if (@"union".layout != .@"extern") {
@compileError("byteSwapAligned expects a packed or extern union");
}
const first_size = @bitSizeOf(@"union".field_types[0]);
inline for (@"union".field_types) |field_type| {
if (@bitSizeOf(field_type) != first_size) {
@compileError("Unable to byte-swap unions with varying field sizes");
}
}
const FieldInt = @Int(.unsigned, first_size);
const field_ptr = &@field(ptr, @"union".field_names[0]);
field_ptr.* = @bitCast(@byteSwap(@as(FieldInt, @bitCast(field_ptr.*))));
},
.array => |array| {
byteSwapAllElements(array.child, ptr);
},
.@"enum" => {
ptr.* = @fromBackingInt(@byteSwap(@backingInt(ptr.*)));
},
.bool => {},
.float => |float| {
const int_repr: @Int(.unsigned, float.bits) = @bitCast(ptr.*);
ptr.* = @bitCast(@byteSwap(int_repr));
},
else => {
ptr.* = @byteSwap(ptr.*);
},
}
}
Reverses the byte order. Handles structs, unions, arrays, enums, floats, and integers recursively. The order of extern struct fields and array elements remains unchanged and will be byte swapped recursively. Useful for converting between little-endian and big-endian representations.