From 2c773bef71cdfd1a628b5ffb68d4a272a59c3505 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Thu, 21 Nov 2024 11:43:19 -0500 Subject: [PATCH] only support void hooks --- src/nu/hooks.zig | 166 ++++++++--------------------------------------- 1 file changed, 27 insertions(+), 139 deletions(-) diff --git a/src/nu/hooks.zig b/src/nu/hooks.zig index 8e6b4e1..1039d1e 100644 --- a/src/nu/hooks.zig +++ b/src/nu/hooks.zig @@ -2,69 +2,37 @@ const std = @import("std"); pub fn Hook(ftype: type) type { const F: std.builtin.Type.Fn = @typeInfo(ftype).Fn; - const Result: type = F.return_type.?; + const R: std.builtin.Type = @typeInfo(F.return_type.?); + comptime if (R != .Void) @compileError("Hook signature must return void."); - return switch (@typeInfo(Result)) { - .Void => struct { - const Self = @This(); + return struct { + const Self = @This(); - handlers: std.AutoArrayHashMap(*const ftype, void), + handlers: std.AutoArrayHashMap(*const ftype, void), - pub fn init(alloc: std.mem.Allocator) Self { - return Self{ - .handlers = std.AutoArrayHashMap(*const ftype, void).init(alloc), - }; + pub fn init(alloc: std.mem.Allocator) Self { + return Self{ + .handlers = std.AutoArrayHashMap(*const ftype, void).init(alloc), + }; + } + + pub fn deinit(self: *Self) void { + self.handlers.deinit(); + } + + pub fn register(self: *Self, f: ftype) !void { + try self.handlers.putNoClobber(f, {}); + } + + pub fn unregister(self: *Self, f: ftype) void { + _ = self.handlers.orderedRemove(f); + } + + pub fn invoke(self: Self, args: anytype) void { + for (self.handlers.keys()) |handler| { + @call(.auto, handler, args); } - - pub fn deinit(self: *Self) void { - self.handlers.deinit(); - } - - pub fn register(self: *Self, f: ftype) !void { - try self.handlers.putNoClobber(f, {}); - } - - pub fn unregister(self: *Self, f: ftype) void { - _ = self.handlers.orderedRemove(f); - } - - pub fn invoke(self: Self, args: anytype) void { - for (self.handlers.keys()) |handler| { - @call(.auto, handler, args); - } - } - }, - else => struct { - const Self = @This(); - - handlers: std.AutoArrayHashMap(*const ftype, void), - - pub fn init(alloc: std.mem.Allocator) Self { - return Self{ - .handlers = std.AutoArrayHashMap(*const ftype, void).init(alloc), - }; - } - - pub fn deinit(self: *Self) void { - self.handlers.deinit(); - } - - pub fn register(self: *Self, f: ftype) !void { - try self.handlers.putNoClobber(f, {}); - } - - pub fn unregister(self: *Self, f: ftype) void { - _ = self.handlers.orderedRemove(f); - } - - pub fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result { - const results = try alloc.alloc(Result, self.handlers.count()); - for (self.handlers.keys(), results) |handler, *result| { - result.* = @call(.auto, handler, args); - } - return results; - } - }, + } }; } @@ -112,83 +80,3 @@ test "void hooks" { set_flags.invoke(.{&flag}); try std.testing.expect(flag == 0b00); } - -test "collect hooks" { - var collect = Hook(fn (usize) usize).init(std.testing.allocator); - defer collect.deinit(); - - const hooks = struct { - pub fn double(f: usize) usize { - return f * 2; - } - - pub fn square(f: usize) usize { - return f * f; - } - }; - - { - const result = try collect.invoke(std.testing.allocator, .{3}); - defer std.testing.allocator.free(result); - try std.testing.expectEqualSlices(usize, &.{}, result); - } - - try collect.register(hooks.double); - - { - const result = try collect.invoke(std.testing.allocator, .{4}); - defer std.testing.allocator.free(result); - try std.testing.expectEqualSlices(usize, &.{8}, result); - } - - try collect.register(hooks.square); - - { - const result = try collect.invoke(std.testing.allocator, .{5}); - defer std.testing.allocator.free(result); - try std.testing.expectEqualSlices(usize, &.{ 10, 25 }, result); - } - - collect.unregister(hooks.double); - - { - const result = try collect.invoke(std.testing.allocator, .{6}); - defer std.testing.allocator.free(result); - try std.testing.expectEqualSlices(usize, &.{36}, result); - } - - collect.unregister(hooks.square); - - { - const result = try collect.invoke(std.testing.allocator, .{7}); - defer std.testing.allocator.free(result); - try std.testing.expectEqualSlices(usize, &.{}, result); - } -} - -test "error_hooks" { - const CollectError = error{Fail}; - const Collect = Hook(fn (usize) CollectError!usize); - var collect = Collect.init(std.testing.allocator); - defer collect.deinit(); - - const hooks = struct { - pub fn halve(f: usize) !usize { - if (f % 2 == 0) return f / 2; - return CollectError.Fail; - } - - pub fn third(f: usize) !usize { - if (f % 3 == 0) return f / 3; - return CollectError.Fail; - } - }; - - try collect.register(hooks.halve); - try collect.register(hooks.third); - - const result = try collect.invoke(std.testing.allocator, .{4}); - defer std.testing.allocator.free(result); - try std.testing.expectEqual(2, try result[0]); - try std.testing.expectError(CollectError.Fail, result[1]); -}