// --- LIBS --- const std = @import("std"); const System = @import("system.zig"); const Context = @import("context.zig"); const TypeID = @import("../template/type_id.zig").of; const Self = @This(); // // FIELDS // data: std.ArrayList(System), alloc: std.mem.Allocator, /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn init(alloc: std.mem.Allocator) Self { return .{ .data = .empty, .alloc = alloc, }; } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn deinit(self: *Self) void { self.data.deinit(self.alloc); } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn add( self: *Self, comptime T: type, execute: *const fn (Context) anyerror!void, ) !void { // --- GET ID --- const stage_id = TypeID(T); // --- NEW SYSTEM --- try self.data.append(self.alloc, .{ .stage_id = stage_id, .execute = execute, }); errdefer _ = self.data.swapRemove(self.data.items.len - 1); } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn addMany( self: *Self, comptime T: type, values: []const *const fn (Context) anyerror!void, ) !void { for (values) |exe| { try self.add(T, exe); } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn addBefore( self: *Self, comptime Stage: type, comptime Before: type, execute: *const fn (Context) anyerror!void, ) !void { const stage_id = TypeID(Stage); const insert_idx = self.firstStageIndex(TypeID(Before)); try self.data.insert(self.alloc, insert_idx, .{ .stage_id = stage_id, .execute = execute, }); errdefer _ = self.data.swapRemove(insert_idx); } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn addManyBefore( self: *Self, comptime Stage: type, comptime Before: type, values: []const *const fn (Context) anyerror!void, ) !void { const stage_id = TypeID(Stage); var insert_idx = self.firstStageIndex(TypeID(Before)); for (values) |exe| { try self.data.insert(self.alloc, insert_idx, .{ .stage_id = stage_id, .execute = exe, }); insert_idx += 1; } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn addAfter( self: *Self, comptime Stage: type, comptime After: type, execute: *const fn (Context) anyerror!void, ) !void { const stage_id = TypeID(Stage); const insert_idx = self.lastStageIndex(TypeID(After)); try self.data.insert(self.alloc, insert_idx, .{ .stage_id = stage_id, .execute = execute, }); errdefer _ = self.data.swapRemove(insert_idx); } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn addManyAfter( self: *Self, comptime Stage: type, comptime After: type, values: []const *const fn (Context) anyerror!void, ) !void { const stage_id = TypeID(Stage); var insert_idx = self.lastStageIndex(TypeID(After)); for (values) |exe| { try self.data.insert(self.alloc, insert_idx, .{ .stage_id = stage_id, .execute = exe, }); insert_idx += 1; } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn runAll( self: *Self, ctx: Context, ) !void { for (self.data.items) |sys| { try sys.execute(ctx); } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn run( self: *Self, comptime T: type, ctx: Context, ) !void { // --- GET ID --- const stage_id = TypeID(T); // --- RUN --- for (self.data.items) |sys| { if (sys.stage_id != stage_id) continue; try sys.execute(ctx); } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn runMany( self: *Self, comptime Ts: []const type, ctx: Context, ) !void { inline for (Ts) |T| { try self.run(T, ctx); } } /// ---------------------------------------------------- /// ---------------------------------------------------- fn firstStageIndex(self: *Self, stage_id: u64) usize { for (self.data.items, 0..) |sys, i| { if (sys.stage_id == stage_id) return i; } return self.data.items.len; } /// ---------------------------------------------------- /// ---------------------------------------------------- fn lastStageIndex(self: *Self, stage_id: u64) usize { var last: usize = self.data.items.len; for (self.data.items, 0..) |sys, i| { if (sys.stage_id == stage_id) last = i + 1; } return last; }