fix(zig-0.16): BREAKING adapt to std.json.ObjectMap becoming unmanaged

Remove JsonObjectExtractor because extract(&obj) for ObjectMap cannot work
without a stored allocator

Migration: replace extract(&obj) with extractAlloc(&obj, allocator)
This commit is contained in:
CJ van den Berg 2026-04-15 11:42:26 +02:00
parent e21fa573c5
commit 50cb8cc9e9
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
2 changed files with 19 additions and 32 deletions

View file

@ -388,7 +388,7 @@ fn decodeJsonArray(iter_: *[]const u8, minor: u5, arr: *json.Array) Error!bool {
return true; return true;
} }
fn decodeJsonObject(iter_: *[]const u8, minor: u5, obj: *json.ObjectMap) Error!bool { fn decodeJsonObject(iter_: *[]const u8, minor: u5, obj: *json.ObjectMap, allocator: std.mem.Allocator) Error!bool {
var iter = iter_.*; var iter = iter_.*;
var n = try decodePInt(&iter, minor); var n = try decodePInt(&iter, minor);
while (n > 0) { while (n > 0) {
@ -397,10 +397,10 @@ fn decodeJsonObject(iter_: *[]const u8, minor: u5, obj: *json.ObjectMap) Error!b
if (!try matchString(&iter, &key)) if (!try matchString(&iter, &key))
return false; return false;
if (!try matchJsonValue(&iter, &value, obj.allocator)) if (!try matchJsonValue(&iter, &value, allocator))
return false; return false;
_ = try obj.getOrPutValue(key, value); _ = try obj.getOrPutValue(allocator, key, value);
n -= 1; n -= 1;
} }
iter_.* = iter; iter_.* = iter;
@ -924,8 +924,8 @@ fn matchJsonValue(iter_: *[]const u8, v: *json.Value, a: std.mem.Allocator) Erro
break :ret try decodeJsonArray(&iter, t.minor, &v.array); break :ret try decodeJsonArray(&iter, t.minor, &v.array);
}, },
5 => ret: { // map 5 => ret: { // map
v.* = json.Value{ .object = json.ObjectMap.init(a) }; v.* = json.Value{ .object = .empty };
break :ret try decodeJsonObject(&iter, t.minor, &v.object); break :ret try decodeJsonObject(&iter, t.minor, &v.object, a);
}, },
6 => ret: { // tag 6 => ret: { // tag
break :ret false; break :ret false;
@ -1041,14 +1041,14 @@ fn matchArrayAlloc(iter: *[]const u8, element_type: type, arr: anytype, allocato
return true; return true;
} }
fn matchJsonObject(iter_: *[]const u8, obj: *json.ObjectMap) !bool { fn matchJsonObject(iter_: *[]const u8, obj: *json.ObjectMap, allocator: std.mem.Allocator) !bool {
var iter = iter_.*; var iter = iter_.*;
const t = try decodeType(&iter); const t = try decodeType(&iter);
if (t.type == cbor_magic_null) if (t.type == cbor_magic_null)
return true; return true;
if (t.major != 5) if (t.major != 5)
return error.NotAnObject; return error.NotAnObject;
const ret = try decodeJsonObject(&iter, t.minor, obj); const ret = try decodeJsonObject(&iter, t.minor, obj, allocator);
if (ret) iter_.* = iter; if (ret) iter_.* = iter;
return ret; return ret;
} }
@ -1148,6 +1148,8 @@ fn GenericExtractorAlloc(T: type) type {
pub fn extract(self: Self, iter: *[]const u8) Error!bool { pub fn extract(self: Self, iter: *[]const u8) Error!bool {
if (comptime T == json.Value) { if (comptime T == json.Value) {
return matchJsonValue(iter, self.dest, self.allocator); return matchJsonValue(iter, self.dest, self.allocator);
} else if (comptime T == json.ObjectMap) {
return matchJsonObject(iter, self.dest, self.allocator);
} else if (comptime isExtractableAlloc(T)) { } else if (comptime isExtractableAlloc(T)) {
return self.dest.cborExtract(iter, self.allocator); return self.dest.cborExtract(iter, self.allocator);
} else { } else {
@ -1209,26 +1211,11 @@ const JsonValueExtractor = struct {
} }
}; };
const JsonObjectExtractor = struct {
dest: *T,
const Self = @This();
pub const EXTRACTOR_TAG = struct {};
const T = json.ObjectMap;
pub fn init(dest: *T) Self {
return .{ .dest = dest };
}
pub fn extract(self: Self, iter: *[]const u8) Error!bool {
return matchJsonObject(iter, self.dest);
}
};
fn Extractor(comptime T: type) type { fn Extractor(comptime T: type) type {
if (T == json.Value) if (T == json.Value)
return JsonValueExtractor; return JsonValueExtractor;
if (T == json.ObjectMap) if (T == json.ObjectMap)
return JsonObjectExtractor; return extractErrorAlloc(json.ObjectMap);
return struct { return struct {
dest: *T, dest: *T,
const Self = @This(); const Self = @This();

View file

@ -369,9 +369,9 @@ test "cbor.extract_map" {
var buf: [128]u8 = undefined; var buf: [128]u8 = undefined;
const v = .{ "five", 5, "four", 4, .{ .three = 3 } }; const v = .{ "five", 5, "four", 4, .{ .three = 3 } };
const m = fmt(&buf, v); const m = fmt(&buf, v);
var obj = std.json.ObjectMap.init(std.testing.allocator); var obj: std.json.ObjectMap = .empty;
defer obj.deinit(); defer obj.deinit(std.testing.allocator);
try expect(try match(m, .{ "five", 5, "four", 4, extract(&obj) })); try expect(try match(m, .{ "five", 5, "four", 4, extractAlloc(&obj, std.testing.allocator) }));
try expect(obj.contains("three")); try expect(obj.contains("three"));
try expectEqual(obj.get("three").?, std.json.Value{ .integer = 3 }); try expectEqual(obj.get("three").?, std.json.Value{ .integer = 3 });
} }
@ -382,9 +382,9 @@ test "cbor.extract_map_map" {
const m = fmt(&buf, v); const m = fmt(&buf, v);
var a = std.heap.ArenaAllocator.init(std.testing.allocator); var a = std.heap.ArenaAllocator.init(std.testing.allocator);
defer a.deinit(); defer a.deinit();
var obj = std.json.ObjectMap.init(a.allocator()); var obj: std.json.ObjectMap = .empty;
defer obj.deinit(); defer obj.deinit(a.allocator());
try expect(try match(m, .{ "five", 5, "four", 4, extract(&obj) })); try expect(try match(m, .{ "five", 5, "four", 4, extractAlloc(&obj, a.allocator()) }));
try expect(obj.contains("three")); try expect(obj.contains("three"));
try expectEqual(obj.get("three").?, std.json.Value{ .integer = 3 }); try expectEqual(obj.get("three").?, std.json.Value{ .integer = 3 });
var child = obj.get("child").?.object; var child = obj.get("child").?.object;
@ -734,9 +734,9 @@ test "cbor.writeJsonValue object" {
var writer: Io.Writer = .fixed(&buf); var writer: Io.Writer = .fixed(&buf);
var arena = std.heap.ArenaAllocator.init(std.testing.allocator); var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit(); defer arena.deinit();
var obj = std.json.ObjectMap.init(arena.allocator()); var obj: std.json.ObjectMap = .empty;
try obj.put("x", .{ .integer = 42 }); try obj.put(arena.allocator(), "x", .{ .integer = 42 });
try obj.put("y", .{ .string = "hello" }); try obj.put(arena.allocator(), "y", .{ .string = "hello" });
try writeJsonValue(&writer, .{ .object = obj }); try writeJsonValue(&writer, .{ .object = obj });
var json_buf: [128]u8 = undefined; var json_buf: [128]u8 = undefined;
try expectEqualStrings("{\"x\":42,\"y\":\"hello\"}", try toJson(writer.buffered(), &json_buf)); try expectEqualStrings("{\"x\":42,\"y\":\"hello\"}", try toJson(writer.buffered(), &json_buf));