clean up hook implementation
This commit is contained in:
@@ -4,7 +4,8 @@ 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 Result: type = F.return_type.?;
|
||||||
|
|
||||||
return struct {
|
return switch (@typeInfo(Result)) {
|
||||||
|
.Void => struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
handlers: std.AutoArrayHashMap(*const ftype, void),
|
handlers: std.AutoArrayHashMap(*const ftype, void),
|
||||||
@@ -27,28 +28,50 @@ pub fn Hook(ftype: type) type {
|
|||||||
_ = self.handlers.orderedRemove(f);
|
_ = self.handlers.orderedRemove(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke_alloc_results(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result {
|
||||||
const results = try alloc.alloc(Result, self.handlers.count());
|
const results = try alloc.alloc(Result, self.handlers.count());
|
||||||
for (self.handlers.keys(), results) |handler, *result| {
|
for (self.handlers.keys(), results) |handler, *result| {
|
||||||
result.* = @call(.auto, handler, args);
|
result.* = @call(.auto, handler, args);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
fn invoke_void(self: Self, args: anytype) void {
|
|
||||||
for (self.handlers.keys()) |handler| {
|
|
||||||
@call(.auto, handler, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const invoke = switch (@typeInfo(Result)) {
|
|
||||||
.Void => invoke_void,
|
|
||||||
else => invoke_alloc_results,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test "void hooks" {
|
test "void hooks" {
|
||||||
|
var set_flags = Hook(fn (*usize) void).init(std.testing.allocator);
|
||||||
|
defer set_flags.deinit();
|
||||||
|
|
||||||
const hooks = struct {
|
const hooks = struct {
|
||||||
pub fn set_one(f: *usize) void {
|
pub fn set_one(f: *usize) void {
|
||||||
f.* |= 0b01;
|
f.* |= 0b01;
|
||||||
@@ -59,9 +82,6 @@ test "void hooks" {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var set_flags = Hook(fn (*usize) void).init(std.testing.allocator);
|
|
||||||
defer set_flags.deinit();
|
|
||||||
|
|
||||||
var flag: usize = undefined;
|
var flag: usize = undefined;
|
||||||
|
|
||||||
flag = 0;
|
flag = 0;
|
||||||
@@ -94,6 +114,9 @@ test "void hooks" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "collect hooks" {
|
test "collect hooks" {
|
||||||
|
var collect = Hook(fn (usize) usize).init(std.testing.allocator);
|
||||||
|
defer collect.deinit();
|
||||||
|
|
||||||
const hooks = struct {
|
const hooks = struct {
|
||||||
pub fn double(f: usize) usize {
|
pub fn double(f: usize) usize {
|
||||||
return f * 2;
|
return f * 2;
|
||||||
@@ -104,9 +127,6 @@ test "collect hooks" {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var collect = Hook(fn (usize) usize).init(std.testing.allocator);
|
|
||||||
defer collect.deinit();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const result = try collect.invoke(std.testing.allocator, .{3});
|
const result = try collect.invoke(std.testing.allocator, .{3});
|
||||||
defer std.testing.allocator.free(result);
|
defer std.testing.allocator.free(result);
|
||||||
|
Reference in New Issue
Block a user