Function byteSwapAllFields [src]
Swap the byte order of all the members of the fields of a struct
(Changing their endianness)
Prototype
pub fn byteSwapAllFields(comptime S: type, ptr: *S) void Parameters
S: typeptr: *S Example
test byteSwapAllFields {
const T = extern struct {
f0: u8,
f1: u16,
f2: u32,
f3: [1]u8,
f4: bool,
f5: f32,
f6: extern union { f0: u16, f1: u16 },
};
const K = extern struct {
f0: u8,
f1: T,
f2: u16,
f3: [1]u8,
f4: bool,
f5: f32,
};
var s = T{
.f0 = 0x12,
.f1 = 0x1234,
.f2 = 0x12345678,
.f3 = .{0x12},
.f4 = true,
.f5 = @as(f32, @bitCast(@as(u32, 0x4640e400))),
.f6 = .{ .f0 = 0x1234 },
};
var k = K{
.f0 = 0x12,
.f1 = s,
.f2 = 0x1234,
.f3 = .{0x12},
.f4 = false,
.f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),
};
byteSwapAllFields(T, &s);
byteSwapAllFields(K, &k);
try std.testing.expectEqual(T{
.f0 = 0x12,
.f1 = 0x3412,
.f2 = 0x78563412,
.f3 = .{0x12},
.f4 = true,
.f5 = @as(f32, @bitCast(@as(u32, 0x00e44046))),
.f6 = .{ .f0 = 0x3412 },
}, s);
try std.testing.expectEqual(K{
.f0 = 0x12,
.f1 = s,
.f2 = 0x3412,
.f3 = .{0x12},
.f4 = false,
.f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),
}, k);
} Source
pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
switch (@typeInfo(S)) {
.@"struct" => {
inline for (std.meta.fields(S)) |f| {
switch (@typeInfo(f.type)) {
.@"struct" => |struct_info| if (struct_info.backing_integer) |Int| {
@field(ptr, f.name) = @bitCast(@byteSwap(@as(Int, @bitCast(@field(ptr, f.name)))));
} else {
byteSwapAllFields(f.type, &@field(ptr, f.name));
},
.@"union", .array => byteSwapAllFields(f.type, &@field(ptr, f.name)),
.@"enum" => {
@field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));
},
.bool => {},
.float => |float_info| {
@field(ptr, f.name) = @bitCast(@byteSwap(@as(std.meta.Int(.unsigned, float_info.bits), @bitCast(@field(ptr, f.name)))));
},
else => {
@field(ptr, f.name) = @byteSwap(@field(ptr, f.name));
},
}
}
},
.@"union" => |union_info| {
if (union_info.tag_type != null) {
@compileError("byteSwapAllFields expects an untagged union");
}
const first_size = @bitSizeOf(union_info.fields[0].type);
inline for (union_info.fields) |field| {
if (@bitSizeOf(field.type) != first_size) {
@compileError("Unable to byte-swap unions with varying field sizes");
}
}
const BackingInt = std.meta.Int(.unsigned, @bitSizeOf(S));
ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));
},
.array => |info| {
byteSwapAllElements(info.child, ptr);
},
else => {
ptr.* = @byteSwap(ptr.*);
},
}
}