Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ea83962
zig: the 0.17 switch, scaffolded with marked stand-ins (#437)
foxnne Oct 16, 2026
9a22df2
zig: the build's custom steps become helper programs (#438)
foxnne Oct 16, 2026
2491f4e
zig: release packaging on 0.17, with Velopack 1.2.161 (#448)
foxnne Oct 16, 2026
b18213c
backend: no crash quitting a plain dvui app on macOS (#480)
foxnne Oct 17, 2026
a59ff14
backend: a plain dvui app's floating windows open as OS windows (#481)
foxnne Oct 17, 2026
67cc6ea
macos: a plain dvui app's windows take fizzy's window shape (#482)
foxnne Oct 17, 2026
78a5019
macos: child windows stay above the main window (#483)
foxnne Oct 17, 2026
46ddcd8
zig/0.17: merge main (40 commits, to #469)
foxnne Oct 17, 2026
6d94889
zig/0.17: merge main (40 commits, to #469) (#486)
foxnne Oct 17, 2026
28766fa
zig: settings and command schemas read 0.17's @typeInfo (#488)
foxnne Oct 17, 2026
b45233a
zig: a lifted view keeps its drag through dvui's captureMouseGet (#489)
foxnne Oct 17, 2026
a1feb78
docs: the Windows traps of the Zig 0.17 move (#494)
foxnne Oct 18, 2026
300d797
core: a transparent blit reads its pixels as bytes on Zig 0.17 (#496)
foxnne Oct 18, 2026
1b6ad2c
sdk: a plugin can install a program beside itself (#498)
foxnne Oct 18, 2026
0be3e64
zig/0.17: record #486's merge of main as a parent
foxnne Oct 18, 2026
47a0c1e
zig/0.17: merge main (6 commits, to #490)
foxnne Oct 18, 2026
87ae2ae
zig: what 0.16 needed goes with the move (#505)
foxnne Oct 18, 2026
3513b9f
macos: a plain dvui app's OS windows are ordinary document windows (#…
foxnne Oct 18, 2026
eb452e8
backend: OS windows for the floating windows that ask, or all by choi…
foxnne Oct 18, 2026
7336d4a
macos: a float's full screen at the display's rate, clear and rounded…
foxnne Oct 18, 2026
2dc6fc4
macos: the pointer reaches the window it is over, not one behind it (…
foxnne Oct 18, 2026
44849f2
zig/0.17: merge main (22 commits, to #509)
foxnne Oct 18, 2026
9e8e530
zig/0.17: merge main (22 commits, to #509) (#558)
foxnne Oct 18, 2026
54014c7
zig: settings own only strings, and builds read through b.root (#561)
foxnne Oct 18, 2026
39574be
core: one window material, and the kinds each backend can show (#546)
foxnne Oct 18, 2026
1c60f52
zig/0.17: record #558's merge of main as a parent
foxnne Oct 18, 2026
cfed055
zig/0.17: merge main (9 commits, to #569)
foxnne Oct 18, 2026
7d1347a
sdk: a plugin build compiles its install helper once, in Debug (#573)
foxnne Oct 18, 2026
57476de
Merge zig/0.17 (#573) into the main catch-up
foxnne Oct 18, 2026
c6bf7f3
zig/0.17: merge main (to #555)
foxnne Oct 18, 2026
c253724
zig: the 0.17 rewrite script goes
foxnne Oct 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"vpk": {
"version": "0.0.1298",
"version": "1.2.161",
"commands": [
"vpk"
],
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ concurrency:
cancel-in-progress: true

env:
ZIG_VERSION: "0.16.0"
ZIG_VERSION: "0.17.0"

jobs:
changes:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/plugin-loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on:
inputs:
zig_version:
description: "Zig to measure with (a version, or master)"
default: "0.16.0"
default: "0.17.0"
backends:
description: "Comma-separated: default, llvm, self-hosted"
default: "default,llvm,self-hosted"
Expand All @@ -34,7 +34,7 @@ concurrency:
cancel-in-progress: true

env:
ZIG_VERSION: ${{ inputs.zig_version || '0.16.0' }}
ZIG_VERSION: ${{ inputs.zig_version || '0.17.0' }}

jobs:
measure:
Expand Down
14 changes: 10 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ concurrency:
cancel-in-progress: false

env:
ZIG_VERSION: "0.16.0"
ZIG_VERSION: "0.17.0"

jobs:
# Linux + Windows: no fizzy_release environment (no signing secrets needed).
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:

- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0"
dotnet-version: "10.0" # vpk 1.2 targets .NET 10

# Prefetch before msvcup/package so lazy deps (e.g. zigwin32 from GitHub) get retry
# backoff; zig build msvcup-setup alone can hit HttpConnectionClosing with no retries.
Expand Down Expand Up @@ -278,7 +278,7 @@ jobs:

- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0"
dotnet-version: "10.0" # vpk 1.2 targets .NET 10

- name: Fetch deps with retries
shell: bash
Expand Down Expand Up @@ -349,7 +349,13 @@ jobs:
log="$RUNNER_TEMP/package-${{ matrix.channel }}.log"
n=0
until [ "$n" -ge 3 ]; do
if zig build package -Doptimize=ReleaseFast "-Dtarget=${{ matrix.target }}" 2>&1 | tee "$log"; then
# Signing as build options: zig build caches its configuration without regard to the
# environment, so build.zig does not read the FIZZY_MACOS_* variables itself.
sign=()
[ -n "${FIZZY_MACOS_SIGN_APP:-}" ] && sign+=("-Dmacos-sign-app=$FIZZY_MACOS_SIGN_APP")
[ -n "${FIZZY_MACOS_SIGN_INSTALLER:-}" ] && sign+=("-Dmacos-sign-installer=$FIZZY_MACOS_SIGN_INSTALLER")
[ -n "${FIZZY_MACOS_NOTARY_PROFILE:-}" ] && sign+=("-Dmacos-notary-profile=$FIZZY_MACOS_NOTARY_PROFILE")
if zig build package -Doptimize=ReleaseFast "-Dtarget=${{ matrix.target }}" ${sign[@]+"${sign[@]}"} 2>&1 | tee "$log"; then
exit 0
fi
if ! grep -Eq 'HttpConnectionClosing|invalid HTTP response|TlsInitializationFailed|ConnectionResetByPeer|TemporaryNameServerFailure|unable to fetch|connection reset' "$log"; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ on:
default: ""

env:
ZIG_VERSION: "0.16.0"
ZIG_VERSION: "0.17.0"
WEBSITE: fizzyedit/website

jobs:
Expand Down
8 changes: 4 additions & 4 deletions app/App.zig
Original file line number Diff line number Diff line change
Expand Up @@ -844,11 +844,11 @@ pub fn readPluginReservedField(gpa: std.mem.Allocator, settings_data: ?[:0]const
const data = settings_data orelse return null;
const plugins = SettingsPluginsZon.extractField(gpa, data, "plugins") orelse return null;
defer gpa.free(plugins);
const plugins_z = gpa.dupeZ(u8, plugins) catch return null;
const plugins_z = gpa.dupeSentinel(u8, plugins, 0) catch return null;
defer gpa.free(plugins_z);
const id_block = SettingsPluginsZon.extractField(gpa, plugins_z, id) orelse return null;
defer gpa.free(id_block);
const id_z = gpa.dupeZ(u8, id_block) catch return null;
const id_z = gpa.dupeSentinel(u8, id_block, 0) catch return null;
defer gpa.free(id_z);
return SettingsPluginsZon.extractField(gpa, id_z, field);
}
Expand All @@ -858,11 +858,11 @@ pub fn readPluginSettingsText(gpa: std.mem.Allocator, settings_data: ?[:0]const
const data = settings_data orelse return null;
const plugins = SettingsPluginsZon.extractField(gpa, data, "plugins") orelse return null;
defer gpa.free(plugins);
const plugins_z = gpa.dupeZ(u8, plugins) catch return null;
const plugins_z = gpa.dupeSentinel(u8, plugins, 0) catch return null;
defer gpa.free(plugins_z);
const id_block = SettingsPluginsZon.extractField(gpa, plugins_z, id) orelse return null;
defer gpa.free(id_block);
const id_z = gpa.dupeZ(u8, id_block) catch return null;
const id_z = gpa.dupeSentinel(u8, id_block, 0) catch return null;
defer gpa.free(id_z);
return SettingsPluginsZon.extractField(gpa, id_z, "settings");
}
Expand Down
7 changes: 4 additions & 3 deletions app/Recents.zig
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ pub fn load(allocator: std.mem.Allocator, path: []const u8) !Recents {
if (core.fs.readZ(allocator, dvui.io, path) catch null) |data| {
defer allocator.free(data);

if (std.zon.parse.fromSliceAlloc(Disk, allocator, data, null, .{ .ignore_unknown_fields = true }) catch null) |disk| {
defer std.zon.parse.free(allocator, disk);

var disk_arena: std.heap.ArenaAllocator = .init(allocator);
defer disk_arena.deinit();
var disk_diag: std.zon.parse.Diagnostics = undefined;
if (std.zon.parse.fromSlice(Disk, .{ .gpa = allocator, .arena = disk_arena.allocator(), .source = data, .diagnostics = &disk_diag, .ignore_unknown_fields = true }) catch null) |disk| {
for (disk.folders) |folder| {
// A folder on a mount (`gdrive://…`) is not the disk's to check: it exists
// whenever its plugin is signed in, which is decided at open time.
Expand Down
2 changes: 1 addition & 1 deletion app/Secrets.zig
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn save(self: *Secrets) !void {
const tmp = try std.fmt.allocPrint(self.gpa, "{s}.tmp", .{self.path});
defer self.gpa.free(tmp);
{
var file = try std.Io.Dir.createFileAbsolute(self.io, tmp, .{ .permissions = @enumFromInt(0o600), .truncate = true });
var file = try std.Io.Dir.createFileAbsolute(self.io, tmp, .{ .permissions = @fromBackingInt(@intCast(0o600)), .truncate = true });
defer file.close(self.io);
try file.writeStreamingAll(self.io, out.written());
}
Expand Down
14 changes: 7 additions & 7 deletions app/automation/Service.zig
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ fn playFor(self: *Service, bytes: []const u8, author: ?sdk.Author) Api.Play {
else => .{ .invalid = @errorName(err) },
};
if (self.current) |t| self.remember(.{ .ticket = t, .outcome = last });
const ticket: Api.Ticket = @enumFromInt(self.next);
const ticket: Api.Ticket = @fromBackingInt(@intCast(self.next));
self.next += 1;
self.current = ticket;
return .{ .started = ticket };
Expand Down Expand Up @@ -170,22 +170,22 @@ pub fn frameEnded(self: *Service, end_micros: ?u32) bool {
}

fn snapshot(ctx: *anyopaque) Api.SnapshotTicket {
const s = from(ctx).snapshots orelse return @enumFromInt(0);
return @enumFromInt(s.request());
const s = from(ctx).snapshots orelse return @fromBackingInt(@intCast(0));
return @fromBackingInt(@intCast(s.request()));
}

fn snapshotText(ctx: *anyopaque, ticket: Api.SnapshotTicket) ?[]const u8 {
const s = from(ctx).snapshots orelse return null;
return s.get(@intFromEnum(ticket));
return s.get(@backingInt(ticket));
}

fn capture(ctx: *anyopaque, window: []const u8) Api.CaptureTicket {
const c = from(ctx).captures orelse return @enumFromInt(0);
return @enumFromInt(c.request(window));
const c = from(ctx).captures orelse return @fromBackingInt(@intCast(0));
return @fromBackingInt(@intCast(c.request(window)));
}

fn captureImage(ctx: *anyopaque, ticket: Api.CaptureTicket) ?Api.Image {
const c = from(ctx).captures orelse return null;
const image = c.get(@intFromEnum(ticket)) orelse return null;
const image = c.get(@backingInt(ticket)) orelse return null;
return .{ .pixels = image.pixels, .width = image.width, .height = image.height };
}
28 changes: 14 additions & 14 deletions app/automation/overlay.zig
Original file line number Diff line number Diff line change
Expand Up @@ -634,12 +634,12 @@ fn drawTransport(player: *Player, tape: *const Tape, win: dvui.Rect) f32 {

var phys: [5]dvui.Rect.Physical = undefined;
for (pieces, &phys) |r, *out| out.* = wrs.rectToPhysical(r);
tr.prev = phys[@intFromEnum(Piece.prev)];
tr.play = phys[@intFromEnum(Piece.play)];
tr.next = phys[@intFromEnum(Piece.next)];
tr.close = phys[@intFromEnum(Piece.close)];
tr.prev = phys[@backingInt(Piece.prev)];
tr.play = phys[@backingInt(Piece.play)];
tr.next = phys[@backingInt(Piece.next)];
tr.close = phys[@backingInt(Piece.close)];
const hovered: ?Piece = if (tr.pointer) |pt| for (phys, 0..) |r, i| {
if (i != @intFromEnum(Piece.track) and r.contains(pt)) break @enumFromInt(i);
if (i != @backingInt(Piece.track) and r.contains(pt)) break @fromBackingInt(@intCast(i));
} else null else null;

barGlass(fw.data().id, &phys, s, hovered, apart);
Expand All @@ -650,11 +650,11 @@ fn drawTransport(player: *Player, tape: *const Tape, win: dvui.Rect) f32 {
const ink = theme().color(.content, .text);
const playing = player.state == .playing or (player.state == .seeking and player.after_seek == .play);
const play_glyph: Glyph = if (playing) .pause else if (player.state == .ended) .replay else .play;
barIcon(bounds, pieces[@intFromEnum(Piece.prev)], .prev, ink.opacity(0.8));
barIcon(bounds, pieces[@intFromEnum(Piece.play)], play_glyph, ink);
barIcon(bounds, pieces[@intFromEnum(Piece.next)], .next, ink.opacity(0.8));
barIcon(bounds, pieces[@intFromEnum(Piece.close)], .close, ink.opacity(0.65));
tr.track = barTrack(player, tape, bounds, pieces[@intFromEnum(Piece.track)], ink);
barIcon(bounds, pieces[@backingInt(Piece.prev)], .prev, ink.opacity(0.8));
barIcon(bounds, pieces[@backingInt(Piece.play)], play_glyph, ink);
barIcon(bounds, pieces[@backingInt(Piece.next)], .next, ink.opacity(0.8));
barIcon(bounds, pieces[@backingInt(Piece.close)], .close, ink.opacity(0.65));
tr.track = barTrack(player, tape, bounds, pieces[@backingInt(Piece.track)], ink);
return std.math.clamp(p * 1.6, 0, 1);
}

Expand All @@ -671,9 +671,9 @@ fn barGeometry(center: dvui.Point, full_w: f32, p: f32, out: *[5]dvui.Rect) f32
var widths = piece_d;
var round_w: f32 = 0;
for (piece_d, 0..) |d, i| {
if (i != @intFromEnum(Piece.track)) round_w += d;
if (i != @backingInt(Piece.track)) round_w += d;
}
widths[@intFromEnum(Piece.track)] = @max(80, full_w - round_w - 4 * bar_gap);
widths[@backingInt(Piece.track)] = @max(80, full_w - round_w - 4 * bar_gap);
const gap = bar_gap * apart;
var total: f32 = 4 * gap;
for (widths) |w| total += w;
Expand All @@ -694,7 +694,7 @@ fn barGlass(id: dvui.Id, pieces: []const dvui.Rect.Physical, s: f32, hovered: ?P
var bubbles: [5]core.dialogs.Bubble = undefined;
for (pieces, bubbles[0..pieces.len], 0..) |r, *b, i| b.* = .{
.rect = r,
.light = if (hovered != null and @intFromEnum(hovered.?) == i) core.dialogs.bubble_hover else 0,
.light = if (hovered != null and @backingInt(hovered.?) == i) core.dialogs.bubble_hover else 0,
};
core.dialogs.glassBubbles(id, bubbles[0..pieces.len], s, .{ .merge = bar_merge, .shadow = apart });
}
Expand All @@ -715,7 +715,7 @@ fn barIcon(bounds: dvui.Rect, r: dvui.Rect, glyph: Glyph, color: dvui.Color) voi
.stroke_color = .{ .color = color },
.fill_color = .{ .color = color },
}, .{
.id_extra = @intFromEnum(glyph),
.id_extra = @backingInt(glyph),
.rect = .{ .x = r.x + (r.w - d) / 2 - bounds.x, .y = r.y + (r.h - d) / 2 - bounds.y, .w = d, .h = d },
});
}
Expand Down
18 changes: 9 additions & 9 deletions app/control/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub const keep_alive_ms = 15_000;
/// The longest socket path the OS takes, without its terminating zero. std's
/// `UnixAddress.max_len` says 108 everywhere but Windows, where Darwin's `sockaddr_un` holds 104:
/// a path between them passes `UnixAddress.init` and then overruns the copy in `listen`.
pub const max_path = if (builtin.os.tag == .windows) 107 else @sizeOf(std.posix.sockaddr.un) - @offsetOf(std.posix.sockaddr.un, "path") - 1;
pub const max_path = if (builtin.target.os.tag == .windows) 107 else @sizeOf(std.posix.sockaddr.un) - @offsetOf(std.posix.sockaddr.un, "path") - 1;

/// Where an app whose config folder is `config_folder` listens: `control/control.sock` in it, a folder
/// of its own only this user can open (`start` makes it). When that is longer than the OS takes
Expand Down Expand Up @@ -188,7 +188,7 @@ pub fn start(self: *Server) !void {
// target may be a folder shared with others, which the mode would then be set on.
if (std.fs.path.dirname(self.socket_path)) |dir| {
try Io.Dir.cwd().createDirPath(self.io, dir);
if (comptime builtin.os.tag != .windows) {
if (comptime builtin.target.os.tag != .windows) {
const st = try Io.Dir.cwd().statFile(self.io, dir, .{ .follow_symlinks = false });
if (st.kind != .directory) return error.NotAFolder;
try Io.Dir.cwd().setFilePermissions(self.io, dir, .fromMode(0o700), .{ .follow_symlinks = false });
Expand All @@ -203,7 +203,7 @@ pub fn start(self: *Server) !void {
self.listener = null;
Io.Dir.deleteFileAbsolute(self.io, self.socket_path) catch {};
}
if (comptime builtin.os.tag != .windows) {
if (comptime builtin.target.os.tag != .windows) {
// This user only. The umask usually says so already; a shared machine's may not.
try Io.Dir.cwd().setFilePermissions(self.io, self.socket_path, .fromMode(0o600), .{});
// Not on Windows, where the socket is a reparse point `statFile` cannot open: there this
Expand Down Expand Up @@ -545,7 +545,7 @@ const TestClient = struct {
}
const head = self.reply[0..self.reply_len];
const key = "content-length: ";
if (std.ascii.indexOfIgnoreCase(head, key)) |i| {
if (std.ascii.findIgnoreCase(head, key)) |i| {
const end = std.mem.indexOfPos(u8, head, i, "\r\n") orelse return;
const len = std.fmt.parseInt(usize, head[i + key.len .. end], 10) catch return;
const want = @min(len, self.reply.len - self.reply_len);
Expand Down Expand Up @@ -604,7 +604,7 @@ test "a request reaches the UI thread and its answer goes back" {
try std.testing.expect(std.mem.endsWith(u8, reply, "\r\n\r\n{\"ok\":true}"));

// Only this user may open it.
if (builtin.os.tag == .windows) return;
if (builtin.target.os.tag == .windows) return;
const st = try Io.Dir.cwd().statFile(io, path, .{});
try std.testing.expectEqual(@as(std.posix.mode_t, 0o600), st.permissions.toMode() & 0o777);
// And its folder: nobody else reaches it, even before the socket's own mode is set.
Expand Down Expand Up @@ -688,7 +688,7 @@ test "a config folder too deep for a socket path listens in a runtime folder ins
defer gpa.free(want);
try std.testing.expectEqualStrings(want, short);
// Between Darwin's 104 and std's 108, the length that crashed `listen`: not used as it is.
const deep = "/" ++ "d" ** (max_path - "/control/control.sock".len + 2);
const deep = "/" ++ @as([max_path - "/control/control.sock".len + 2]u8, @splat('d'));
const fallback = try socketPath(gpa, deep, "/tmp/me");
defer gpa.free(fallback);
try std.testing.expect(fallback.len <= max_path);
Expand All @@ -704,7 +704,7 @@ test "a config folder too deep for a socket path listens in a runtime folder ins
test "a socket path the OS cannot hold fails at start, not later" {
if (!Io.net.has_unix_sockets) return error.SkipZigTest;
// Longer than the OS takes but within std's limit: refused here, not overrun in `listen`.
const long = "/" ++ "d" ** max_path;
const long = "/" ++ @as([max_path]u8, @splat('d'));
var server: Server = .{ .gpa = std.testing.allocator, .io = std.testing.io, .socket_path = long, .wake = noWake };
try std.testing.expectError(error.NameTooLong, server.start());
}
Expand Down Expand Up @@ -854,7 +854,7 @@ test "a client that stops reading neither holds up the quit nor buffers without
try answerStreams(&server, 1);
// Until its task blocks writing and the backlog passes the cap; how much the socket takes first
// is the OS's (Windows grows its buffers), so publish until then, up to far more than any.
const chunk = "\"" ++ "x" ** (64 * 1024) ++ "\"";
const chunk = "\"" ++ @as([64 * 1024]u8, @splat('x')) ++ "\"";
var published: usize = 0;
while (!overrun(&server) and published < 256 * 1024 * 1024) : (published += chunk.len) server.publish("e", chunk);
try std.testing.expect(overrun(&server));
Expand Down Expand Up @@ -895,7 +895,7 @@ test "a stopped server ends a stream whose client stopped reading" {
}
try answerStreams(&server, 1);
// Enough to block its write, not enough to overrun.
const chunk = "\"" ++ "x" ** (64 * 1024) ++ "\"";
const chunk = "\"" ++ @as([64 * 1024]u8, @splat('x')) ++ "\"";
for (0..16) |_| server.publish("e", chunk);
io.sleep(.fromMilliseconds(50), .awake) catch {};
// Returns: the stream's socket is shut down under its blocked write.
Expand Down
11 changes: 6 additions & 5 deletions app/control/json.zig
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ fn writeZon(w: *std.Io.Writer, value: std.json.Value) std.Io.Writer.Error!void {
pub fn jsonFromZon(arena: std.mem.Allocator, zon: ?[]const u8) Error![]u8 {
const text = zon orelse return arena.dupe(u8, "null");
if (std.mem.trim(u8, text, " \t\r\n").len == 0) return arena.dupe(u8, "null");
const source = try arena.dupeZ(u8, text);
const ast = try std.zig.Ast.parse(arena, source, .zon);
const source = try arena.dupeSentinel(u8, text, 0);
const ast = try std.zig.Ast.parse(arena, source, .{ .mode = .zon });
if (ast.errors.len > 0) return error.NotZon;
const zoir = try std.zig.ZonGen.generate(arena, ast, .{ .parse_str_lits = true });
if (zoir.hasCompileErrors()) return error.NotZon;
var out: std.Io.Writer.Allocating = .init(arena);
writeJson(&out.writer, zoir, .root) catch |err| return switch (err) {
writeJson(&out.writer, &zoir, .root) catch |err| return switch (err) {
error.NotUtf8 => error.NotUtf8,
error.WriteFailed => error.OutOfMemory,
};
Expand All @@ -91,7 +91,7 @@ fn writeString(w: *std.Io.Writer, s: []const u8) (std.Io.Writer.Error || error{N
try std.json.Stringify.encodeJsonString(s, .{}, w);
}

fn writeJson(w: *std.Io.Writer, zoir: std.zig.Zoir, index: std.zig.Zoir.Node.Index) (std.Io.Writer.Error || error{NotUtf8})!void {
fn writeJson(w: *std.Io.Writer, zoir: *const std.zig.Zoir, index: std.zig.Zoir.Node.Index) (std.Io.Writer.Error || error{NotUtf8})!void {
switch (index.get(zoir)) {
.true => try w.writeAll("true"),
.false => try w.writeAll("false"),
Expand Down Expand Up @@ -152,7 +152,8 @@ test "arguments: JSON object to a ZON struct literal" {
// Negative zero as ZON reads it.
const neg = try zonFromJson(a, "{\"x\":-0.0}", &.{});
try std.testing.expectEqualStrings(".{.x=-0.0}", neg);
_ = try std.zon.parse.fromSliceAlloc(struct { x: f64 }, a, try a.dupeZ(u8, neg), null, .{});
var diag: std.zon.parse.Diagnostics = undefined;
_ = try std.zon.parse.fromSlice(struct { x: f64 }, .{ .gpa = a, .arena = a, .source = try a.dupeSentinel(u8, neg, 0), .diagnostics = &diag });
try std.testing.expectError(error.NotAnObject, zonFromJson(a, "[1]", &.{}));
}

Expand Down
2 changes: 1 addition & 1 deletion app/crash/crash.zig
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ pub fn writeTo(io: std.Io, config_folder: []const u8) void {
const pid = if (builtin.target.os.tag == .windows) win.GetCurrentProcessId() else std.c.getpid();
const launched = std.Io.Timestamp.now(io, .real).toMilliseconds();
const sep = std.fs.path.sep;
const path = std.fmt.bufPrintZ(&path_buf, "{s}{c}crashes{c}{d}-{d}.txt", .{ config_folder, sep, sep, launched, pid }) catch return;
const path = std.fmt.bufPrintSentinel(&path_buf, "{s}{c}crashes{c}{d}-{d}.txt", .{ config_folder, sep, sep, launched, pid }, 0) catch return;
const dir = std.fs.path.dirname(path).?;
std.Io.Dir.cwd().createDirPath(io, dir) catch |err| {
std.log.warn("crash reports: can't create {s}: {t}", .{ dir, err });
Expand Down
Loading
Loading