only support void hooks
This commit is contained in:
118
src/nu/hooks.zig
118
src/nu/hooks.zig
@@ -2,10 +2,10 @@ const std = @import("std");
|
|||||||
|
|
||||||
pub fn Hook(ftype: type) type {
|
pub fn Hook(ftype: type) type {
|
||||||
const F: std.builtin.Type.Fn = @typeInfo(ftype).Fn;
|
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)) {
|
return struct {
|
||||||
.Void => struct {
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
handlers: std.AutoArrayHashMap(*const ftype, void),
|
handlers: std.AutoArrayHashMap(*const ftype, void),
|
||||||
@@ -33,38 +33,6 @@ pub fn Hook(ftype: type) type {
|
|||||||
@call(.auto, handler, args);
|
@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});
|
set_flags.invoke(.{&flag});
|
||||||
try std.testing.expect(flag == 0b00);
|
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]);
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user