module: expose Module.GlobalEvent type

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-03-25 10:30:13 -07:00 committed by Stephen Gutekanst
parent f3f4524f1b
commit 38e0d576cc
2 changed files with 10 additions and 7 deletions

View file

@ -74,7 +74,7 @@ pub fn World(comptime mods: anytype) type {
world.modules.sendToModule(module_tag, event_name, args);
}
pub inline fn sendGlobal(m: *@This(), comptime event_name: anytype, args: anytype) void {
pub inline fn sendGlobal(m: *@This(), event_name: Modules.GlobalEvent, args: anytype) void {
const mod_ptr: *Mods = @alignCast(@fieldParentPtr(Mods, @tagName(module_tag), m));
const world = @fieldParentPtr(WorldT, "mod", mod_ptr);
world.modules.send(event_name, args);

View file

@ -40,6 +40,8 @@ pub fn Modules(comptime mods: anytype) type {
pub const ModuleID = u32;
pub const EventID = u32;
pub const GlobalEvent = GlobalEventEnum(mods);
const Event = struct {
module_name: ?ModuleID,
event_name: EventID,
@ -98,7 +100,7 @@ pub fn Modules(comptime mods: anytype) type {
/// Returns an args tuple representing the standard, uninjected, arguments which the given
/// global event handler requires.
fn Args(event_name: GlobalEventEnum(mods)) type {
fn Args(event_name: GlobalEvent) type {
inline for (modules) |M| {
_ = Module(M); // Validate the module
@ -129,7 +131,7 @@ pub fn Modules(comptime mods: anytype) type {
pub fn send(
m: *@This(),
// TODO: is a variant of this function where event_name is not comptime known, but asserted to be a valid enum, useful?
comptime event_name: GlobalEventEnum(mods),
comptime event_name: GlobalEvent,
args: Args(event_name),
) void {
// TODO: comptime safety/debugging
@ -215,7 +217,7 @@ pub fn Modules(comptime mods: anytype) type {
}
/// Call global event handler with the specified name in all modules
inline fn callGlobal(event_name: GlobalEventEnum(mods), args: []u8, injectable: anytype) !void {
inline fn callGlobal(event_name: GlobalEvent, args: []u8, injectable: anytype) !void {
if (@typeInfo(@TypeOf(event_name)).Enum.fields.len == 0) return;
switch (event_name) {
inline else => |ev_name| {
@ -403,6 +405,7 @@ fn LocalEventEnum(comptime mods: anytype) type {
/// enum describing every possible comptime-known global event name
fn GlobalEventEnum(comptime mods: anytype) type {
// Note: this function only accesses M.Events' .global name field. No other field is accessed
var enum_fields: []const std.builtin.Type.EnumField = &[0]std.builtin.Type.EnumField{};
var i: u32 = 0;
for (mods) |M| {
@ -643,7 +646,7 @@ test "event name" {
try testing.expect([]const u8, "baz").eql(locals.fields[0].name);
try testing.expect([]const u8, "bam").eql(locals.fields[1].name);
const globals = @typeInfo(GlobalEventEnum(Mods.modules)).Enum;
const globals = @typeInfo(Mods.GlobalEvent).Enum;
try testing.expect(type, u3).eql(globals.tag_type);
try testing.expect(usize, 6).eql(globals.fields.len);
try testing.expect([]const u8, "foo").eql(globals.fields[0].name);
@ -852,7 +855,7 @@ test "event name calling" {
// Check we can use .callGlobal() with a runtime-known event name.
const alloc = try testing.allocator.create(u3);
defer testing.allocator.destroy(alloc);
const GE = GlobalEventEnum(@TypeOf(modules).modules);
const GE = @TypeOf(modules).GlobalEvent;
const LE = LocalEventEnum(@TypeOf(modules).modules);
alloc.* = @intFromEnum(@as(GE, .tick));
@ -968,7 +971,7 @@ test "dispatch" {
try modules.init(testing.allocator);
defer modules.deinit(testing.allocator);
const GE = GlobalEventEnum(@TypeOf(modules).modules);
const GE = @TypeOf(modules).GlobalEvent;
const LE = LocalEventEnum(@TypeOf(modules).modules);
const M = ModuleName(@TypeOf(modules).modules);