refactor: use explicit error sets in MessageFilter and project_manager

This commit is contained in:
CJ van den Berg 2024-09-19 21:54:18 +02:00
parent 6fac0b1cb4
commit 0542fdc680
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
12 changed files with 396 additions and 341 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const cbor = @import("cbor");
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const Self = @This();
@ -8,9 +9,16 @@ const MessageFilter = Self;
ptr: *anyopaque,
vtable: *const VTable,
pub const Error = (cbor.Error || cbor.JsonEncodeError || error{
OutOfMemory,
ThespianSpawnFailed,
NoProject,
SendFailed,
});
pub const VTable = struct {
deinit: *const fn (ctx: *anyopaque) void,
filter: *const fn (ctx: *anyopaque, from: tp.pid_ref, m: tp.message) error{Exit}!bool,
filter: *const fn (ctx: *anyopaque, from: tp.pid_ref, m: tp.message) Error!bool,
type_name: []const u8,
};
@ -27,7 +35,7 @@ pub fn to_owned(pimpl: anytype) Self {
}
}.deinit,
.filter = struct {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) Error!bool {
return child.filter(@as(*child, @ptrCast(@alignCast(ctx))), from_, m);
}
}.filter,
@ -46,7 +54,7 @@ pub fn to_unowned(pimpl: anytype) Self {
pub fn deinit(_: *anyopaque) void {}
}.deinit,
.filter = struct {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) Error!bool {
return child.filter(@as(*child, @ptrCast(@alignCast(ctx))), from_, m);
}
}.filter,
@ -54,7 +62,7 @@ pub fn to_unowned(pimpl: anytype) Self {
};
}
pub fn bind(pimpl: anytype, comptime f: *const fn (ctx: @TypeOf(pimpl), from: tp.pid_ref, m: tp.message) error{Exit}!bool) Self {
pub fn bind(pimpl: anytype, comptime f: *const fn (ctx: @TypeOf(pimpl), from: tp.pid_ref, m: tp.message) Error!bool) Self {
const impl = @typeInfo(@TypeOf(pimpl));
const child: type = impl.Pointer.child;
return .{
@ -65,7 +73,7 @@ pub fn bind(pimpl: anytype, comptime f: *const fn (ctx: @TypeOf(pimpl), from: tp
pub fn deinit(_: *anyopaque) void {}
}.deinit,
.filter = struct {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter(ctx: *anyopaque, from_: tp.pid_ref, m: tp.message) Error!bool {
return @call(.auto, f, .{ @as(*child, @ptrCast(@alignCast(ctx))), from_, m });
}
}.filter,
@ -84,7 +92,7 @@ pub fn dynamic_cast(self: Self, comptime T: type) ?*T {
null;
}
pub fn filter(self: Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter(self: Self, from_: tp.pid_ref, m: tp.message) Error!bool {
return self.vtable.filter(self.ptr, from_, m);
}
@ -120,14 +128,14 @@ pub const List = struct {
self.list.orderedRemove(i).deinit();
}
pub fn filter(self: *const List, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter(self: *const List, from: tp.pid_ref, m: tp.message) Error!bool {
var sfa = std.heap.stackFallback(4096, self.allocator);
const a = sfa.get();
const buf = a.alloc(u8, m.buf.len) catch |e| return tp.exit_error(e, @errorReturnTrace());
const buf = try a.alloc(u8, m.buf.len);
defer a.free(buf);
@memcpy(buf[0..m.buf.len], m.buf);
const m_: tp.message = .{ .buf = buf[0..m.buf.len] };
var e: ?error{Exit} = null;
var e: ?Error = null;
for (self.list.items) |*i| {
const consume = i.filter(from, m_) catch |e_| ret: {
e = e_;

View file

@ -333,7 +333,7 @@ fn diff_result_send(from: tp.pid_ref, edits: []diff.Edit) !void {
from.send_raw(tp.message{ .buf = stream.getWritten() }) catch return;
}
pub fn process_diff(self: *Self, cb: []const u8) !void {
pub fn process_diff(self: *Self, cb: []const u8) MessageFilter.Error!void {
var iter = cb;
self.diff_symbols_clear();
var count = try cbor.decodeArrayHeader(&iter);
@ -382,10 +382,10 @@ fn process_edit(self: *Self, kind: Kind, line: usize, offset: usize, bytes: []co
};
}
pub fn filter_receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn filter_receive(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
var cb: []const u8 = undefined;
if (try m.match(.{ "DIFF", tp.extract_cbor(&cb) })) {
self.process_diff(cb) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (cbor.match(m.buf, .{ "DIFF", tp.extract_cbor(&cb) }) catch false) {
try self.process_diff(cb);
return true;
}
return false;

View file

@ -5,10 +5,12 @@ const Allocator = @import("std").mem.Allocator;
const ArrayList = @import("std").ArrayList;
const tp = @import("thespian");
const cbor = @import("cbor");
const Plane = @import("renderer").Plane;
const Widget = @import("Widget.zig");
const MessageFilter = @import("MessageFilter.zig");
const escape = fmt.fmtSliceEscapeLower;
@ -82,21 +84,21 @@ fn output_tdiff(self: *Self, tdiff: i64) !void {
}
}
pub fn process_log(m: tp.message) !void {
pub fn process_log(m: tp.message) MessageFilter.Error!void {
var src: []const u8 = undefined;
var context: []const u8 = undefined;
var msg: []const u8 = undefined;
const buffer = get_buffer();
if (try m.match(.{ "log", tp.extract(&src), tp.extract(&msg) })) {
if (try cbor.match(m.buf, .{ "log", tp.extract(&src), tp.extract(&msg) })) {
try append(buffer, src, msg, .info);
} else if (try m.match(.{ "log", "error", tp.extract(&src), tp.extract(&context), "->", tp.extract(&msg) })) {
} else if (try cbor.match(m.buf, .{ "log", "error", tp.extract(&src), tp.extract(&context), "->", tp.extract(&msg) })) {
const err_stop = "error.Stop";
if (eql(u8, msg, err_stop))
return;
if (msg.len >= err_stop.len + 1 and eql(u8, msg[0 .. err_stop.len + 1], err_stop ++ "\n"))
return;
try append_error(buffer, src, context, msg);
} else if (try m.match(.{ "log", tp.extract(&src), tp.more })) {
} else if (try cbor.match(m.buf, .{ "log", tp.extract(&src), tp.more })) {
try append_json(buffer, src, m);
}
}
@ -120,16 +122,23 @@ fn append(buffer: *Buffer, src: []const u8, msg: []const u8, level: Level) !void
};
}
fn append_error(buffer: *Buffer, src: []const u8, context: []const u8, msg_: []const u8) !void {
var buf: [4096]u8 = undefined;
const msg = try fmt.bufPrint(&buf, "error in {s}: {s}", .{ context, msg_ });
try append(buffer, src, msg, .err);
fn append_error(buffer: *Buffer, src: []const u8, context: []const u8, msg_: []const u8) MessageFilter.Error!void {
const std = @import("std");
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var sfa = std.heap.stackFallback(4096, arena.allocator());
var msg = std.ArrayList(u8).init(sfa.get());
try fmt.format(msg.writer(), "error in {s}: {s}", .{ context, msg_ });
try append(buffer, src, msg.items, .err);
}
fn append_json(buffer: *Buffer, src: []const u8, m: tp.message) !void {
var buf: [4096]u8 = undefined;
const json = try m.to_json(&buf);
try append(buffer, src, json, .err);
fn append_json(buffer: *Buffer, src: []const u8, m: tp.message) MessageFilter.Error!void {
const std = @import("std");
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var sfa = std.heap.stackFallback(4096, arena.allocator());
const msg = try cbor.toJsonAlloc(sfa.get(), m.buf);
try append(buffer, src, msg, .err);
}
fn get_buffer() *Buffer {

View file

@ -1,5 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const cbor = @import("cbor");
const log = @import("log");
const root = @import("root");
@ -216,15 +217,15 @@ pub fn Create(options: type) type {
try self.do_complete();
}
fn receive_path_entry(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "PRJ", tp.more })) {
self.process_project_manager(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
fn receive_path_entry(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
if (try cbor.match(m.buf, .{ "PRJ", tp.more })) {
try self.process_project_manager(m);
return true;
}
return false;
}
fn process_project_manager(self: *Self, m: tp.message) !void {
fn process_project_manager(self: *Self, m: tp.message) MessageFilter.Error!void {
defer {
if (tui.current().mini_mode) |*mini_mode| {
mini_mode.text = self.file_path.items;
@ -232,23 +233,23 @@ pub fn Create(options: type) type {
}
}
var count: usize = undefined;
if (try m.match(.{ "PRJ", "path_entry", tp.more })) {
if (try cbor.match(m.buf, .{ "PRJ", "path_entry", tp.more })) {
return self.process_path_entry(m);
} else if (try m.match(.{ "PRJ", "path_done", tp.any, tp.any, tp.extract(&count) })) {
} else if (try cbor.match(m.buf, .{ "PRJ", "path_done", tp.any, tp.any, tp.extract(&count) })) {
try self.do_complete();
} else {
log.logger("file_browser").err("receive", tp.unexpected(m));
}
}
fn process_path_entry(self: *Self, m: tp.message) !void {
fn process_path_entry(self: *Self, m: tp.message) MessageFilter.Error!void {
var path: []const u8 = undefined;
var file_name: []const u8 = undefined;
if (try m.match(.{ tp.any, tp.any, tp.any, tp.extract(&path), "DIR", tp.extract(&file_name) })) {
if (try cbor.match(m.buf, .{ tp.any, tp.any, tp.any, tp.extract(&path), "DIR", tp.extract(&file_name) })) {
(try self.entries.addOne()).* = .{ .name = try self.allocator.dupe(u8, file_name), .type = .dir };
} else if (try m.match(.{ tp.any, tp.any, tp.any, tp.extract(&path), "LINK", tp.extract(&file_name) })) {
} else if (try cbor.match(m.buf, .{ tp.any, tp.any, tp.any, tp.extract(&path), "LINK", tp.extract(&file_name) })) {
(try self.entries.addOne()).* = .{ .name = try self.allocator.dupe(u8, file_name), .type = .link };
} else if (try m.match(.{ tp.any, tp.any, tp.any, tp.extract(&path), "FILE", tp.extract(&file_name) })) {
} else if (try cbor.match(m.buf, .{ tp.any, tp.any, tp.any, tp.extract(&path), "FILE", tp.extract(&file_name) })) {
(try self.entries.addOne()).* = .{ .name = try self.allocator.dupe(u8, file_name), .type = .file };
} else {
log.logger("file_browser").err("receive", tp.unexpected(m));

View file

@ -118,7 +118,7 @@ pub fn restore_state(palette: *Type) !void {
tp.extract(&name_),
tp.extract(&used_time),
}) catch |e| switch (e) {
error.CborTooShort => return,
error.TooShort => return,
else => return e,
}) {
const id = command.getId(name_) orelse continue;

View file

@ -148,19 +148,19 @@ fn add_item(self: *Self, file_name: []const u8, matches: ?[]const u8) !void {
try self.menu.add_item_with_handler(label.items, menu_action_open_file);
}
fn receive_project_manager(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "PRJ", tp.more })) {
self.process_project_manager(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
fn receive_project_manager(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
if (cbor.match(m.buf, .{ "PRJ", tp.more }) catch false) {
try self.process_project_manager(m);
return true;
}
return false;
}
fn process_project_manager(self: *Self, m: tp.message) !void {
fn process_project_manager(self: *Self, m: tp.message) MessageFilter.Error!void {
var file_name: []const u8 = undefined;
var matches: []const u8 = undefined;
var query: []const u8 = undefined;
if (try m.match(.{ "PRJ", "recent", tp.extract(&self.longest), tp.extract(&file_name), tp.extract_cbor(&matches) })) {
if (try cbor.match(m.buf, .{ "PRJ", "recent", tp.extract(&self.longest), tp.extract(&file_name), tp.extract_cbor(&matches) })) {
if (self.need_reset) self.reset_results();
try self.add_item(file_name, matches);
self.menu.resize(.{ .y = 0, .x = self.menu_pos_x(), .w = self.menu_width() });
@ -169,7 +169,7 @@ fn process_project_manager(self: *Self, m: tp.message) !void {
self.need_select_first = false;
}
tui.need_render();
} else if (try m.match(.{ "PRJ", "recent", tp.extract(&self.longest), tp.extract(&file_name) })) {
} else if (try cbor.match(m.buf, .{ "PRJ", "recent", tp.extract(&self.longest), tp.extract(&file_name) })) {
if (self.need_reset) self.reset_results();
try self.add_item(file_name, null);
self.menu.resize(.{ .y = 0, .x = self.menu_pos_x(), .w = self.menu_width() });
@ -178,7 +178,7 @@ fn process_project_manager(self: *Self, m: tp.message) !void {
self.need_select_first = false;
}
tui.need_render();
} else if (try m.match(.{ "PRJ", "recent_done", tp.extract(&self.longest), tp.extract(&query) })) {
} else if (try cbor.match(m.buf, .{ "PRJ", "recent_done", tp.extract(&self.longest), tp.extract(&query) })) {
self.query_pending = false;
self.need_reset = true;
if (!std.mem.eql(u8, self.inputbox.text.items, query))
@ -283,7 +283,7 @@ fn reset_results(self: *Self) void {
self.need_select_first = true;
}
fn start_query(self: *Self) !void {
fn start_query(self: *Self) MessageFilter.Error!void {
if (self.query_pending) return;
self.query_pending = true;
try project_manager.query_recent_files(max_recent_files, self.inputbox.text.items);

View file

@ -1,5 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const cbor = @import("cbor");
const zeit = @import("zeit");
const Plane = @import("renderer").Plane;
@ -67,8 +68,8 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
return false;
}
fn receive_tick(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{"CLOCK"})) {
fn receive_tick(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
if (try cbor.match(m.buf, .{"CLOCK"})) {
tui.need_render();
self.update_tick_timer(.ticked);
return true;

View file

@ -1,5 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const cbor = @import("cbor");
const log = @import("log");
const Plane = @import("renderer").Plane;
@ -76,13 +77,13 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
return false;
}
fn receive_log(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
fn receive_log(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
var clear_msg_num: usize = 0;
if (try m.match(.{ "log", tp.more })) {
logview.process_log(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
self.process_log(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try cbor.match(m.buf, .{ "log", tp.more })) {
try logview.process_log(m);
try self.process_log(m);
return true;
} else if (try m.match(.{ "MINILOG", tp.extract(&clear_msg_num) })) {
} else if (try cbor.match(m.buf, .{ "MINILOG", tp.extract(&clear_msg_num) })) {
if (clear_msg_num == self.msg_counter)
self.clear();
return true;
@ -90,20 +91,20 @@ fn receive_log(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
return false;
}
fn process_log(self: *Self, m: tp.message) !void {
fn process_log(self: *Self, m: tp.message) MessageFilter.Error!void {
var src: []const u8 = undefined;
var context: []const u8 = undefined;
var msg: []const u8 = undefined;
if (try m.match(.{ "log", tp.extract(&src), tp.extract(&msg) })) {
if (try cbor.match(m.buf, .{ "log", tp.extract(&src), tp.extract(&msg) })) {
try self.set(msg, .info);
} else if (try m.match(.{ "log", "error", tp.extract(&src), tp.extract(&context), "->", tp.extract(&msg) })) {
} else if (try cbor.match(m.buf, .{ "log", "error", tp.extract(&src), tp.extract(&context), "->", tp.extract(&msg) })) {
const err_stop = "error.Stop";
if (std.mem.eql(u8, msg, err_stop))
return;
if (msg.len >= err_stop.len + 1 and std.mem.eql(u8, msg[0 .. err_stop.len + 1], err_stop ++ "\n"))
return;
try self.set(msg, .err);
} else if (try m.match(.{ "log", tp.extract(&src), tp.more })) {
} else if (try cbor.match(m.buf, .{ "log", tp.extract(&src), tp.more })) {
self.level = .err;
var s = std.json.writeStream(self.msg.writer(), .{});
var iter: []const u8 = m.buf;