Swap the byte order of all the members of the fields of a struct (Changing their endianness)
pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void
pub fn byteSwapAllFieldsAligned(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 inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
switch (@typeInfo(f_type)) {
.@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"enum" => {
@field(ptr, f_name) = @fromBackingInt(@intCast(@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("byteSwapAllFields 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);
},
else => {
ptr.* = @byteSwap(ptr.*);
},
}
}