authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 18:57:34+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 18:57:34+02:00
logc79058895bce4ccacbe9f018404dd715e4cf2778
tree08b02b178f2b62831c51673011a009cde894c9ac
parentd1f80fe1063ab9ef28d527e27d2f19b23ea06bc3
parent6fbb5ad328d180f6d397d0d64feb599a6570914b

Merge pull request 'std.json: update usages of array_list.Managed to ArrayList' (#37291) from mcrtin/array-list-unmanaged into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37291 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

4 files changed, 50 insertions(+), 58 deletions(-)

lib/std/json/Scanner.zig+34-30
......@@ -135,11 +135,10 @@ pub fn nextAllocMax(self: *@This(), allocator: Allocator, when: AllocWhen, max_v
135135 };
136136 switch (token_type) {
137137 .number, .string => {
138 var value_list = std.array_list.Managed(u8).init(allocator);
139 errdefer {
140 value_list.deinit();
141 }
142 if (self.allocNextIntoArrayListMax(&value_list, when, max_value_len) catch |e| switch (e) {
138 var value_list: std.ArrayList(u8) = .empty;
139 defer value_list.deinit(allocator);
140
141 if (self.allocNextIntoArrayListMax(allocator, &value_list, when, max_value_len) catch |e| switch (e) {
143142 error.BufferUnderrun => unreachable,
144143 else => |err| return err,
145144 }) |slice| {
......@@ -149,9 +148,9 @@ pub fn nextAllocMax(self: *@This(), allocator: Allocator, when: AllocWhen, max_v
149148 Token{ .string = slice };
150149 } else {
151150 return if (token_type == .number)
152 Token{ .allocated_number = try value_list.toOwnedSlice() }
151 Token{ .allocated_number = try value_list.toOwnedSlice(allocator) }
153152 else
154 Token{ .allocated_string = try value_list.toOwnedSlice() };
153 Token{ .allocated_string = try value_list.toOwnedSlice(allocator) };
155154 }
156155 },
157156
......@@ -172,8 +171,8 @@ pub fn nextAllocMax(self: *@This(), allocator: Allocator, when: AllocWhen, max_v
172171}
173172
174173/// Equivalent to `allocNextIntoArrayListMax(value_list, when, default_max_value_len);`
175pub fn allocNextIntoArrayList(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen) AllocIntoArrayListError!?[]const u8 {
176 return self.allocNextIntoArrayListMax(value_list, when, default_max_value_len);
174pub fn allocNextIntoArrayList(self: *@This(), allocator: Allocator, value_list: *std.ArrayList(u8), when: AllocWhen) AllocIntoArrayListError!?[]const u8 {
175 return self.allocNextIntoArrayListMax(allocator, value_list, when, default_max_value_len);
177176}
178177/// The next token type must be either `.number` or `.string`. See `peekNextTokenType()`.
179178/// When allocation is not necessary with `.alloc_if_needed`,
......@@ -185,25 +184,25 @@ pub fn allocNextIntoArrayList(self: *@This(), value_list: *std.array_list.Manage
185184/// can be resumed by passing the same array list in again.
186185/// This method does not indicate whether the token content being returned is for a `.number` or `.string` token type;
187186/// the caller of this method is expected to know which type of token is being processed.
188pub fn allocNextIntoArrayListMax(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen, max_value_len: usize) AllocIntoArrayListError!?[]const u8 {
187pub fn allocNextIntoArrayListMax(self: *@This(), allocator: Allocator, value_list: *std.ArrayList(u8), when: AllocWhen, max_value_len: usize) AllocIntoArrayListError!?[]const u8 {
189188 while (true) {
190189 const token = try self.next();
191190 switch (token) {
192191 // Accumulate partial values.
193192 .partial_number, .partial_string => |slice| {
194 try appendSlice(value_list, slice, max_value_len);
193 try appendSlice(allocator, value_list, slice, max_value_len);
195194 },
196195 .partial_string_escaped_1 => |buf| {
197 try appendSlice(value_list, buf[0..], max_value_len);
196 try appendSlice(allocator, value_list, buf[0..], max_value_len);
198197 },
199198 .partial_string_escaped_2 => |buf| {
200 try appendSlice(value_list, buf[0..], max_value_len);
199 try appendSlice(allocator, value_list, buf[0..], max_value_len);
201200 },
202201 .partial_string_escaped_3 => |buf| {
203 try appendSlice(value_list, buf[0..], max_value_len);
202 try appendSlice(allocator, value_list, buf[0..], max_value_len);
204203 },
205204 .partial_string_escaped_4 => |buf| {
206 try appendSlice(value_list, buf[0..], max_value_len);
205 try appendSlice(allocator, value_list, buf[0..], max_value_len);
207206 },
208207
209208 // Return complete values.
......@@ -212,7 +211,7 @@ pub fn allocNextIntoArrayListMax(self: *@This(), value_list: *std.array_list.Man
212211 // No alloc necessary.
213212 return slice;
214213 }
215 try appendSlice(value_list, slice, max_value_len);
214 try appendSlice(allocator, value_list, slice, max_value_len);
216215 // The token is complete.
217216 return null;
218217 },
......@@ -221,7 +220,7 @@ pub fn allocNextIntoArrayListMax(self: *@This(), value_list: *std.array_list.Man
221220 // No alloc necessary.
222221 return slice;
223222 }
224 try appendSlice(value_list, slice, max_value_len);
223 try appendSlice(allocator, value_list, slice, max_value_len);
225224 // The token is complete.
226225 return null;
227226 },
......@@ -1607,20 +1606,19 @@ pub const Reader = struct {
16071606 const token_type = try self.peekNextTokenType();
16081607 switch (token_type) {
16091608 .number, .string => {
1610 var value_list = std.array_list.Managed(u8).init(allocator);
1611 errdefer {
1612 value_list.deinit();
1613 }
1614 if (try self.allocNextIntoArrayListMax(&value_list, when, max_value_len)) |slice| {
1609 var value_list: std.ArrayList(u8) = .empty;
1610 defer value_list.deinit(allocator);
1611
1612 if (try self.allocNextIntoArrayListMax(allocator, &value_list, when, max_value_len)) |slice| {
16151613 return if (token_type == .number)
16161614 Token{ .number = slice }
16171615 else
16181616 Token{ .string = slice };
16191617 } else {
16201618 return if (token_type == .number)
1621 Token{ .allocated_number = try value_list.toOwnedSlice() }
1619 Token{ .allocated_number = try value_list.toOwnedSlice(allocator) }
16221620 else
1623 Token{ .allocated_string = try value_list.toOwnedSlice() };
1621 Token{ .allocated_string = try value_list.toOwnedSlice(allocator) };
16241622 }
16251623 },
16261624
......@@ -1638,13 +1636,19 @@ pub const Reader = struct {
16381636 }
16391637
16401638 /// Equivalent to `allocNextIntoArrayListMax(value_list, when, default_max_value_len);`
1641 pub fn allocNextIntoArrayList(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen) Reader.AllocError!?[]const u8 {
1642 return self.allocNextIntoArrayListMax(value_list, when, default_max_value_len);
1639 pub fn allocNextIntoArrayList(self: *@This(), allocator: Allocator, value_list: *std.ArrayList(u8), when: AllocWhen) Reader.AllocError!?[]const u8 {
1640 return self.allocNextIntoArrayListMax(allocator, value_list, when, default_max_value_len);
16431641 }
16441642 /// Calls `std.json.Scanner.allocNextIntoArrayListMax` and handles `error.BufferUnderrun`.
1645 pub fn allocNextIntoArrayListMax(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen, max_value_len: usize) Reader.AllocError!?[]const u8 {
1643 pub fn allocNextIntoArrayListMax(
1644 self: *@This(),
1645 allocator: Allocator,
1646 value_list: *std.ArrayList(u8),
1647 when: AllocWhen,
1648 max_value_len: usize,
1649 ) Reader.AllocError!?[]const u8 {
16461650 while (true) {
1647 return self.scanner.allocNextIntoArrayListMax(value_list, when, max_value_len) catch |err| switch (err) {
1651 return self.scanner.allocNextIntoArrayListMax(allocator, value_list, when, max_value_len) catch |err| switch (err) {
16481652 error.BufferUnderrun => {
16491653 try self.refillBuffer();
16501654 continue;
......@@ -1745,10 +1749,10 @@ pub const Reader = struct {
17451749const OBJECT_MODE = 0;
17461750const ARRAY_MODE = 1;
17471751
1748fn appendSlice(list: *std.array_list.Managed(u8), buf: []const u8, max_value_len: usize) !void {
1752fn appendSlice(allocator: Allocator, list: *std.ArrayList(u8), buf: []const u8, max_value_len: usize) !void {
17491753 const new_len = std.math.add(usize, list.items.len, buf.len) catch return error.ValueTooLong;
17501754 if (new_len > max_value_len) return error.ValueTooLong;
1751 try list.appendSlice(buf);
1755 try list.appendSlice(allocator, buf);
17521756}
17531757
17541758/// For the slice you get from a `Token.number` or `Token.allocated_number`,
lib/std/json/dynamic.zig+7-7
......@@ -11,7 +11,7 @@ const ParseError = @import("./static.zig").ParseError;
1111const isNumberFormattedLikeAnInteger = @import("Scanner.zig").isNumberFormattedLikeAnInteger;
1212
1313pub const ObjectMap = StringArrayHashMap(Value);
14pub const Array = std.array_list.Managed(Value);
14pub const Array = std.ArrayList(Value);
1515
1616/// Represents any JSON value, potentially containing other JSON values.
1717/// A .float value may be an approximation of the original value.
......@@ -76,8 +76,8 @@ pub const Value = union(enum) {
7676 pub fn jsonParse(allocator: Allocator, source: anytype, options: ParseOptions) ParseError(@TypeOf(source.*))!@This() {
7777 // The grammar of the stack is:
7878 // (.array | .object .string)*
79 var stack = Array.init(allocator);
80 defer stack.deinit();
79 var stack: Array = .empty;
80 defer stack.deinit(allocator);
8181
8282 while (true) {
8383 // Assert the stack grammar at the top of the stack.
......@@ -105,7 +105,7 @@ pub const Value = union(enum) {
105105 switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
106106 .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = .empty }, options) orelse continue,
107107 .allocated_string => |key| {
108 try stack.appendSlice(&[_]Value{
108 try stack.appendSlice(allocator, &[_]Value{
109109 Value{ .object = .empty },
110110 Value{ .string = key },
111111 });
......@@ -114,7 +114,7 @@ pub const Value = union(enum) {
114114 }
115115 },
116116 .array_begin => {
117 try stack.append(Value{ .array = Array.init(allocator) });
117 try stack.append(allocator, Value{ .array = .empty });
118118 },
119119 .array_end => return try handleCompleteValue(&stack, allocator, source, stack.pop().?, options) orelse continue,
120120
......@@ -170,7 +170,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
170170 },
171171 .allocated_string => |next_key| {
172172 // We've got another key.
173 try stack.append(Value{ .string = next_key });
173 try stack.append(allocator, Value{ .string = next_key });
174174 // stack: [..., .object, .string]
175175 return null;
176176 },
......@@ -179,7 +179,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
179179 },
180180 .array => |*array| {
181181 // stack: [..., .array]
182 try array.append(value);
182 try array.append(allocator, value);
183183 return null;
184184 },
185185 else => unreachable,
lib/std/json/dynamic_test.zig+1-13
......@@ -122,18 +122,6 @@ test "parsing empty string gives appropriate error" {
122122 try testing.expectError(error.UnexpectedEndOfInput, testParse(arena_allocator.allocator(), ""));
123123}
124124
125test "Value.array allocator should still be usable after parsing" {
126 var parsed = try parseFromSlice(Value, std.testing.allocator, "[]", .{});
127 defer parsed.deinit();
128
129 // Allocation should succeed
130 var i: usize = 0;
131 while (i < 100) : (i += 1) {
132 try parsed.value.array.append(Value{ .integer = 100 });
133 }
134 try testing.expectEqual(parsed.value.array.items.len, 100);
135}
136
137125test "integer after float has proper type" {
138126 var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
139127 defer arena_allocator.deinit();
......@@ -236,7 +224,7 @@ test "Value.jsonStringify" {
236224 .{ .number_string = "43" },
237225 .{ .float = 42 },
238226 .{ .string = "weeee" },
239 .{ .array = Array.fromOwnedSlice(undefined, &vals) },
227 .{ .array = .fromOwnedSlice(&vals) },
240228 .{ .object = obj },
241229 };
242230 var buffer: [0x1000]u8 = undefined;
lib/std/json/static.zig+8-8
......@@ -2,7 +2,7 @@ const std = @import("std");
22const assert = std.debug.assert;
33const Allocator = std.mem.Allocator;
44const ArenaAllocator = std.heap.ArenaAllocator;
5const ArrayList = std.array_list.Managed;
5const ArrayList = std.ArrayList;
66
77const Scanner = @import("Scanner.zig");
88const Token = Scanner.Token;
......@@ -469,7 +469,7 @@ pub fn innerParse(
469469 _ = try source.next();
470470
471471 // Typical array.
472 var arraylist = ArrayList(ptrInfo.child).init(allocator);
472 var arraylist: ArrayList(ptrInfo.child) = .empty;
473473 while (true) {
474474 switch (try source.peekNextTokenType()) {
475475 .array_end => {
......@@ -479,15 +479,15 @@ pub fn innerParse(
479479 else => {},
480480 }
481481
482 try arraylist.ensureUnusedCapacity(1);
482 try arraylist.ensureUnusedCapacity(allocator, 1);
483483 arraylist.appendAssumeCapacity(try innerParse(ptrInfo.child, allocator, source, options));
484484 }
485485
486486 if (ptrInfo.sentinel()) |s| {
487 return try arraylist.toOwnedSliceSentinel(s);
487 return try arraylist.toOwnedSliceSentinel(allocator, s);
488488 }
489489
490 return try arraylist.toOwnedSlice();
490 return try arraylist.toOwnedSlice(allocator);
491491 },
492492 .string => {
493493 if (ptrInfo.child != u8) return error.UnexpectedToken;
......@@ -495,9 +495,9 @@ pub fn innerParse(
495495 // Dynamic length string.
496496 if (ptrInfo.sentinel()) |s| {
497497 // Use our own array list so we can append the sentinel.
498 var value_list = ArrayList(u8).init(allocator);
499 _ = try source.allocNextIntoArrayListMax(&value_list, .alloc_always, options.max_value_len.?);
500 return try value_list.toOwnedSliceSentinel(s);
498 var value_list: ArrayList(u8) = .empty;
499 _ = try source.allocNextIntoArrayListMax(allocator, &value_list, .alloc_always, options.max_value_len.?);
500 return try value_list.toOwnedSliceSentinel(allocator, s);
501501 }
502502 if (ptrInfo.attrs.@"const") {
503503 switch (try source.nextAllocMax(allocator, options.allocate.?, options.max_value_len.?)) {