Changes
4 changed files (+28/-142)
-
-
@@ -19,7 +19,7 @@ pub const Error = errors.CommandLineError ||std.Io.Reader.LimitedAllocError || events.Envelope.AppendError || events.Manifest.SaveError || timer.AggregateError || timer.TimerIterator.Error || std.mem.Allocator.Error || error{TimerNotFound};
-
-
-
@@ -98,27 +98,34 @@ pub fn run(args: *std.process.Args.Iterator, gpa: std.mem.Allocator, io: std.Io,defer manifest.deinit(gpa); var iter = try events.Iterator.init(io, &manifest); if (filter == .running) { const result = try timer.aggregate(timer.Aggregation.RunningOnly, gpa, io, &iter); defer result.deinit(gpa); for (result.running) |t| { timer.Timer.print(&.{ .running = t }, &writer.interface, print_opts) catch return Error.WriteToStdoutFailed; } } else { const result = try timer.aggregate(timer.Aggregation.Full, gpa, io, &iter); defer result.deinit(gpa); if (filter == null) { for (result.running) |t| { timer.Timer.print(&.{ .running = t }, &writer.interface, print_opts) catch return Error.WriteToStdoutFailed; } var timer_iter: timer.TimerIterator = .{ .events_iter = &iter }; defer timer_iter.deinit(gpa); var timers: std.ArrayList(timer.Timer) = .empty; defer timers.deinit(gpa); defer for (timers.items) |t| { t.deinit(gpa); }; while (try timer_iter.next(gpa, io)) |t| { switch (t) { .running => { if (filter != .stopped) { try timers.append(gpa, t); } }, .stopped => { if (filter != .running) { try timers.append(gpa, t); } }, } } for (result.stopped) |t| { timer.Timer.print(&.{ .stopped = t }, &writer.interface, print_opts) catch return Error.WriteToStdoutFailed; } var i: usize = timers.items.len; while (i > 0) { i -= 1; timers.items[i].print(&writer.interface, print_opts) catch return Error.WriteToStdoutFailed; } writer.flush() catch return Error.WriteToStdoutFailed;
-
-
-
@@ -19,7 +19,7 @@ pub const Error = errors.CommandLineError ||std.Io.Reader.LimitedAllocError || events.Envelope.AppendError || events.Manifest.SaveError || timer.AggregateError || timer.TimerIterator.Error || std.mem.Allocator.Error || error{TimerNotFound};
-
-
-
@@ -493,127 +493,6 @@ test {_ = Timer; } pub const Aggregation = struct { pub const RunningOnly = struct { running: []RunningTimer, pub fn deinit(self: RunningOnly, allocator: std.mem.Allocator) void { for (self.running) |t| t.deinit(allocator); allocator.free(self.running); } }; pub const Full = struct { running: []RunningTimer, stopped: []StoppedTimer, pub fn deinit(self: Full, allocator: std.mem.Allocator) void { for (self.running) |t| t.deinit(allocator); allocator.free(self.running); for (self.stopped) |t| t.deinit(allocator); allocator.free(self.stopped); } }; }; pub const AggregateError = std.mem.Allocator.Error || events.Iterator.IterateError; /// Caller is responsible for calling `deinit` on the returned struct after use. pub fn aggregate(Type: type, gpa: std.mem.Allocator, io: std.Io, iterator: *events.Iterator) AggregateError!Type { if (Type != Aggregation.RunningOnly and Type != Aggregation.Full) { @compileError("Type parameter of \"aggregate\" must be either one of \"State.RunningOnly\" or \"State.Full\""); } var event_list = std.ArrayList(events.Event).empty; defer event_list.deinit(gpa); defer for (event_list.items) |event| event.deinit(gpa); while (try iterator.next(gpa, io)) |event| { try event_list.append(gpa, event); } var running_timers = std.array_hash_map.Auto(uuid.Uuid, RunningTimer).empty; defer running_timers.deinit(gpa); errdefer for (running_timers.values()) |timer| timer.deinit(gpa); var stopped_timers = if (Type == Aggregation.Full) std.array_hash_map.Auto(uuid.Uuid, StoppedTimer).empty else std.array_hash_map.Auto(void, void).empty; defer if (Type == Aggregation.Full) stopped_timers.deinit(gpa); errdefer if (Type == Aggregation.Full) for (stopped_timers.values()) |timer| timer.deinit(gpa); for (0..event_list.items.len) |i| { const event = event_list.items[event_list.items.len - i - 1]; switch (event) { .timer_started => |started| { try running_timers.put(gpa, started.timer_id, .{ .id = started.timer_id, .title = try gpa.dupe(u8, started.title), .started_at = started.created_at, }); }, .timer_stopped => |stopped| { const found = running_timers.fetchOrderedRemove(stopped.timer_id) orelse { std.log.warn("Detected stopping non-existing timer ID ({s}), skipping", .{uuid.urn.serialize(stopped.timer_id)}); continue; }; if (Type == Aggregation.Full) { try stopped_timers.put(gpa, stopped.timer_id, .{ .id = found.value.id, .title = found.value.title, .started_at = found.value.started_at, .stopped_at = stopped.created_at, }); } else { found.value.deinit(gpa); } }, .timer_deleted => |deleted| { if (running_timers.fetchOrderedRemove(deleted.timer_id)) |timer| { timer.value.deinit(gpa); } if (Type == Aggregation.Full) { if (stopped_timers.fetchOrderedRemove(deleted.timer_id)) |timer| { timer.value.deinit(gpa); } } }, .timer_title_changed => |title_changed| { if (running_timers.getPtr(title_changed.timer_id)) |timer| { gpa.free(timer.title); timer.title = try gpa.dupe(u8, title_changed.new_title); } if (Type == Aggregation.Full) { if (stopped_timers.getPtr(title_changed.timer_id)) |timer| { gpa.free(timer.title); timer.title = try gpa.dupe(u8, title_changed.new_title); } } }, } } if (Type == Aggregation.RunningOnly) { return .{ .running = try gpa.dupe(RunningTimer, running_timers.values()), }; } else { const running = try gpa.dupe(RunningTimer, running_timers.values()); errdefer gpa.free(running); const stopped = try gpa.dupe(StoppedTimer, stopped_timers.values()); errdefer gpa.free(stopped); return .{ .running = running, .stopped = stopped, }; } } pub const FindError = std.mem.Allocator.Error || events.Iterator.IterateError; /// Caller is responsible for calling `deinit` on the returned struct after use.
-