From 917ca5ffdc476123c28e610b1b8b3868cedd45a6 Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 7 Jun 2020 17:28:49 -0700 Subject: [PATCH] allow inserts --- zig-ecs/src/signals/signal.zig | 16 +++++-- zig-ecs/src/signals/sink.zig | 88 ++++++++++++++++++++++++++++++---- 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/zig-ecs/src/signals/signal.zig b/zig-ecs/src/signals/signal.zig index c14bf8b..98e2368 100644 --- a/zig-ecs/src/signals/signal.zig +++ b/zig-ecs/src/signals/signal.zig @@ -77,9 +77,6 @@ test "Signal/Sink" { sink.connect(tester); std.testing.expectEqual(@as(usize, 1), signal.size()); - sink.connect(tester); - std.testing.expectEqual(@as(usize, 1), signal.size()); - // bound listener var thing = Thing{}; sink.connectBound(&thing, "tester"); @@ -93,3 +90,16 @@ test "Signal/Sink" { sink.disconnectBound(&thing); std.testing.expectEqual(@as(usize, 0), signal.size()); } + +test "Sink Before null" { + var signal = Signal(u32).init(std.testing.allocator); + defer signal.deinit(); + + var sink = signal.sink(); + sink.connect(tester); + std.testing.expectEqual(@as(usize, 1), signal.size()); + + var thing = Thing{}; + sink.before(null).connectBound(&thing, "tester"); + std.testing.expectEqual(@as(usize, 2), signal.size()); +} diff --git a/zig-ecs/src/signals/sink.zig b/zig-ecs/src/signals/sink.zig index d915ab9..b4a6986 100644 --- a/zig-ecs/src/signals/sink.zig +++ b/zig-ecs/src/signals/sink.zig @@ -8,40 +8,108 @@ pub fn Sink(comptime Event: type) type { return struct { const Self = @This(); + insert_index: usize, + /// the Signal this Sink is temporarily wrapping var owning_signal: *Signal(Event) = undefined; pub fn init(signal: *Signal(Event)) Self { owning_signal = signal; - return Self{}; + return Self{ .insert_index = owning_signal.calls.items.len }; + } + + pub fn before(self: Self, callback: ?fn (Event) void) Self { + if (callback) |cb| { + if (self.indexOf(cb)) |index| { + return Self{ .insert_index = index }; + } + } + return self; + } + + pub fn beforeBound(self: Self, ctx: var) Self { + if (@typeInfo(@TypeOf(ctx)) == .Pointer) { + if (self.indexOfBound(ctx)) |index| { + return Self{ .insert_index = index }; + } + } + return self; } pub fn connect(self: Self, callback: fn (Event) void) void { - self.disconnect(callback); - _ = owning_signal.calls.append(Delegate(Event).initFree(callback)) catch unreachable; + std.debug.assert(self.indexOf(callback) == null); + _ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initFree(callback)) catch unreachable; } pub fn connectBound(self: Self, ctx: var, comptime fn_name: []const u8) void { - self.disconnectBound(ctx); - _ = owning_signal.calls.append(Delegate(Event).initBound(ctx, fn_name)) catch unreachable; + std.debug.assert(self.indexOfBound(ctx) == null); + _ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initBound(ctx, fn_name)) catch unreachable; } pub fn disconnect(self: Self, callback: fn (Event) void) void { + if (self.indexOf(callback)) |index| { + _ = owning_signal.calls.swapRemove(index); + } + } + + pub fn disconnectBound(self: Self, ctx: var) void { + if (self.indexOfBound(ctx)) |index| { + _ = owning_signal.calls.swapRemove(index); + } + } + + fn indexOf(self: Self, callback: fn (Event) void) ?usize { for (owning_signal.calls.items) |call, i| { if (call.containsFree(callback)) { - _ = owning_signal.calls.swapRemove(i); - break; + return i; } } + return null; } - pub fn disconnectBound(self: Self, ctx: var) void { + fn indexOfBound(self: Self, ctx: var) ?usize { for (owning_signal.calls.items) |call, i| { if (call.containsBound(ctx)) { - _ = owning_signal.calls.swapRemove(i); - break; + return i; } } + return null; } }; } + +fn tester(param: u32) void { + std.testing.expectEqual(@as(u32, 666), param); +} + +const Thing = struct { + field: f32 = 0, + + pub fn tester(self: *Thing, param: u32) void { + std.testing.expectEqual(@as(u32, 666), param); + } +}; + +test "Sink Before free" { + var signal = Signal(u32).init(std.testing.allocator); + defer signal.deinit(); + + signal.sink().connect(tester); + std.testing.expectEqual(signal.sink().indexOf(tester).?, 0); + + var thing = Thing{}; + signal.sink().before(tester).connectBound(&thing, "tester"); + std.testing.expectEqual(signal.sink().indexOfBound(&thing).?, 0); +} + +test "Sink Before bound" { + var signal = Signal(u32).init(std.testing.allocator); + defer signal.deinit(); + + var thing = Thing{}; + signal.sink().connectBound(&thing, "tester"); + std.testing.expectEqual(signal.sink().indexOfBound(&thing).?, 0); + + signal.sink().beforeBound(&thing).connect(tester); + std.testing.expectEqual(signal.sink().indexOf(tester).?, 0); +} \ No newline at end of file