clean up hook implementation
This commit is contained in:
102
src/nu/hooks.zig
102
src/nu/hooks.zig
@@ -4,51 +4,74 @@ pub fn Hook(ftype: type) type {
|
||||
const F: std.builtin.Type.Fn = @typeInfo(ftype).Fn;
|
||||
const Result: type = F.return_type.?;
|
||||
|
||||
return struct {
|
||||
const Self = @This();
|
||||
return switch (@typeInfo(Result)) {
|
||||
.Void => 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 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_alloc_results(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);
|
||||
pub fn init(alloc: std.mem.Allocator) Self {
|
||||
return Self{
|
||||
.handlers = std.AutoArrayHashMap(*const ftype, void).init(alloc),
|
||||
};
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
fn invoke_void(self: Self, args: anytype) void {
|
||||
for (self.handlers.keys()) |handler| {
|
||||
@call(.auto, handler, args);
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.handlers.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
pub const invoke = switch (@typeInfo(Result)) {
|
||||
.Void => invoke_void,
|
||||
else => invoke_alloc_results,
|
||||
};
|
||||
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, 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());
|
||||
for (self.handlers.keys(), results) |handler, *result| {
|
||||
result.* = @call(.auto, handler, args);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test "void hooks" {
|
||||
var set_flags = Hook(fn (*usize) void).init(std.testing.allocator);
|
||||
defer set_flags.deinit();
|
||||
|
||||
const hooks = struct {
|
||||
pub fn set_one(f: *usize) void {
|
||||
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;
|
||||
|
||||
flag = 0;
|
||||
@@ -94,6 +114,9 @@ test "void hooks" {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -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});
|
||||
defer std.testing.allocator.free(result);
|
||||
|
Reference in New Issue
Block a user