Last active
June 7, 2022 15:49
-
-
Save garettbass/e2fa65955fb17a09bd22c339ba564ea3 to your computer and use it in GitHub Desktop.
A generic type that maps provided types to monotonically increasing integers.
This file contains 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
const std = @import("std"); | |
pub fn TypeIndexGenerator(comptime TIndex: type) type { | |
const index_info = @typeInfo(TIndex); | |
const TInt = switch (index_info) { | |
.Int => TIndex, | |
.Enum => |t| if (t.is_exhaustive) | |
@compileError("TIndex enum must be non-exhaustive") | |
else | |
t.tag_type, | |
else => @compileError("TIndex must be an enum or integer type"), | |
}; | |
comptime var next_int: TInt = 0; | |
return struct { | |
const Int = TInt; | |
const Index = TIndex; | |
fn intToIndex(int: Int) Index { | |
return switch (index_info) { | |
.Int => int, | |
.Enum => @intToEnum(Index, int), | |
else => unreachable, | |
}; | |
} | |
fn IndexOf(comptime T: type) type { | |
const int = next_int; | |
next_int += 1; | |
return struct { | |
const Type = T; | |
const index = intToIndex(int); | |
}; | |
} | |
pub fn indexOf(comptime T: type) Index { | |
return IndexOf(T).index; | |
} | |
}; | |
} | |
test "TypeIndexGenerator(Enum)" { | |
const Foo = struct {}; | |
const Bar = struct {}; | |
const Baz = struct {}; | |
const Enum = enum(u8) { | |
_, | |
const Self = @This(); | |
pub fn init(n: u8) Self { | |
return @intToEnum(Self, n); | |
} | |
pub fn toInt(self: Self) u8 { | |
return @enumToInt(self); | |
} | |
}; | |
const Generator = TypeIndexGenerator(Enum); | |
const print = std.debug.print; | |
print("\n", .{}); | |
print(" indexOf(void): {}\n", .{Generator.indexOf(void)}); | |
print(" indexOf(void): {}\n", .{Generator.indexOf(void)}); | |
print(" indexOf(bool): {}\n", .{Generator.indexOf(bool)}); | |
print(" indexOf(bool): {}\n", .{Generator.indexOf(bool)}); | |
print(" indexOf(Foo): {}\n", .{Generator.indexOf(Foo)}); | |
print(" indexOf(Foo): {}\n", .{Generator.indexOf(Foo)}); | |
print(" indexOf(Bar): {}\n", .{Generator.indexOf(Bar)}); | |
print(" indexOf(Bar): {}\n", .{Generator.indexOf(Bar)}); | |
print(" indexOf(Baz): {}\n", .{Generator.indexOf(Baz)}); | |
print(" indexOf(Baz): {}\n", .{Generator.indexOf(Baz)}); | |
const expectEqual = std.testing.expectEqual; | |
try expectEqual(Enum.init(0), Generator.indexOf(void)); | |
try expectEqual(Enum.init(0), Generator.indexOf(void)); | |
try expectEqual(Enum.init(1), Generator.indexOf(bool)); | |
try expectEqual(Enum.init(1), Generator.indexOf(bool)); | |
try expectEqual(Enum.init(2), Generator.indexOf(Foo)); | |
try expectEqual(Enum.init(2), Generator.indexOf(Foo)); | |
try expectEqual(Enum.init(3), Generator.indexOf(Bar)); | |
try expectEqual(Enum.init(3), Generator.indexOf(Bar)); | |
try expectEqual(Enum.init(4), Generator.indexOf(Baz)); | |
try expectEqual(Enum.init(4), Generator.indexOf(Baz)); | |
} | |
test "TypeIndexGenerator(u32)" { | |
const Foo = struct {}; | |
const Bar = struct {}; | |
const Baz = struct {}; | |
const Generator = TypeIndexGenerator(u32); | |
const print = std.debug.print; | |
print("\n", .{}); | |
print(" indexOf(void): {}\n", .{Generator.indexOf(void)}); | |
print(" indexOf(void): {}\n", .{Generator.indexOf(void)}); | |
print(" indexOf(bool): {}\n", .{Generator.indexOf(bool)}); | |
print(" indexOf(bool): {}\n", .{Generator.indexOf(bool)}); | |
print(" indexOf(Foo): {}\n", .{Generator.indexOf(Foo)}); | |
print(" indexOf(Foo): {}\n", .{Generator.indexOf(Foo)}); | |
print(" indexOf(Bar): {}\n", .{Generator.indexOf(Bar)}); | |
print(" indexOf(Bar): {}\n", .{Generator.indexOf(Bar)}); | |
print(" indexOf(Baz): {}\n", .{Generator.indexOf(Baz)}); | |
print(" indexOf(Baz): {}\n", .{Generator.indexOf(Baz)}); | |
const expectEqual = std.testing.expectEqual; | |
try expectEqual(@as(u32, 0), Generator.indexOf(void)); | |
try expectEqual(@as(u32, 0), Generator.indexOf(void)); | |
try expectEqual(@as(u32, 1), Generator.indexOf(bool)); | |
try expectEqual(@as(u32, 1), Generator.indexOf(bool)); | |
try expectEqual(@as(u32, 2), Generator.indexOf(Foo)); | |
try expectEqual(@as(u32, 2), Generator.indexOf(Foo)); | |
try expectEqual(@as(u32, 3), Generator.indexOf(Bar)); | |
try expectEqual(@as(u32, 3), Generator.indexOf(Bar)); | |
try expectEqual(@as(u32, 4), Generator.indexOf(Baz)); | |
try expectEqual(@as(u32, 4), Generator.indexOf(Baz)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment