From 98eac689294509ae09ab1b0ce2feab16dc05ee00 Mon Sep 17 00:00:00 2001 From: torque Date: Thu, 23 Nov 2023 17:54:14 -0800 Subject: [PATCH] value: simplify list conversion code There was really no reason to use ArrayLists here when the list length is known ahead of time. This slightly shortens the code and should be slightly more memory/stack efficient. --- src/parser/value.zig | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/parser/value.zig b/src/parser/value.zig index 2138e7f..c65b1b1 100644 --- a/src/parser/value.zig +++ b/src/parser/value.zig @@ -131,15 +131,18 @@ pub const Value = union(enum) { } }, .list, .inline_list => |lst| { - var result = try std.ArrayList(ptr.child).initCapacity(allocator, lst.items.len); - errdefer result.deinit(); - for (lst.items) |item| { - result.appendAssumeCapacity(try item.convertTo(ptr.child, allocator, options)); + const result = try allocator.alloc(ptr.child, lst.items.len + @intFromBool(ptr.sentinel != null)); + + for (result[0..lst.items.len], lst.items) |*res, item| { + res.* = try item.convertTo(ptr.child, allocator, options); } - if (ptr.sentinel) |sent| { - return try result.toOwnedSliceSentinel(@as(*align(1) const ptr.child, @ptrCast(sent)).*); + + if (comptime ptr.sentinel) |sentinel| { + const sval = @as(*align(1) const ptr.child, @ptrCast(sentinel)).*; + result[lst.items.len] = sval; + return result[0..lst.items.len :sval]; } else { - return try result.toOwnedSlice(); + return result; } }, else => return error.BadValue, @@ -151,7 +154,7 @@ pub const Value = union(enum) { result.* = try self.convertTo(ptr.child, allocator, options); return result; }, - else => @compileError("Cannot deserialize into many-pointer or c-pointer " ++ @typeName(T)), // do not support many or C item pointers. + else => @compileError("Cannot deserialize into many-pointer or c-pointer " ++ @typeName(T)), }, .Array => |arr| { // TODO: There is ambiguity here because a document expecting a list @@ -168,14 +171,12 @@ pub const Value = union(enum) { } else return error.BadValue; }, .list, .inline_list => |lst| { - var storage = try std.ArrayList(arr.child).initCapacity(allocator, arr.len); - defer storage.deinit(); - for (lst.items) |item| { - storage.appendAssumeCapacity(try item.convertTo(arr.child, allocator, options)); - } - // this may result in a big stack allocation, which is not ideal + if (lst.items.len != arr.len) return error.BadValue; + var result: T = undefined; - @memcpy(&result, storage.items); + for (&result, lst.items) |*res, item| { + res.* = try item.convertTo(arr.child, allocator, options); + } return result; }, else => return error.BadValue, @@ -190,8 +191,8 @@ pub const Value = union(enum) { .list, .inline_list => |list| { if (list.items.len != stt.fields.len) return error.BadValue; var result: T = undefined; - inline for (stt.fields, 0..) |field, idx| { - result[idx] = try list.items[idx].convertTo(field.type, allocator, options); + inline for (stt.fields, &result, list.items) |field, *res, item| { + res.* = try item.convertTo(field.type, allocator, options); } return result; },