pub fn Observable(T: type) type { return struct { allocator: std.mem.Allocator, observers: std.ArrayList(*const Observer(T)), const Self = @This(); pub fn init(allocator: std.mem.Allocator) Self { return .{ .allocator = allocator, .observers = std.ArrayList(*const Observer(T)).init(allocator), }; } pub fn deinit(self: *Self) void { for(self.observers.items)|o| { self.allocator.destroy(o); } self.observers.deinit(); } pub fn attach(self: *Self, obs: *const Observer(T)) !void { try self.observers.append(obs); } pub fn detach(self: *Self, obs: *const Observer(T)) void { if (std.mem.indexOfScalar(*const Observer(T), self.observers.items, obs)) |index| { _ = self.observers.swapRemove(index); } } pub fn notify(self: Self, args: T) void { for (self.observers.items) |obs| { obs.update(obs.ctx, args); } } }; } pub fn Observer(T: type) type { return struct { ctx: *anyopaque, update: *const fn (ctx: *anyopaque, args: T) void, }; } const std = @import("std");