Skip to content

Instantly share code, notes, and snippets.

@garettbass
Last active June 7, 2022 15:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save garettbass/e2fa65955fb17a09bd22c339ba564ea3 to your computer and use it in GitHub Desktop.
Save garettbass/e2fa65955fb17a09bd22c339ba564ea3 to your computer and use it in GitHub Desktop.
A generic type that maps provided types to monotonically increasing integers.
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