From be3fd8878e628e3ab4ae5509dfeacf5b5c7065aa Mon Sep 17 00:00:00 2001 From: ItsMeSamey Date: Sun, 4 Oct 2026 08:35:38 +1000 Subject: [PATCH 1/2] build: migrate to Zig 0.17.0 --- .github/workflows/ci.yml | 8 ++++---- CONTRIBUTING.md | 4 +++- README.md | 2 ++ build.zig | 22 ++++++++++++++-------- build.zig.zon | 2 +- src/document.zig | 19 +++++++++++++------ src/parser.zig | 7 ++++++- src/root.zig | 4 ++-- src/scanner.zig | 16 ++++++++-------- src/streaming.zig | 6 +++--- src/tables.zig | 8 ++++---- test_runner.zig | 6 +++--- tests/public_api.zig | 10 +++++----- tools/scripts.zig | 10 +++++----- 14 files changed, 73 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe9c783..ce6f821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: 0.17.0 - name: Zig fmt check shell: bash @@ -36,7 +36,7 @@ jobs: - name: Benchmark smoke shell: bash run: | - zig build bench-only -Doptimize=ReleaseFast + zig build bench-only -Doptimize=fast for mode in validated validated-trusted permissive; do ./zig-out/bin/zxml-bench parse "$mode" bench/smoke.xml 1 >/dev/null ./zig-out/bin/zxml-stream-bench parse "$mode" bench/smoke.xml 1 >/dev/null @@ -45,8 +45,8 @@ jobs: - name: Darwin compile and 32-bit public API shell: bash run: | - zig build bench-only -Dtarget=x86_64-macos -Doptimize=ReleaseFast - zig build test-public-api -Dtarget=x86-linux-musl -Dintlen=u64 -Doptimize=ReleaseSafe + zig build bench-only -Dtarget=x86_64-macos -Doptimize=fast + zig build test-public-api -Dtarget=x86-linux-musl -Dintlen=u64 -Doptimize=safe - name: Conformance run: zig build conformance diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b235a3..5b2e8dd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Prerequisites -- Zig `0.16.0` +- Zig `0.17.0` - Git ## Local Development Workflow @@ -23,6 +23,8 @@ zig build bench-compare zig build conformance ``` +Use `zig build test -j1 -Dtest-jobs=1` to bound both compilation and test-process concurrency. + ## Style - Format Zig code before pushing: diff --git a/README.md b/README.md index c34139b..80a1903 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Fast XML parsing for Zig with comptime-generated DOM and streaming types. The default parser is destructive and permissive. Attributes and text stay source-backed and are materialized lazily; the DOM does not build an attribute array or a separate open-element stack. +Requires Zig `0.17.0`. + ## Quick start ```zig diff --git a/build.zig b/build.zig index f41d44d..bc620ff 100644 --- a/build.zig +++ b/build.zig @@ -11,6 +11,7 @@ const IntLen = enum { pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const test_jobs = b.option(usize, "test-jobs", "Maximum concurrent test processes"); const intlen = b.option(IntLen, "intlen", "Integer width used for DOM spans and node indexes") orelse .u32; const config_options = b.addOptions(); @@ -117,20 +118,19 @@ pub fn build(b: *std.Build) void { docs_check_cmd.step.dependOn(b.getInstallStep()); examples_check_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - tools_cmd.addArgs(args); - compare_cmd.addArgs(args); - interleaved_cmd.addArgs(args); - conformance_cmd.addArgs(args); - docs_check_cmd.addArgs(args); - examples_check_cmd.addArgs(args); - } + tools_cmd.addPassthruArgs(); + compare_cmd.addPassthruArgs(); + interleaved_cmd.addPassthruArgs(); + conformance_cmd.addPassthruArgs(); + docs_check_cmd.addPassthruArgs(); + examples_check_cmd.addPassthruArgs(); const mod_tests = b.addTest(.{ .root_module = mod, .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_mod_tests = b.addRunArtifact(mod_tests); + if (test_jobs) |jobs| run_mod_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const example_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -144,6 +144,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_example_tests = b.addRunArtifact(example_tests); + if (test_jobs) |jobs| run_example_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const bench_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -157,6 +158,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_bench_tests = b.addRunArtifact(bench_tests); + if (test_jobs) |jobs| run_bench_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const tools_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -170,6 +172,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_tools_tests = b.addRunArtifact(tools_tests); + if (test_jobs) |jobs| run_tools_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const tools_common_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -180,6 +183,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_tools_common_tests = b.addRunArtifact(tools_common_tests); + if (test_jobs) |jobs| run_tools_common_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const conformance_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -193,6 +197,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_conformance_tests = b.addRunArtifact(conformance_tests); + if (test_jobs) |jobs| run_conformance_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const public_api_tests = b.addTest(.{ .root_module = b.createModule(.{ @@ -206,6 +211,7 @@ pub fn build(b: *std.Build) void { .test_runner = .{ .path = b.path("test_runner.zig"), .mode = .simple }, }); const run_public_api_tests = b.addRunArtifact(public_api_tests); + if (test_jobs) |jobs| run_public_api_tests.addArgs(&.{ "--jobs", b.fmt("{d}", .{jobs}) }); const public_api_step = b.step("test-public-api", "Run exhaustive consumer-facing public API tests"); public_api_step.dependOn(&run_public_api_tests.step); diff --git a/build.zig.zon b/build.zig.zon index b641670..ae868a4 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,7 +2,7 @@ .name = .zxml, .version = "0.1.0", .fingerprint = 0xeb739e953d363ad3, - .minimum_zig_version = "0.16.0", + .minimum_zig_version = "0.17.0", .paths = .{ ".gitignore", "LICENSE", diff --git a/src/document.zig b/src/document.zig index ed0831a..da16ba9 100644 --- a/src/document.zig +++ b/src/document.zig @@ -1656,8 +1656,9 @@ fn consumeMixedContent(input: []const u8, i: *usize) ParseError!void { fn consumeChildrenContent(allocator: std.mem.Allocator, input: []const u8, i: *usize) ParseError!void { std.debug.assert(input[i.*] == '('); - var stack_fallback = std.heap.stackFallback(512, allocator); - const temp_allocator = stack_fallback.get(); + var stack_buffer: [512]u8 align(@alignOf(ContentFrame)) = undefined; + var stack_fallback: std.heap.BufferFirstAllocator = .init(&stack_buffer, allocator); + const temp_allocator = stack_fallback.allocator(); var stack: std.ArrayList(ContentFrame) = .empty; defer stack.deinit(temp_allocator); @@ -2470,7 +2471,7 @@ pub fn GetDocument(comptime options: ParseOptions) type { const end: usize = @intCast(span.end); if (end >= self.source.len) return .raw; return switch (self.source[end]) { - @intFromEnum(TextMaterializationState.decoded) => .decoded, + @backingInt(TextMaterializationState.decoded) => .decoded, else => .raw, }; } @@ -2478,7 +2479,7 @@ pub fn GetDocument(comptime options: ParseOptions) type { inline fn markTextState(self: *Self, idx: IndexInt, state: TextMaterializationState) void { if (comptime options.non_destructive) return; const end: usize = @intCast(self.nodes[@intCast(idx)].valueSpan(idx).end); - if (end < self.source.len) self.source[end] = @intFromEnum(state); + if (end < self.source.len) self.source[end] = @backingInt(state); } fn materializeText(self: *Self, idx: IndexInt, alloc: std.mem.Allocator) ValueError!common.SliceResult { @@ -3253,7 +3254,7 @@ test "XML character vector exits never skip invalid controls or encodings" { } test "XML character validation crosses dense Unicode and ASCII windows" { - const source = "é漢😀" ** 20 ++ " ASCII " ** 20 ++ "Ω漢é" ** 35; + const source = &(comptime repeatTestBytes("é漢😀", 20) ++ repeatTestBytes(" ASCII ", 20) ++ repeatTestBytes("Ω漢é", 35)); for (0..source.len + 1) |split| { var expected = split; while (!std.unicode.utf8ValidateSlice(source[0..expected])) : (expected -= 1) {} @@ -3279,7 +3280,7 @@ test "vector UTF-8 validation rejects illegal sequences at every lane boundary" try std.testing.expectError(error.InvalidXmlCharacter, xmlValidPrefixLenStreaming(&input)); } } - const valid = "é漢😀Ω" ** 12 ++ " \t\n\rASCII" ** 4; + const valid = &(comptime repeatTestBytes("é漢😀Ω", 12) ++ repeatTestBytes(" \t\n\rASCII", 4)); for (0..valid.len + 1) |end| { var boundary = end; while (!std.unicode.utf8ValidateSlice(valid[0..boundary])) : (boundary -= 1) {} @@ -3441,3 +3442,9 @@ test "compact validated serialization preserves a required DOCTYPE" { try std.testing.expectEqualStrings("&e;", reparsed.nodeAt(1).?.getAttributeValueRaw("a").?); } } + +fn repeatTestBytes(comptime bytes: []const u8, comptime count: usize) [bytes.len * count]u8 { + var result: [bytes.len * count]u8 = undefined; + for (0..count) |i| @memcpy(result[i * bytes.len ..][0..bytes.len], bytes); + return result; +} diff --git a/src/parser.zig b/src/parser.zig index 14ecfa0..769bf03 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -2092,7 +2092,12 @@ test "inline node storage spills safely and releases every failed allocation" { const Check = struct { fn run(allocator: std.mem.Allocator) !void { const options: ParseOptions = .{ .validate_well_formedness = true }; - var source = ("" ++ "value" ** 90 ++ "").*; + var source = comptime blk: { + const child = "value"; + var children: [child.len * 90]u8 = undefined; + for (0..90) |i| @memcpy(children[i * child.len ..][0..child.len], child); + break :blk "".* ++ children ++ "".*; + }; var doc = try options.parse(allocator, &source); defer doc.deinit(); try std.testing.expectEqual(@as(usize, 182), doc.nodes.len); diff --git a/src/root.zig b/src/root.zig index 7c15a98..75bad27 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1564,11 +1564,11 @@ fn refAllDeclsRecursiveSeen(comptime T: type, comptime seen: []const type) void // Recurse into namespace-style containers only; value-carrying types blow // up the traversal without contributing additional declaration coverage. inline for (comptime std.meta.declarations(T)) |decl| { - const decl_value = @field(T, decl.name); + const decl_value = @field(T, decl); if (@TypeOf(decl_value) != type) continue; const Child = decl_value; if (comptime switch (@typeInfo(Child)) { - .@"struct" => |s| s.fields.len != 0, + .@"struct" => |s| s.field_names.len != 0, .@"union", .@"enum", .@"opaque" => true, else => true, }) continue; diff --git a/src/scanner.zig b/src/scanner.zig index 1bb9ec0..3f4680f 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -11,7 +11,7 @@ const byte_scan_vector_len: comptime_int = switch (builtin.cpu.arch) { pub noinline fn countByte(source: []const u8, value: u8) usize { const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); const needle: Vec = @splat(value); var i: usize = 0; var count: usize = 0; @@ -145,7 +145,7 @@ pub inline fn findTextEnd(noalias haystack: []const u8, start: usize) ?usize { const Vec = @Vector(byte_scan_vector_len, u8); if (haystack.len - start >= @sizeOf(Vec)) { const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); // Load the vector directly; array coercion can reconstruct it from scalar loads. const bytes = @as(*align(1) const Vec, @ptrCast(haystack.ptr + start)).*; const lt_vec: Vec = @splat('<'); @@ -170,7 +170,7 @@ pub noinline fn scanStartTagEnd(noalias input: []const u8, start: usize) ?StartT const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); const gt_vec: Vec = @splat('>'); const sq_vec: Vec = @splat('\''); const dq_vec: Vec = @splat('"'); @@ -250,7 +250,7 @@ pub noinline fn scanStartTagEndFast(noalias input: []const u8, start: usize) usi if (start >= input.len) return 0; const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); if (input.len - start < @sizeOf(Vec)) return scanStartTagEndFastLong(input, start, start, 0, false); const bytes: Vec = input[start..][0..@sizeOf(Vec)].*; @@ -277,7 +277,7 @@ noinline fn scanStartTagEndFastLong( ) usize { const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); var seen_quotes = initial_seen_quotes; var odd = initial_odd; var i = initial_i; @@ -490,7 +490,7 @@ pub inline fn scanQuotedValueSpecials(noalias hay: []const u8, start: usize, quo const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); const quote_vec: Vec = @splat(quote); const lt_vec: Vec = @splat('<'); const amp_vec: Vec = @splat('&'); @@ -730,7 +730,7 @@ pub inline fn scanTextSpecials(noalias hay: []const u8, start: usize) TextSpecia const Vec = @Vector(byte_scan_vector_len, u8); const Bits = @Vector(byte_scan_vector_len, u1); - const Mask = std.meta.Int(.unsigned, byte_scan_vector_len); + const Mask = @Int(.unsigned, byte_scan_vector_len); const lt_vec: Vec = @splat('<'); const close_vec: Vec = @splat(']'); const amp_vec: Vec = @splat('&'); @@ -1110,7 +1110,7 @@ test "bytePairPresence finds either sentinel in short and vector-sized inputs" { try std.testing.expect(both.first); try std.testing.expect(both.second); - var long = [_]u8{'x'} ** (byte_scan_vector_len * 2 + 3); + var long: [byte_scan_vector_len * 2 + 3]u8 = @splat('x'); long[byte_scan_vector_len - 1] = ']'; long[byte_scan_vector_len * 2 + 1] = '&'; const vector = bytePairPresence(&long, ']', '&'); diff --git a/src/streaming.zig b/src/streaming.zig index 345e4e6..e6213c3 100644 --- a/src/streaming.zig +++ b/src/streaming.zig @@ -1651,13 +1651,13 @@ const CallbackKind = enum { fn callbackKind(comptime callback: anytype, comptime Node: type) CallbackKind { const cb_info = @typeInfo(@TypeOf(callback)).@"fn"; - return switch (cb_info.params.len) { - 1 => switch (cb_info.params[0].type.?) { + return switch (cb_info.param_types.len) { + 1 => switch (cb_info.param_types[0].?) { Node => .node, *const Node => .node_ptr, else => @compileError("streaming callback node parameter must be Node or *const Node"), }, - 2 => switch (cb_info.params[1].type.?) { + 2 => switch (cb_info.param_types[1].?) { Node => .ctx_node, *const Node => .ctx_node_ptr, else => @compileError("streaming callback node parameter must be Node or *const Node"), diff --git a/src/tables.zig b/src/tables.zig index fc38e96..bcde18c 100644 --- a/src/tables.zig +++ b/src/tables.zig @@ -1,7 +1,7 @@ const std = @import("std"); pub const WhitespaceTable = blk: { - var t = [_]bool{false} ** 256; + var t: [256]bool = @splat(false); t[' '] = true; t['\t'] = true; t['\n'] = true; @@ -10,7 +10,7 @@ pub const WhitespaceTable = blk: { }; pub const NameStartTable = blk: { - var t = [_]bool{false} ** 256; + var t: [256]bool = @splat(false); for ('A'..('Z' + 1)) |c| t[c] = true; for ('a'..('z' + 1)) |c| t[c] = true; for (0x80..256) |c| t[c] = true; @@ -20,7 +20,7 @@ pub const NameStartTable = blk: { }; pub const NameCharTable = blk: { - var t = [_]bool{false} ** 256; + var t: [256]bool = @splat(false); for ('A'..('Z' + 1)) |c| t[c] = true; for ('a'..('z' + 1)) |c| t[c] = true; for ('0'..('9' + 1)) |c| t[c] = true; @@ -33,7 +33,7 @@ pub const NameCharTable = blk: { }; pub const AttrUnquotedValueCharTable = blk: { - var t = [_]bool{true} ** 256; + var t: [256]bool = @splat(true); t['<'] = false; t['>'] = false; t['&'] = false; diff --git a/test_runner.zig b/test_runner.zig index 54861c4..3f5f073 100644 --- a/test_runner.zig +++ b/test_runner.zig @@ -515,7 +515,7 @@ fn printTestOutput(name: []const u8, res: ChildResult) void { switch (res.term) { .exited => |code| if (code != 0) print(" | exit {d}", .{code}), - .signal => |sig| print(" | signal {d} ({s})", .{ @intFromEnum(sig), @tagName(sig) }), + .signal => |sig| print(" | signal {d} ({s})", .{ @backingInt(sig), @tagName(sig) }), .stopped => |code| print(" | stopped {d}", .{code}), .unknown => |code| print(" | unknown {d}", .{code}), } @@ -544,11 +544,11 @@ fn runSingleTest(name: []const u8, seed: ?u32) void { std.process.exit(1); }; - std.testing.allocator_instance = .{}; + std.testing.allocator_instance = .init(std.heap.page_allocator, .{ .check_write_after_free = true }); const result = test_fn.func(); const leak_status = std.testing.allocator_instance.deinit(); - if (leak_status == .leak) { + if (leak_status != 0) { print("memory leak\n", .{}); std.process.exit(3); } diff --git a/tests/public_api.zig b/tests/public_api.zig index 76b0da8..fc24380 100644 --- a/tests/public_api.zig +++ b/tests/public_api.zig @@ -10,8 +10,8 @@ fn assertDeclCoverage(comptime T: type, comptime expected: []const []const u8) v comptime { const decls = std.meta.declarations(T); for (decls) |decl| { - if (!contains(expected, decl.name)) { - @compileError("public API declaration is not covered: " ++ @typeName(T) ++ "." ++ decl.name); + if (!contains(expected, decl)) { + @compileError("public API declaration is not covered: " ++ @typeName(T) ++ "." ++ decl); } } if (decls.len != expected.len) @compileError("public API declaration coverage list contains a missing declaration for " ++ @typeName(T)); @@ -22,11 +22,11 @@ fn assertFnCoverage(comptime T: type, comptime expected: []const []const u8) voi comptime { var actual: usize = 0; for (std.meta.declarations(T)) |decl| { - const value = @field(T, decl.name); + const value = @field(T, decl); if (@typeInfo(@TypeOf(value)) != .@"fn") continue; actual += 1; - if (!contains(expected, decl.name)) { - @compileError("public API function is not exercised: " ++ @typeName(T) ++ "." ++ decl.name); + if (!contains(expected, decl)) { + @compileError("public API function is not exercised: " ++ @typeName(T) ++ "." ++ decl); } } if (actual != expected.len) @compileError("public API coverage list contains a missing/non-function declaration for " ++ @typeName(T)); diff --git a/tools/scripts.zig b/tools/scripts.zig index 68395e9..91825f9 100644 --- a/tools/scripts.zig +++ b/tools/scripts.zig @@ -104,8 +104,8 @@ const BenchmarkEnvironment = struct { cxx_driver: []const u8, fn deinit(self: BenchmarkEnvironment, alloc: std.mem.Allocator) void { - inline for (std.meta.fields(BenchmarkEnvironment)) |field| { - alloc.free(@field(self, field.name)); + inline for (comptime std.meta.fieldNames(BenchmarkEnvironment)) |field_name| { + alloc.free(@field(self, field_name)); } } }; @@ -862,7 +862,7 @@ fn buildRunners(io: std.Io, alloc: std.mem.Allocator, force_external_rebuild: bo // Match zhtml: build the installed benchmark binary directly. The tools // executable is already running, so bench-only avoids recursive tool builds. - const zig_build = [_][]const u8{ "zig", "build", "bench-only", "-Doptimize=ReleaseFast", "-Dcpu=native" }; + const zig_build = [_][]const u8{ "zig", "build", "bench-only", "-Doptimize=fast", "-Dcpu=native" }; try runInheritWithBenchTmp(io, alloc, &zig_build, REPO_ROOT); const pugixml_sources = [_][]const u8{ @@ -1576,7 +1576,7 @@ fn writeBenchmarkEnvironmentTable(w: anytype, heading: []const u8, environment: try w.print("| CPU | {s} |\n", .{environment.cpu_model}); try w.print("| CPU frequency scaling | {s} |\n", .{environment.cpu_scaling}); try w.print("| CPU MHz range | {s}–{s} |\n", .{ environment.cpu_min_mhz, environment.cpu_max_mhz }); - try w.print("| Zig | {s} (`ReleaseFast -Dcpu=native`) |\n", .{environment.zig_version}); + try w.print("| Zig | {s} (`fast -Dcpu=native`) |\n", .{environment.zig_version}); try w.print("| C++ driver | {s} (`-O3 -DNDEBUG -march=native`) |\n\n", .{environment.cxx_driver}); } @@ -2840,7 +2840,7 @@ fn compareWorktrees(io: std.Io, alloc: std.mem.Allocator, args: []const []const const seed_text = try std.fmt.allocPrint(alloc, "{d}", .{seed}); defer alloc.free(seed_text); try common.runInherit(io, alloc, &.{ - "zig", "build", "bench-only", "-Doptimize=ReleaseFast", "-Dcpu=native", "--seed", seed_text, + "zig", "build", "bench-only", "-Doptimize=fast", "-Dcpu=native", "--seed", seed_text, }, worktree); } From 9087aeee00bfc7e9dedc709df44adcf7f0bc54a2 Mon Sep 17 00:00:00 2001 From: ItsMeSamey Date: Sun, 4 Oct 2026 08:37:46 +1000 Subject: [PATCH 2/2] style: apply Zig 0.17 formatter --- bench/runners/run_parse.zig | 6 +++--- src/attr.zig | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bench/runners/run_parse.zig b/bench/runners/run_parse.zig index 70c5c5c..4878b2d 100644 --- a/bench/runners/run_parse.zig +++ b/bench/runners/run_parse.zig @@ -108,7 +108,7 @@ fn runStreamValidated(io: std.Io, alloc: std.mem.Allocator, input: []const u8, i fn onNode(self: *@This(), node: *const StreamingEventType) bool { self.count +%= 1; - self.checksum +%= @as(u64, @intFromEnum(node.kind)) +% 1; + self.checksum +%= @as(u64, @backingInt(node.kind)) +% 1; switch (node.kind) { .element => { self.checksum +%= @as(u64, node.name.end - node.name.start); @@ -143,7 +143,7 @@ fn runStreamValidatedTrusted(io: std.Io, alloc: std.mem.Allocator, input: []cons fn onNode(self: *@This(), node: *const StreamingEventType) bool { self.count +%= 1; - self.checksum +%= @as(u64, @intFromEnum(node.kind)) +% 1; + self.checksum +%= @as(u64, @backingInt(node.kind)) +% 1; switch (node.kind) { .element => { self.checksum +%= @as(u64, node.name.end - node.name.start); @@ -175,7 +175,7 @@ fn runStreamPermissive(io: std.Io, alloc: std.mem.Allocator, input: []const u8, fn onNode(self: *@This(), node: *const StreamingEventType) bool { self.count +%= 1; - self.checksum +%= @as(u64, @intFromEnum(node.kind)) +% 1; + self.checksum +%= @as(u64, @backingInt(node.kind)) +% 1; switch (node.kind) { .element => { self.checksum +%= @as(u64, node.name.end - node.name.start); diff --git a/src/attr.zig b/src/attr.zig index 79727df..5dd84e5 100644 --- a/src/attr.zig +++ b/src/attr.zig @@ -206,7 +206,7 @@ pub fn materializeAttributes( } } - source[write] = @intFromEnum(state); + source[write] = @backingInt(state); write += 1; const value_start: usize = @intCast(item.value.start); std.mem.copyForwards(u8, source[write .. write + value_len], source[value_start .. value_start + value_len]);