Created
March 17, 2025 11:12
-
-
Save blogscot/99cb08f8101e60843cfbb4e922ac3450 to your computer and use it in GitHub Desktop.
Building Zig structs at Compile Time by mht.wtf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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