From 68671a1af1e8fbe7e0fd8617533083bc330c52d6 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Tue, 19 Aug 2025 12:53:09 +0200 Subject: [PATCH] Zig 0.15: Migrate all ArrayLists to the Unmanaged API Managed ArrayLists are deprecated in 0.15. "ArrayList" in 0.15 is the same as "ArrayListUnmanaged" in 0.14. The latter alias is still available in 0.15, so let's stick with that for now. When dropping support for 0.14, we can do s/ArrayListUnmanaged/ArrayList/. --- src/bin_export.zig | 22 +++++++++++----------- src/browser.zig | 28 ++++++++++++++-------------- src/delete.zig | 38 +++++++++++++++++++------------------- src/exclude.zig | 2 +- src/main.zig | 9 ++++----- src/mem_src.zig | 6 +++--- src/model.zig | 27 ++++++++++++++------------- src/scan.zig | 8 ++++---- src/sink.zig | 15 ++++++++------- src/ui.zig | 18 +++++++++--------- src/util.zig | 4 ++-- 11 files changed, 89 insertions(+), 88 deletions(-) diff --git a/src/bin_export.zig b/src/bin_export.zig index ca60bcf..a10128b 100644 --- a/src/bin_export.zig +++ b/src/bin_export.zig @@ -11,7 +11,7 @@ const c = @import("c.zig").c; pub const global = struct { var fd: std.fs.File = undefined; - var index = std.ArrayList(u8).init(main.allocator); + var index: std.ArrayListUnmanaged(u8) = .empty; var file_off: u64 = 0; var lock: std.Thread.Mutex = .{}; var root_itemref: u64 = 0; @@ -105,11 +105,11 @@ pub const Thread = struct { } } - fn createBlock(t: *Thread) std.ArrayList(u8) { - var out = std.ArrayList(u8).init(main.allocator); + fn createBlock(t: *Thread) std.ArrayListUnmanaged(u8) { + var out: std.ArrayListUnmanaged(u8) = .empty; if (t.block_num == std.math.maxInt(u32) or t.off == 0) return out; - out.ensureTotalCapacityPrecise(12 + @as(usize, @intCast(c.ZSTD_COMPRESSBOUND(@as(c_int, @intCast(t.off)))))) catch unreachable; + out.ensureTotalCapacityPrecise(main.allocator, 12 + @as(usize, @intCast(c.ZSTD_COMPRESSBOUND(@as(c_int, @intCast(t.off)))))) catch unreachable; out.items.len = out.capacity; const bodylen = compressZstd(t.buf[0..t.off], out.items[8..]); out.items.len = 12 + bodylen; @@ -122,8 +122,8 @@ pub const Thread = struct { fn flush(t: *Thread, expected_len: usize) void { @branchHint(.unlikely); - const block = createBlock(t); - defer block.deinit(); + var block = createBlock(t); + defer block.deinit(main.allocator); global.lock.lock(); defer global.lock.unlock(); @@ -141,7 +141,7 @@ pub const Thread = struct { t.off = 0; t.block_num = @intCast((global.index.items.len - 4) / 8); - global.index.appendSlice(&[1]u8{0}**8) catch unreachable; + global.index.appendSlice(main.allocator, &[1]u8{0}**8) catch unreachable; if (global.index.items.len + 12 >= (1<<28)) ui.die("Too many data blocks, please report a bug.\n", .{}); const newsize = blockSize(t.block_num); @@ -447,12 +447,12 @@ pub fn done(threads: []sink.Thread) void { while (std.mem.endsWith(u8, global.index.items, &[1]u8{0}**8)) global.index.shrinkRetainingCapacity(global.index.items.len - 8); - global.index.appendSlice(&bigu64(global.root_itemref)) catch unreachable; - global.index.appendSlice(&blockHeader(1, @intCast(global.index.items.len + 4))) catch unreachable; + global.index.appendSlice(main.allocator, &bigu64(global.root_itemref)) catch unreachable; + global.index.appendSlice(main.allocator, &blockHeader(1, @intCast(global.index.items.len + 4))) catch unreachable; global.index.items[0..4].* = blockHeader(1, @intCast(global.index.items.len)); global.fd.writeAll(global.index.items) catch |e| ui.die("Error writing to file: {s}.\n", .{ ui.errorString(e) }); - global.index.clearAndFree(); + global.index.clearAndFree(main.allocator); global.fd.close(); } @@ -464,5 +464,5 @@ pub fn setupOutput(fd: std.fs.File) void { global.file_off = 8; // Placeholder for the index block header. - global.index.appendSlice("aaaa") catch unreachable; + global.index.appendSlice(main.allocator, "aaaa") catch unreachable; } diff --git a/src/browser.zig b/src/browser.zig index 4d49663..c664baf 100644 --- a/src/browser.zig +++ b/src/browser.zig @@ -15,16 +15,16 @@ const util = @import("util.zig"); // Currently opened directory. pub var dir_parent: *model.Dir = undefined; pub var dir_path: [:0]u8 = undefined; -var dir_parents = std.ArrayList(model.Ref).init(main.allocator); +var dir_parents: std.ArrayListUnmanaged(model.Ref) = .empty; var dir_alloc = std.heap.ArenaAllocator.init(main.allocator); // Used to keep track of which dir is which ref, so we can enter it. // Only used for binreader browsing. -var dir_refs = std.ArrayList(struct { ptr: *model.Dir, ref: u64 }).init(main.allocator); +var dir_refs: std.ArrayListUnmanaged(struct { ptr: *model.Dir, ref: u64 }) = .empty; // Sorted list of all items in the currently opened directory. // (first item may be null to indicate the "parent directory" item) -var dir_items = std.ArrayList(?*model.Entry).init(main.allocator); +var dir_items: std.ArrayListUnmanaged(?*model.Entry) = .empty; var dir_max_blocks: u64 = 0; var dir_max_size: u64 = 0; @@ -146,7 +146,7 @@ pub fn loadDir(next_sel: u64) void { dir_has_shared = false; if (dir_parents.items.len > 1) - dir_items.append(null) catch unreachable; + dir_items.append(main.allocator, null) catch unreachable; var ref = dir_parent.sub; while (!ref.isNull()) { const e = @@ -164,10 +164,10 @@ pub fn loadDir(next_sel: u64) void { break :blk !excl and name[0] != '.' and name[name.len-1] != '~'; }; if (shown) { - dir_items.append(e) catch unreachable; + dir_items.append(main.allocator, e) catch unreachable; if (e.dir()) |d| { if (d.shared_blocks > 0 or d.shared_size > 0) dir_has_shared = true; - if (main.config.binreader) dir_refs.append(.{ .ptr = d, .ref = ref.ref }) catch unreachable; + if (main.config.binreader) dir_refs.append(main.allocator, .{ .ptr = d, .ref = ref.ref }) catch unreachable; } } @@ -185,10 +185,10 @@ pub fn initRoot() void { if (main.config.binreader) { const ref = bin_reader.getRoot(); dir_parent = bin_reader.get(ref, main.allocator).dir() orelse ui.die("Invalid import\n", .{}); - dir_parents.append(.{ .ref = ref }) catch unreachable; + dir_parents.append(main.allocator, .{ .ref = ref }) catch unreachable; } else { dir_parent = model.root; - dir_parents.append(.{ .ptr = &dir_parent.entry }) catch unreachable; + dir_parents.append(main.allocator, .{ .ptr = &dir_parent.entry }) catch unreachable; } dir_path = main.allocator.dupeZ(u8, dir_parent.entry.name()) catch unreachable; loadDir(0); @@ -202,10 +202,10 @@ fn enterSub(e: *model.Dir) void { }; dir_parent.entry.destroy(main.allocator); dir_parent = bin_reader.get(ref, main.allocator).dir() orelse unreachable; - dir_parents.append(.{ .ref = ref }) catch unreachable; + dir_parents.append(main.allocator, .{ .ref = ref }) catch unreachable; } else { dir_parent = e; - dir_parents.append(.{ .ptr = &e.entry }) catch unreachable; + dir_parents.append(main.allocator, .{ .ptr = &e.entry }) catch unreachable; } const newpath = std.fs.path.joinZ(main.allocator, &[_][]const u8{ dir_path, e.entry.name() }) catch unreachable; @@ -430,7 +430,7 @@ const info = struct { var tab: Tab = .info; var entry: ?*model.Entry = null; - var links: ?std.ArrayList(*model.Link) = null; + var links: ?std.ArrayListUnmanaged(*model.Link) = null; var links_top: usize = 0; var links_idx: usize = 0; @@ -445,7 +445,7 @@ const info = struct { // Set the displayed entry to the currently selected item and open the tab. fn set(e: ?*model.Entry, t: Tab) void { if (e != entry) { - if (links) |*l| l.deinit(); + if (links) |*l| l.deinit(main.allocator); links = null; links_top = 0; links_idx = 0; @@ -458,10 +458,10 @@ const info = struct { state = .info; tab = t; if (tab == .links and links == null and !main.config.binreader) { - var list = std.ArrayList(*model.Link).init(main.allocator); + var list: std.ArrayListUnmanaged(*model.Link) = .empty; var l = e.?.link().?; while (true) { - list.append(l) catch unreachable; + list.append(main.allocator, l) catch unreachable; l = l.next; if (&l.entry == e) break; diff --git a/src/delete.zig b/src/delete.zig index 896c2a4..5d4d4af 100644 --- a/src/delete.zig +++ b/src/delete.zig @@ -136,19 +136,19 @@ pub fn delete() ?*model.Entry { if (it.* == entry) break; - var path = std.ArrayList(u8).init(main.allocator); - defer path.deinit(); - parent.fmtPath(true, &path); + var path: std.ArrayListUnmanaged(u8) = .empty; + defer path.deinit(main.allocator); + parent.fmtPath(main.allocator, true, &path); if (path.items.len == 0 or path.items[path.items.len-1] != '/') - path.append('/') catch unreachable; - path.appendSlice(entry.name()) catch unreachable; + path.append(main.allocator, '/') catch unreachable; + path.appendSlice(main.allocator, entry.name()) catch unreachable; if (main.config.delete_command.len == 0) { - _ = deleteItem(std.fs.cwd(), util.arrayListBufZ(&path), it); + _ = deleteItem(std.fs.cwd(), util.arrayListBufZ(&path, main.allocator), it); model.inodes.addAllStats(); return if (it.* == e) e else next_sel; } else { - const isdel = deleteCmd(util.arrayListBufZ(&path), it); + const isdel = deleteCmd(util.arrayListBufZ(&path, main.allocator), it); model.inodes.addAllStats(); return if (isdel) next_sel else it.*; } @@ -197,17 +197,17 @@ fn drawConfirm() void { } fn drawProgress() void { - var path = std.ArrayList(u8).init(main.allocator); - defer path.deinit(); - parent.fmtPath(false, &path); - path.append('/') catch unreachable; - path.appendSlice(entry.name()) catch unreachable; + var path: std.ArrayListUnmanaged(u8) = .empty; + defer path.deinit(main.allocator); + parent.fmtPath(main.allocator, false, &path); + path.append(main.allocator, '/') catch unreachable; + path.appendSlice(main.allocator, entry.name()) catch unreachable; // TODO: Item counts and progress bar would be nice. const box = ui.Box.create(6, 60, "Deleting..."); box.move(2, 2); - ui.addstr(ui.shorten(ui.toUtf8(util.arrayListBufZ(&path)), 56)); + ui.addstr(ui.shorten(ui.toUtf8(util.arrayListBufZ(&path, main.allocator)), 56)); box.move(4, 41); ui.addstr("Press "); ui.style(.key); @@ -217,16 +217,16 @@ fn drawProgress() void { } fn drawErr() void { - var path = std.ArrayList(u8).init(main.allocator); - defer path.deinit(); - parent.fmtPath(false, &path); - path.append('/') catch unreachable; - path.appendSlice(entry.name()) catch unreachable; + var path: std.ArrayListUnmanaged(u8) = .empty; + defer path.deinit(main.allocator); + parent.fmtPath(main.allocator, false, &path); + path.append(main.allocator, '/') catch unreachable; + path.appendSlice(main.allocator, entry.name()) catch unreachable; const box = ui.Box.create(6, 60, "Error"); box.move(1, 2); ui.addstr("Error deleting "); - ui.addstr(ui.shorten(ui.toUtf8(util.arrayListBufZ(&path)), 41)); + ui.addstr(ui.shorten(ui.toUtf8(util.arrayListBufZ(&path, main.allocator)), 41)); box.move(2, 4); ui.addstr(ui.errorString(error_code)); diff --git a/src/exclude.zig b/src/exclude.zig index d90611d..2376640 100644 --- a/src/exclude.zig +++ b/src/exclude.zig @@ -123,7 +123,7 @@ test "parse" { fn PatternList(comptime withsub: bool) type { return struct { literals: std.HashMapUnmanaged(*const Pattern, Val, Ctx, 80) = .{}, - wild: std.ArrayListUnmanaged(*const Pattern) = .{}, + wild: std.ArrayListUnmanaged(*const Pattern) = .empty, // Not a fan of the map-of-arrays approach in the 'withsub' case, it // has a lot of extra allocations. Linking the Patterns together in a diff --git a/src/main.zig b/src/main.zig index 3eb7264..53d4832 100644 --- a/src/main.zig +++ b/src/main.zig @@ -80,7 +80,6 @@ pub const config = struct { pub var follow_symlinks: bool = false; pub var exclude_caches: bool = false; pub var exclude_kernfs: bool = false; - pub var exclude_patterns: std.ArrayList([:0]const u8) = std.ArrayList([:0]const u8).init(allocator); pub var threads: usize = 1; pub var complevel: u8 = 4; pub var compress: bool = false; @@ -610,10 +609,10 @@ pub fn main() void { while (true) { switch (state) { .refresh => { - var full_path = std.ArrayList(u8).init(allocator); - defer full_path.deinit(); - mem_sink.global.root.?.fmtPath(true, &full_path); - scan.scan(util.arrayListBufZ(&full_path)) catch { + var full_path: std.ArrayListUnmanaged(u8) = .empty; + defer full_path.deinit(allocator); + mem_sink.global.root.?.fmtPath(allocator, true, &full_path); + scan.scan(util.arrayListBufZ(&full_path, allocator)) catch { sink.global.last_error = allocator.dupeZ(u8, full_path.items) catch unreachable; sink.global.state = .err; while (state == .refresh) handleEvent(true, true); diff --git a/src/mem_src.zig b/src/mem_src.zig index d9ddb29..5e85f6d 100644 --- a/src/mem_src.zig +++ b/src/mem_src.zig @@ -60,10 +60,10 @@ pub fn run(d: *model.Dir) void { .sink = &sink_threads[0], .stat = toStat(&d.entry), }; - var buf = std.ArrayList(u8).init(main.allocator); - d.fmtPath(true, &buf); + var buf: std.ArrayListUnmanaged(u8) = .empty; + d.fmtPath(main.allocator, true, &buf); const root = sink.createRoot(buf.items, &ctx.stat); - buf.deinit(); + buf.deinit(main.allocator); var it = d.sub.ptr; while (it) |e| : (it = e.next.ptr) rec(&ctx, root, e); diff --git a/src/model.zig b/src/model.zig index 6bbd433..834dee5 100644 --- a/src/model.zig +++ b/src/model.zig @@ -217,19 +217,20 @@ pub const Dir = extern struct { suberr: bool = false, }; - pub fn fmtPath(self: *const @This(), withRoot: bool, out: *std.ArrayList(u8)) void { + pub fn fmtPath(self: *const @This(), alloc: std.mem.Allocator, withRoot: bool, out: *std.ArrayListUnmanaged(u8)) void { if (!withRoot and self.parent == null) return; - var components = std.ArrayList([:0]const u8).init(main.allocator); - defer components.deinit(); + var components: std.ArrayListUnmanaged([:0]const u8) = .empty; + defer components.deinit(main.allocator); var it: ?*const @This() = self; while (it) |e| : (it = e.parent) if (withRoot or e.parent != null) - components.append(e.entry.name()) catch unreachable; + components.append(main.allocator, e.entry.name()) catch unreachable; var i: usize = components.items.len-1; while (true) { - if (i != components.items.len-1 and !(out.items.len != 0 and out.items[out.items.len-1] == '/')) out.append('/') catch unreachable; - out.appendSlice(components.items[i]) catch unreachable; + if (i != components.items.len-1 and !(out.items.len != 0 and out.items[out.items.len-1] == '/')) + out.append(main.allocator, '/') catch unreachable; + out.appendSlice(alloc, components.items[i]) catch unreachable; if (i == 0) break; i -= 1; } @@ -271,11 +272,11 @@ pub const Link = extern struct { // Return value should be freed with main.allocator. pub fn path(self: *const @This(), withRoot: bool) [:0]const u8 { - var out = std.ArrayList(u8).init(main.allocator); - self.parent.fmtPath(withRoot, &out); - out.append('/') catch unreachable; - out.appendSlice(self.entry.name()) catch unreachable; - return out.toOwnedSliceSentinel(0) catch unreachable; + var out: std.ArrayListUnmanaged(u8) = .empty; + self.parent.fmtPath(main.allocator, withRoot, &out); + out.append(main.allocator, '/') catch unreachable; + out.appendSlice(main.allocator, self.entry.name()) catch unreachable; + return out.toOwnedSliceSentinel(main.allocator, 0) catch unreachable; } // Add this link to the inodes map and mark it as 'uncounted'. @@ -350,7 +351,7 @@ pub const Ext = extern struct { pub const devices = struct { var lock = std.Thread.Mutex{}; // id -> dev - pub var list = std.ArrayList(u64).init(main.allocator); + pub var list: std.ArrayListUnmanaged(u64) = .empty; // dev -> id var lookup = std.AutoHashMap(u64, DevId).init(main.allocator); @@ -361,7 +362,7 @@ pub const devices = struct { if (!d.found_existing) { if (list.items.len >= std.math.maxInt(DevId)) ui.die("Maximum number of device identifiers exceeded.\n", .{}); d.value_ptr.* = @as(DevId, @intCast(list.items.len)); - list.append(dev) catch unreachable; + list.append(main.allocator, dev) catch unreachable; } return d.value_ptr.*; } diff --git a/src/scan.zig b/src/scan.zig index a284191..476dbf6 100644 --- a/src/scan.zig +++ b/src/scan.zig @@ -184,7 +184,7 @@ const Thread = struct { thread_num: usize, sink: *sink.Thread, state: *State, - stack: std.ArrayList(*Dir) = std.ArrayList(*Dir).init(main.allocator), + stack: std.ArrayListUnmanaged(*Dir) = .empty, thread: std.Thread = undefined, namebuf: [4096]u8 = undefined, @@ -265,13 +265,13 @@ const Thread = struct { const s = dir.sink.addDir(t.sink, name, &stat); const ndir = Dir.create(edir, stat.dev, dir.pat.enter(name), s); if (main.config.threads == 1 or !t.state.tryPush(ndir)) - t.stack.append(ndir) catch unreachable; + t.stack.append(main.allocator, ndir) catch unreachable; } fn run(t: *Thread) void { - defer t.stack.deinit(); + defer t.stack.deinit(main.allocator); while (t.state.waitPop()) |dir| { - t.stack.append(dir) catch unreachable; + t.stack.append(main.allocator, dir) catch unreachable; while (t.stack.items.len > 0) { const d = t.stack.items[t.stack.items.len - 1]; diff --git a/src/sink.zig b/src/sink.zig index 15adb8c..50a5ecf 100644 --- a/src/sink.zig +++ b/src/sink.zig @@ -140,20 +140,21 @@ pub const Dir = struct { } fn path(d: *Dir) [:0]u8 { - var components = std.ArrayList([]const u8).init(main.allocator); - defer components.deinit(); + var components: std.ArrayListUnmanaged([]const u8) = .empty; + defer components.deinit(main.allocator); var it: ?*Dir = d; - while (it) |e| : (it = e.parent) components.append(e.name) catch unreachable; + while (it) |e| : (it = e.parent) components.append(main.allocator, e.name) catch unreachable; - var out = std.ArrayList(u8).init(main.allocator); + var out: std.ArrayListUnmanaged(u8) = .empty; var i: usize = components.items.len-1; while (true) { - if (i != components.items.len-1 and !(out.items.len != 0 and out.items[out.items.len-1] == '/')) out.append('/') catch unreachable; - out.appendSlice(components.items[i]) catch unreachable; + if (i != components.items.len-1 and !(out.items.len != 0 and out.items[out.items.len-1] == '/')) + out.append(main.allocator, '/') catch unreachable; + out.appendSlice(main.allocator, components.items[i]) catch unreachable; if (i == 0) break; i -= 1; } - return out.toOwnedSliceSentinel(0) catch unreachable; + return out.toOwnedSliceSentinel(main.allocator, 0) catch unreachable; } fn ref(d: *Dir) void { diff --git a/src/ui.zig b/src/ui.zig index de2f9a9..07713b2 100644 --- a/src/ui.zig +++ b/src/ui.zig @@ -80,7 +80,7 @@ pub fn errorString(e: anyerror) [:0]const u8 { }; } -var to_utf8_buf = std.ArrayList(u8).init(main.allocator); +var to_utf8_buf: std.ArrayListUnmanaged(u8) = .empty; fn toUtf8BadChar(ch: u8) bool { return switch (ch) { @@ -107,19 +107,19 @@ pub fn toUtf8(in: [:0]const u8) [:0]const u8 { if (std.unicode.utf8ByteSequenceLength(in[i])) |cp_len| { if (!toUtf8BadChar(in[i]) and i + cp_len <= in.len) { if (std.unicode.utf8Decode(in[i .. i + cp_len])) |_| { - to_utf8_buf.appendSlice(in[i .. i + cp_len]) catch unreachable; + to_utf8_buf.appendSlice(main.allocator, in[i .. i + cp_len]) catch unreachable; i += cp_len; continue; } else |_| {} } } else |_| {} - to_utf8_buf.writer().print("\\x{X:0>2}", .{in[i]}) catch unreachable; + to_utf8_buf.writer(main.allocator).print("\\x{X:0>2}", .{in[i]}) catch unreachable; i += 1; } - return util.arrayListBufZ(&to_utf8_buf); + return util.arrayListBufZ(&to_utf8_buf, main.allocator); } -var shorten_buf = std.ArrayList(u8).init(main.allocator); +var shorten_buf: std.ArrayListUnmanaged(u8) = .empty; // Shorten the given string to fit in the given number of columns. // If the string is too long, only the prefix and suffix will be printed, with '...' in between. @@ -150,8 +150,8 @@ pub fn shorten(in: [:0]const u8, max_width: u32) [:0] const u8 { if (total_width <= max_width) return in; shorten_buf.shrinkRetainingCapacity(0); - shorten_buf.appendSlice(in[0..prefix_end]) catch unreachable; - shorten_buf.appendSlice("...") catch unreachable; + shorten_buf.appendSlice(main.allocator, in[0..prefix_end]) catch unreachable; + shorten_buf.appendSlice(main.allocator, "...") catch unreachable; var start_width: u32 = prefix_width; var start_len: u32 = prefix_end; @@ -163,11 +163,11 @@ pub fn shorten(in: [:0]const u8, max_width: u32) [:0] const u8 { start_width += cp_width; start_len += cp_len; if (total_width - start_width <= max_width - prefix_width - 3) { - shorten_buf.appendSlice(in[start_len..]) catch unreachable; + shorten_buf.appendSlice(main.allocator, in[start_len..]) catch unreachable; break; } } - return util.arrayListBufZ(&shorten_buf); + return util.arrayListBufZ(&shorten_buf, main.allocator); } fn shortenTest(in: [:0]const u8, max_width: u32, out: [:0]const u8) !void { diff --git a/src/util.zig b/src/util.zig index 77ee73b..96b0512 100644 --- a/src/util.zig +++ b/src/util.zig @@ -32,8 +32,8 @@ pub fn blocksToSize(b: u64) u64 { // Ensure the given arraylist buffer gets zero-terminated and returns a slice // into the buffer. The returned buffer is invalidated whenever the arraylist // is freed or written to. -pub fn arrayListBufZ(buf: *std.ArrayList(u8)) [:0]const u8 { - buf.append(0) catch unreachable; +pub fn arrayListBufZ(buf: *std.ArrayListUnmanaged(u8), alloc: std.mem.Allocator) [:0]const u8 { + buf.append(alloc, 0) catch unreachable; defer buf.items.len -= 1; return buf.items[0..buf.items.len-1:0]; }