Skip to content

Instantly share code, notes, and snippets.

@blogscot
Created March 17, 2025 11:12
Show Gist options
  • Save blogscot/99cb08f8101e60843cfbb4e922ac3450 to your computer and use it in GitHub Desktop.
Save blogscot/99cb08f8101e60843cfbb4e922ac3450 to your computer and use it in GitHub Desktop.
Building Zig structs at Compile Time by mht.wtf
/// Building Zig structs at Compile Time by mht.wtf
/// https://mht.wtf/post/comptime-struct/#user-content-fnref-typeinfo
///
/// Reading through the blog post originally written on 11 June 2022 with
/// Zig version 0.9.1, I got the examples working for 0.14.0
///
const std = @import("std");
const print = std.debug.print;
fn Range(comptime T: type) type {
return struct {
start: T,
end: T,
pub fn contains(this: @This(), other: T) bool {
return this.start <= other and other < this.end;
}
};
}
fn MakeStruct(comptime ts: anytype) type {
var fields: [ts.len]std.builtin.Type.StructField = undefined;
for (ts, 0..) |t, i| {
var fieldType: type = t[1];
var fieldName: [:0]const u8 = t[0][0..];
if (fieldName[0] == '?') {
fieldType = @Type(.{ .optional = .{ .child = fieldType } });
fieldName = fieldName[1..];
}
fields[i] = .{
.name = fieldName,
.type = fieldType,
.default_value_ptr = null,
.is_comptime = false,
.alignment = 0,
};
}
return @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = fields[0..],
.decls = &[_]std.builtin.Type.Declaration{},
.is_tuple = false,
} });
}
pub fn main() void {
const Foo = MakeStruct(.{
.{ "someNumber", i32 },
.{ "?aBool", bool },
.{ "?yourString", []const u8 },
});
inline for (@typeInfo(Foo).@"struct".fields, 1..) |field, i| {
print("field {d} is {s}, type is {any}\n", .{ i, field.name, field.type });
}
}
test "range-create" {
const a = Range(i32){
.start = 0,
.end = 10,
};
print("{} {}\n", .{ a.start, a.end });
}
test "range-contains" {
const a = Range(i32){
.start = 0,
.end = 10,
};
try std.testing.expect(a.contains(5));
try std.testing.expect(a.contains(0));
try std.testing.expect(a.contains(9));
try std.testing.expect(!a.contains(10));
try std.testing.expect(!a.contains(-1));
}
test "reify-empty" {
const Type = @Type(.{
.@"struct" = .{
.layout = .auto,
.fields = &[_]std.builtin.Type.StructField{},
.decls = &[_]std.builtin.Type.Declaration{},
.is_tuple = false,
},
});
try std.testing.expect(@sizeOf(Type) == 0);
}
test "make-struct" {
const Type = MakeStruct(.{
.{ "someNumber", i32 },
.{ "?aBool", bool },
.{ "?yourString", []const u8 },
});
inline for (@typeInfo(Type).@"struct".fields, 1..) |field, i| {
print("field {d} is {s}, type is {any}\n", .{ i, field.name, field.type });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment