diff --git a/build.zig b/build.zig index 4c1fb66..52f1ec7 100644 --- a/build.zig +++ b/build.zig @@ -40,8 +40,8 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); if (tracy_enabled) { - lib.defineCMacro("TRACY_ENABLE", null); - lib.defineCMacro("TRACY_CALLSTACK", null); + lib.root_module.addCMacro("TRACY_ENABLE", "1"); + lib.root_module.addCMacro("TRACY_CALLSTACK", "1"); } lib.addIncludePath(b.path("src")); lib.addIncludePath(b.path("include")); diff --git a/build.zig.version b/build.zig.version index 54d1a4f..a803cc2 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.13.0 +0.14.0 diff --git a/build.zig.zon b/build.zig.zon index ef47a31..77e30ee 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,15 +1,16 @@ .{ - .name = "thespian", + .name = .thespian, .version = "0.0.1", + .fingerprint = 0xe9ff00fd8e4e01a3, .dependencies = .{ .asio = .{ - .url = "https://github.com/neurocyte/asio/archive/b9c9c23ef2e6f11b6123535ec33e5a23ed0c59da.tar.gz", - .hash = "1220c85e0d9438ec518849c84e3ea66633a0e191e49c4ae4bbb3bc46626cd8dfad75", + .url = "https://github.com/neurocyte/asio/archive/24d28864ec5aae6146d88a172288e3bf3f099734.tar.gz", + .hash = "asio-1.30.2-tLhDdyKA4QBqQFDrsuK_hO1HfqX-DQMl-Sku7yy4vUfM", }, .tracy = .{ - .url = "https://github.com/neurocyte/zig-tracy/archive/e04e31c64498149a324491b8534758e6af43a5c2.tar.gz", - .hash = "1220d0fb2bff7b453dbb39d1db3eb472b6680e2564f2b23b0e947671be47bbdd188f", + .url = "https://github.com/neurocyte/zig-tracy/archive/f2fe3021501c19816006ab65e3389b1c5f0c3c3a.tar.gz", + .hash = "zig_tracy-0.0.3-5-cp3Kp2AABlufxcWskNe6YfKeqCRpDu7b57JvE-Yj1w", }, }, .paths = .{ diff --git a/src/cbor.zig b/src/cbor.zig index c922a1d..2d791c8 100644 --- a/src/cbor.zig +++ b/src/cbor.zig @@ -209,12 +209,12 @@ fn writeErrorset(writer: anytype, err: anyerror) @TypeOf(writer).Error!void { pub fn writeValue(writer: anytype, value: anytype) @TypeOf(writer).Error!void { const T = @TypeOf(value); switch (@typeInfo(T)) { - .Int, .ComptimeInt => return if (T == u64) writeU64(writer, value) else writeI64(writer, @intCast(value)), - .Bool => return writeBool(writer, value), - .Optional => return if (value) |v| writeValue(writer, v) else writeNull(writer), - .ErrorUnion => return if (value) |v| writeValue(writer, v) else |err| writeValue(writer, err), - .ErrorSet => return writeErrorset(writer, value), - .Union => |info| { + .int, .comptime_int => return if (T == u64) writeU64(writer, value) else writeI64(writer, @intCast(value)), + .bool => return writeBool(writer, value), + .optional => return if (value) |v| writeValue(writer, v) else writeNull(writer), + .error_union => return if (value) |v| writeValue(writer, v) else |err| writeValue(writer, err), + .error_set => return writeErrorset(writer, value), + .@"union" => |info| { if (info.tag_type) |TagType| { comptime var v = void; inline for (info.fields) |u_field| { @@ -230,7 +230,7 @@ pub fn writeValue(writer: anytype, value: anytype) @TypeOf(writer).Error!void { try writeArray(writer, .{@typeName(T)}); } }, - .Struct => |info| { + .@"struct" => |info| { if (info.is_tuple) { if (info.fields.len == 0) return writeNull(writer); try writeArrayHeader(writer, info.fields.len); @@ -245,10 +245,10 @@ pub fn writeValue(writer: anytype, value: anytype) @TypeOf(writer).Error!void { } } }, - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => return writeValue(writer, value.*), - .Many, .C => @compileError("cannot write type '" ++ @typeName(T) ++ "' to cbor stream"), - .Slice => { + .pointer => |ptr_info| switch (ptr_info.size) { + .one => return writeValue(writer, value.*), + .many, .c => @compileError("cannot write type '" ++ @typeName(T) ++ "' to cbor stream"), + .slice => { if (ptr_info.child == u8) return writeString(writer, value); if (value.len == 0) return writeNull(writer); try writeArrayHeader(writer, value.len); @@ -256,22 +256,22 @@ pub fn writeValue(writer: anytype, value: anytype) @TypeOf(writer).Error!void { try writeValue(writer, elem); }, }, - .Array => |info| { + .array => |info| { if (info.child == u8) return writeString(writer, &value); if (value.len == 0) return writeNull(writer); try writeArrayHeader(writer, value.len); for (value) |elem| try writeValue(writer, elem); }, - .Vector => |info| { + .vector => |info| { try writeArrayHeader(writer, info.len); var i: usize = 0; while (i < info.len) : (i += 1) { try writeValue(writer, value[i]); } }, - .Null => try writeNull(writer), - .Float => |info| switch (info.bits) { + .null => try writeNull(writer), + .float => |info| switch (info.bits) { 16 => try writeF16(writer, value), 32 => try writeF32(writer, value), 64 => try writeF64(writer, value), @@ -380,7 +380,7 @@ fn decodeJsonObject(iter_: *[]const u8, minor: u5, obj: *json.ObjectMap) Error!b var iter = iter_.*; var n = try decodePInt(&iter, minor); while (n > 0) { - var key: []u8 = undefined; + var key: []const u8 = undefined; var value: json.Value = .null; if (!try matchString(&iter, &key)) @@ -522,6 +522,21 @@ fn matchFloatValue(comptime T: type, iter: *[]const u8, val: T) Error!bool { return if (try matchFloat(T, iter, &v)) v == val else false; } +pub fn matchEnum(comptime T: type, iter_: *[]const u8, val: *T) Error!bool { + var iter = iter_.*; + var str: []const u8 = undefined; + if (try matchString(&iter, &str)) if (std.meta.stringToEnum(T, str)) |val_| { + val.* = val_; + iter_.* = iter; + return true; + }; + return false; +} + +fn matchEnumValue(comptime T: type, iter: *[]const u8, val: T) Error!bool { + return matchStringValue(iter, @tagName(val)); +} + fn skipString(iter: *[]const u8, minor: u5) Error!void { const len: usize = @intCast(try decodePInt(iter, minor)); if (iter.len < len) @@ -642,21 +657,22 @@ pub fn matchValue(iter: *[]const u8, value: anytype) Error!bool { if (comptime isExtractor(T)) return value.extract(iter); return switch (comptime @typeInfo(T)) { - .Int => return matchIntValue(T, iter, value), - .ComptimeInt => return matchIntValue(i64, iter, value), - .Bool => matchBoolValue(iter, value), - .Pointer => |info| switch (info.size) { - .One => matchValue(iter, value.*), - .Many, .C => matchError(T), - .Slice => if (info.child == u8) matchStringValue(iter, value) else matchArray(iter, value, info), + .int => return matchIntValue(T, iter, value), + .comptime_int => return matchIntValue(i64, iter, value), + .bool => matchBoolValue(iter, value), + .pointer => |info| switch (info.size) { + .one => matchValue(iter, value.*), + .many, .c => matchError(T), + .slice => if (info.child == u8) matchStringValue(iter, value) else matchArray(iter, value, info), }, - .Struct => |info| if (info.is_tuple) + .@"struct" => |info| if (info.is_tuple) matchArray(iter, value, info) else matchError(T), - .Array => |info| if (info.child == u8) matchStringValue(iter, &value) else matchArray(iter, value, info), - .Float => return matchFloatValue(T, iter, value), - .ComptimeFloat => matchFloatValue(f64, iter, value), + .array => |info| if (info.child == u8) matchStringValue(iter, &value) else matchArray(iter, value, info), + .float => matchFloatValue(T, iter, value), + .comptime_float => matchFloatValue(f64, iter, value), + .@"enum" => matchEnumValue(T, iter, value), else => @compileError("cannot match value type '" ++ @typeName(T) ++ "' to cbor stream"), }; } @@ -784,7 +800,7 @@ fn hasExtractorTag(info: anytype) bool { fn isExtractor(comptime T: type) bool { return comptime switch (@typeInfo(T)) { - .Struct => |info| hasExtractorTag(info), + .@"struct" => |info| hasExtractorTag(info), else => false, }; } @@ -837,15 +853,15 @@ fn Extractor(comptime T: type) type { pub fn extract(self: Self, iter: *[]const u8) Error!bool { switch (comptime @typeInfo(T)) { - .Int, .ComptimeInt => return matchInt(T, iter, self.dest), - .Bool => return matchBool(iter, self.dest), - .Pointer => |ptr_info| switch (ptr_info.size) { - .Slice => { + .int, .comptime_int => return matchInt(T, iter, self.dest), + .bool => return matchBool(iter, self.dest), + .pointer => |ptr_info| switch (ptr_info.size) { + .slice => { if (ptr_info.child == u8) return matchString(iter, self.dest) else extractError(T); }, else => extractError(T), }, - .Optional => |opt_info| { + .optional => |opt_info| { var nested: opt_info.child = undefined; const extractor = Extractor(opt_info.child).init(&nested); if (try extractor.extract(iter)) { @@ -854,7 +870,8 @@ fn Extractor(comptime T: type) type { } return false; }, - .Float => return matchFloat(T, iter, self.dest), + .float => return matchFloat(T, iter, self.dest), + .@"enum" => return matchEnum(T, iter, self.dest), else => extractError(T), } } @@ -863,8 +880,8 @@ fn Extractor(comptime T: type) type { fn ExtractorType(comptime T: type) type { const T_type_info = @typeInfo(T); - if (T_type_info != .Pointer) @compileError("extract requires a pointer argument"); - return Extractor(T_type_info.Pointer.child); + if (T_type_info != .pointer) @compileError("extract requires a pointer argument"); + return Extractor(T_type_info.pointer.child); } pub fn extract(dest: anytype) ExtractorType(@TypeOf(dest)) { diff --git a/src/executor_asio.cpp b/src/executor_asio.cpp index 69f905d..4cdbc7c 100644 --- a/src/executor_asio.cpp +++ b/src/executor_asio.cpp @@ -58,12 +58,16 @@ using asio::windows::stream_handle; namespace thespian::executor { +const char *MIN_THREAD_STR = getenv("MIN_THREAD"); // NOLINT +const auto MIN_THREAD = + static_cast(atoi(MIN_THREAD_STR ? MIN_THREAD_STR : "4")); // NOLINT + const char *MAX_THREAD_STR = getenv("MAX_THREAD"); // NOLINT const auto MAX_THREAD = static_cast(atoi(MAX_THREAD_STR ? MAX_THREAD_STR : "64")); // NOLINT #if !defined(_WIN32) -const auto threads = min(sysconf(_SC_NPROCESSORS_ONLN), MAX_THREAD); +const auto threads = max(min(sysconf(_SC_NPROCESSORS_ONLN), MAX_THREAD), MIN_THREAD); #else namespace { static auto get_num_processors() -> long { @@ -72,7 +76,7 @@ static auto get_num_processors() -> long { return si.dwNumberOfProcessors; } } // namespace -const auto threads = min(get_num_processors(), MAX_THREAD); +const auto threads = max(min(get_num_processors(), MAX_THREAD), MIN_THREAD); #endif struct context_impl { diff --git a/src/subprocess.zig b/src/subprocess.zig index d7bddf0..7a2ee03 100644 --- a/src/subprocess.zig +++ b/src/subprocess.zig @@ -145,9 +145,9 @@ const Proc = struct { fn receive(self: *Proc, _: tp.pid_ref, m: tp.message) tp.result { errdefer self.deinit(); - var bytes: []u8 = ""; + var bytes: []const u8 = ""; var err: i64 = 0; - var err_msg: []u8 = ""; + var err_msg: []const u8 = ""; if (try m.match(.{ "fd", "stdout", "read_ready" })) { try self.dispatch_stdout(); if (self.fd_stdout) |fd_stdout| fd_stdout.wait_read() catch |e| return self.handle_error(e); diff --git a/src/subprocess_windows.zig b/src/subprocess_windows.zig index e9eaea1..3770ca8 100644 --- a/src/subprocess_windows.zig +++ b/src/subprocess_windows.zig @@ -138,10 +138,10 @@ const Proc = struct { fn receive(self: *Proc, _: tp.pid_ref, m: tp.message) tp.result { errdefer self.deinit(); - var bytes: []u8 = ""; - var stream_name: []u8 = ""; + var bytes: []const u8 = ""; + var stream_name: []const u8 = ""; var err: i64 = 0; - var err_msg: []u8 = ""; + var err_msg: []const u8 = ""; if (try m.match(.{ "stream", "stdout", "read_complete", tp.extract(&bytes) })) { try self.dispatch_stdout(bytes); if (self.stream_stdout) |stream| stream.start_read() catch |e| return self.handle_error(e); @@ -692,7 +692,7 @@ const Child = struct { } var io_status: windows.IO_STATUS_BLOCK = undefined; - const num_supported_pathext = @typeInfo(CreateProcessSupportedExtension).Enum.fields.len; + const num_supported_pathext = @typeInfo(CreateProcessSupportedExtension).@"enum".fields.len; var pathext_seen = [_]bool{false} ** num_supported_pathext; var any_pathext_seen = false; var unappended_exists = false; diff --git a/src/thespian.zig b/src/thespian.zig index 28f6a70..136937d 100644 --- a/src/thespian.zig +++ b/src/thespian.zig @@ -138,7 +138,7 @@ pub const message = struct { pub fn fmt(value: anytype) Self { message_buffer.clearRetainingCapacity(); const f = comptime switch (@typeInfo(@TypeOf(value))) { - .Struct => |info| if (info.is_tuple) + .@"struct" => |info| if (info.is_tuple) fmt_internal else @compileError("thespian.message template should be a tuple: " ++ @typeName(@TypeOf(value))), @@ -158,7 +158,7 @@ pub const message = struct { pub fn fmtbuf(buf: []u8, value: anytype) !Self { const f = comptime switch (@typeInfo(@TypeOf(value))) { - .Struct => |info| if (info.is_tuple) + .@"struct" => |info| if (info.is_tuple) fmtbuf_internal else @compileError("thespian.message template should be a tuple: " ++ @typeName(@TypeOf(value))), @@ -221,14 +221,14 @@ pub fn exit_message(e: anytype, stack_trace: ?*std.builtin.StackTrace) message { defer debug_info_arena_allocator.deinit(); const a = debug_info_arena_allocator.allocator(); var out = std.ArrayList(u8).init(a); - store_stack_trace(a, stack_trace_.*, out.writer()); + store_stack_trace(stack_trace_.*, out.writer()); return message.fmtbuf(&error_message_buffer, .{ "exit", e, out.items }) catch unreachable; } else { return message.fmtbuf(&error_message_buffer, .{ "exit", e }) catch unreachable; } } -fn store_stack_trace(a: std.mem.Allocator, stack_trace: std.builtin.StackTrace, writer: anytype) void { +fn store_stack_trace(stack_trace: std.builtin.StackTrace, writer: anytype) void { nosuspend { if (builtin.strip_debug_info) { writer.print("Unable to store stack trace: debug info stripped\n", .{}) catch return; @@ -238,7 +238,7 @@ fn store_stack_trace(a: std.mem.Allocator, stack_trace: std.builtin.StackTrace, writer.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; return; }; - std.debug.writeStackTrace(stack_trace, writer, a, debug_info, .no_color) catch |err| { + std.debug.writeStackTrace(stack_trace, writer, debug_info, .no_color) catch |err| { writer.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; return; }; @@ -260,7 +260,7 @@ pub fn exit_fmt(comptime fmt: anytype, args: anytype) error{Exit} { } pub fn exit_error(e: anyerror, stack_trace: ?*std.builtin.StackTrace) error{Exit} { - if (stack_trace_on_errors and e == error.OutOfMemory) std.debug.panicExtra(stack_trace, null, "{any}", .{e}); + if (stack_trace_on_errors and e == error.OutOfMemory) std.debug.panic("{any}", .{e}); return switch (e) { error.Exit => error.Exit, else => set_error_msg(exit_message(e, stack_trace)), @@ -336,6 +336,7 @@ pub const channel = struct { pub const event: c.thespian_trace_channel = 2048; pub const widget: c.thespian_trace_channel = 4096; pub const input: c.thespian_trace_channel = 8192; + pub const debug: c.thespian_trace_channel = 16384; pub const all = c.thespian_trace_channel_all; }; @@ -427,7 +428,8 @@ pub fn trace(chan: trace_channel, value: anytype) void { env.get().trace(value.to(message.c_buffer_type)); } else { var trace_buffer: [512]u8 = undefined; - const m = message.fmtbuf(&trace_buffer, value); + const m = message.fmtbuf(&trace_buffer, value) catch |e| + std.debug.panic("TRACE ERROR: {}", .{e}); env.get().trace(m.to(message.c_buffer_type)); } } @@ -497,14 +499,14 @@ fn log_last_error(err: anytype) @TypeOf(err) { fn exitHandlerRun(comptime T: type) c.thespian_exit_handler { if (T == @TypeOf(null)) return null; return switch (@typeInfo(T)) { - .Optional => |info| switch (@typeInfo(info.child)) { - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => ptr_info.child.run, + .optional => |info| switch (@typeInfo(info.child)) { + .pointer => |ptr_info| switch (ptr_info.size) { + .one => ptr_info.child.run, else => @compileError("expected single item pointer, found: '" ++ @typeName(T) ++ "'"), }, }, - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => ptr_info.child.run, + .pointer => |ptr_info| switch (ptr_info.size) { + .one => ptr_info.child.run, else => @compileError("expected single item pointer, found: '" ++ @typeName(T) ++ "'"), }, else => @compileError("expected optional pointer or pointer type, found: '" ++ @typeName(T) ++ "'"), @@ -513,8 +515,8 @@ fn exitHandlerRun(comptime T: type) c.thespian_exit_handler { pub fn receive(r: anytype) void { const T = switch (@typeInfo(@TypeOf(r))) { - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => ptr_info.child, + .pointer => |ptr_info| switch (ptr_info.size) { + .one => ptr_info.child, else => @compileError("invalid receiver type"), }, else => @compileError("invalid receiver type"), diff --git a/test/tests_cbor.zig b/test/tests_cbor.zig index f3d52af..1d27410 100644 --- a/test/tests_cbor.zig +++ b/test/tests_cbor.zig @@ -151,7 +151,7 @@ test "cbor.matchValue(i64) multi" { var buf: [128]u8 = undefined; const iter = fmt(&buf, 7); const iter2 = fmt(buf[iter.len..], 8); - var iter3 = buf[0 .. iter.len + iter2.len]; + var iter3: []const u8 = buf[0 .. iter.len + iter2.len]; try expect(try matchValue(&iter3, 7)); try expect(try matchValue(&iter3, 8)); }