diff --git a/src/rtl/mem.zig b/src/rtl/mem.zig new file mode 100644 index 0000000..fb44bc1 --- /dev/null +++ b/src/rtl/mem.zig @@ -0,0 +1,32 @@ +const std = @import("std"); + +/// Read an extern or packed struct's fields with a given endianness from a byte +/// slice. +pub fn read_struct( + comptime T: type, + bytes: []const u8, + comptime endian: std.lang.Endian, +) T { + comptime { + const info = @typeInfo(T); + if (info != .@"struct" or + (info.@"struct".layout != .@"extern" and + info.@"struct".layout != .@"packed")) + { + @compileError("Type must be an 'extern' or 'packed' struct."); + } + } + + var result: T = undefined; + const str = @typeInfo(T).@"struct"; + + inline for (str.field_names, str.field_types) |name, ftype| { + const offset = @offsetOf(T, name); + const size = @sizeOf(ftype); + const field_bytes = bytes[offset .. offset + size]; + + @field(result, name) = std.mem.readInt(ftype, field_bytes, endian); + } + + return result; +} diff --git a/src/rtl/root.zig b/src/rtl/root.zig index ccf1029..d0e21b7 100644 --- a/src/rtl/root.zig +++ b/src/rtl/root.zig @@ -18,6 +18,7 @@ pub const AtomicBitmapType = @import("bitmap.zig").AtomicBitmapType; pub const HandoffList = @import("handoff.zig").HandoffList; pub const LinkerSetType = @import("linker_set.zig").LinkerSetType; pub const CachePaddedType = @import("cache_padded.zig").CachePaddedType; +pub const mem = @import("mem.zig"); pub fn comptime_error(comptime msg: []const u8, args: anytype) void { @compileError(std.fmt.comptimePrint(msg, args));