mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Adds non allocating alternatives to ZON parse functions (#22916)
* Adds "flat" alternatives to zon.parse.from* that don't support pointers * Fixes documentation * Removes flat postfix from non allocating functions, adds alloc to others * Stops using alloc variant in tests where not needed
This commit is contained in:
parent
37f4bee92a
commit
5a0cf21775
@ -1,11 +1,12 @@
|
||||
//! The simplest way to parse ZON at runtime is to use `fromSlice`. If you need to parse ZON at
|
||||
//! compile time, you may use `@import`.
|
||||
//! The simplest way to parse ZON at runtime is to use `fromSlice`/`fromSliceAlloc`.
|
||||
//!
|
||||
//! Note that if you need to parse ZON at compile time, you may use `@import`.
|
||||
//!
|
||||
//! Parsing from individual Zoir nodes is also available:
|
||||
//! * `fromZoir`
|
||||
//! * `fromZoirNode`
|
||||
//! * `fromZoir`/`fromZoirAlloc`
|
||||
//! * `fromZoirNode`/`fromZoirNodeAlloc`
|
||||
//!
|
||||
//! For lower level control, it is possible to operate on `std.zig.Zoir` directly.
|
||||
//! For lower level control over parsing, see `std.zig.Zoir`.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
@ -254,7 +255,25 @@ pub const Diagnostics = struct {
|
||||
///
|
||||
/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in
|
||||
/// `diag` if non null. If diag is not null, it must be initialized to `.{}`.
|
||||
///
|
||||
/// Asserts at compile time that the result type doesn't contain pointers. As such, the result
|
||||
/// doesn't need to be freed.
|
||||
///
|
||||
/// An allocator is still required for temporary allocations made during parsing.
|
||||
pub fn fromSlice(
|
||||
T: type,
|
||||
gpa: Allocator,
|
||||
source: [:0]const u8,
|
||||
diag: ?*Diagnostics,
|
||||
options: Options,
|
||||
) error{ OutOfMemory, ParseZon }!T {
|
||||
comptime assert(!requiresAllocator(T));
|
||||
return fromSliceAlloc(T, gpa, source, diag, options);
|
||||
}
|
||||
|
||||
/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
|
||||
/// `free`.
|
||||
pub fn fromSliceAlloc(
|
||||
/// The type to deserialize into. May not be or contain any of the following types:
|
||||
/// * Any comptime-only type, except in a comptime field
|
||||
/// * `type`
|
||||
@ -285,11 +304,35 @@ pub fn fromSlice(
|
||||
defer if (diag == null) zoir.deinit(gpa);
|
||||
|
||||
if (diag) |s| s.* = .{};
|
||||
return fromZoir(T, gpa, ast, zoir, diag, options);
|
||||
return fromZoirAlloc(T, gpa, ast, zoir, diag, options);
|
||||
}
|
||||
|
||||
/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
|
||||
pub fn fromZoir(
|
||||
T: type,
|
||||
ast: Ast,
|
||||
zoir: Zoir,
|
||||
diag: ?*Diagnostics,
|
||||
options: Options,
|
||||
) error{ParseZon}!T {
|
||||
comptime assert(!requiresAllocator(T));
|
||||
var buf: [0]u8 = .{};
|
||||
var failing_allocator = std.heap.FixedBufferAllocator.init(&buf);
|
||||
return fromZoirAlloc(
|
||||
T,
|
||||
failing_allocator.allocator(),
|
||||
ast,
|
||||
zoir,
|
||||
diag,
|
||||
options,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => unreachable, // Checked by comptime assertion above
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
|
||||
pub fn fromZoirAlloc(
|
||||
T: type,
|
||||
gpa: Allocator,
|
||||
ast: Ast,
|
||||
@ -297,11 +340,37 @@ pub fn fromZoir(
|
||||
diag: ?*Diagnostics,
|
||||
options: Options,
|
||||
) error{ OutOfMemory, ParseZon }!T {
|
||||
return fromZoirNode(T, gpa, ast, zoir, .root, diag, options);
|
||||
return fromZoirNodeAlloc(T, gpa, ast, zoir, .root, diag, options);
|
||||
}
|
||||
|
||||
/// Like `fromZoir`, but the parse starts on `node` instead of root.
|
||||
/// Like `fromZoir`, but the parse starts at `node` instead of root.
|
||||
pub fn fromZoirNode(
|
||||
T: type,
|
||||
ast: Ast,
|
||||
zoir: Zoir,
|
||||
node: Zoir.Node.Index,
|
||||
diag: ?*Diagnostics,
|
||||
options: Options,
|
||||
) error{ParseZon}!T {
|
||||
comptime assert(!requiresAllocator(T));
|
||||
var buf: [0]u8 = .{};
|
||||
var failing_allocator = std.heap.FixedBufferAllocator.init(&buf);
|
||||
return fromZoirNodeAlloc(
|
||||
T,
|
||||
failing_allocator.allocator(),
|
||||
ast,
|
||||
zoir,
|
||||
node,
|
||||
diag,
|
||||
options,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => unreachable, // Checked by comptime assertion above
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
/// Like `fromZoirAlloc`, but the parse starts at `node` instead of root.
|
||||
pub fn fromZoirNodeAlloc(
|
||||
T: type,
|
||||
gpa: Allocator,
|
||||
ast: Ast,
|
||||
@ -1321,7 +1390,7 @@ test "std.zon failure/oom formatting" {
|
||||
});
|
||||
var diag: Diagnostics = .{};
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(error.OutOfMemory, fromSlice(
|
||||
try std.testing.expectError(error.OutOfMemory, fromSliceAlloc(
|
||||
[]const u8,
|
||||
failing_allocator.allocator(),
|
||||
"\"foo\"",
|
||||
@ -1331,7 +1400,7 @@ test "std.zon failure/oom formatting" {
|
||||
try std.testing.expectFmt("", "{f}", .{diag});
|
||||
}
|
||||
|
||||
test "std.zon fromSlice syntax error" {
|
||||
test "std.zon fromSliceAlloc syntax error" {
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(u8, std.testing.allocator, ".{", null, .{}),
|
||||
@ -1351,9 +1420,9 @@ test "std.zon optional" {
|
||||
|
||||
// Deep free
|
||||
{
|
||||
const none = try fromSlice(?[]const u8, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(?[]const u8, gpa, "null", null, .{});
|
||||
try std.testing.expect(none == null);
|
||||
const some = try fromSlice(?[]const u8, gpa, "\"foo\"", null, .{});
|
||||
const some = try fromSliceAlloc(?[]const u8, gpa, "\"foo\"", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqualStrings("foo", some.?);
|
||||
}
|
||||
@ -1386,10 +1455,10 @@ test "std.zon unions" {
|
||||
{
|
||||
const Union = union(enum) { bar: []const u8, baz: bool };
|
||||
|
||||
const noalloc = try fromSlice(Union, gpa, ".{.baz = false}", null, .{});
|
||||
const noalloc = try fromSliceAlloc(Union, gpa, ".{.baz = false}", null, .{});
|
||||
try std.testing.expectEqual(Union{ .baz = false }, noalloc);
|
||||
|
||||
const alloc = try fromSlice(Union, gpa, ".{.bar = \"qux\"}", null, .{});
|
||||
const alloc = try fromSliceAlloc(Union, gpa, ".{.bar = \"qux\"}", null, .{});
|
||||
defer free(gpa, alloc);
|
||||
try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
|
||||
}
|
||||
@ -1401,7 +1470,7 @@ test "std.zon unions" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(Union, gpa, ".{.z=2.5}", &diag, .{}),
|
||||
fromSliceAlloc(Union, gpa, ".{.z=2.5}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt(
|
||||
\\1:4: error: unexpected field 'z'
|
||||
@ -1420,7 +1489,7 @@ test "std.zon unions" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),
|
||||
fromSliceAlloc(Union, gpa, ".{.x=1}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -1432,7 +1501,7 @@ test "std.zon unions" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
|
||||
fromSliceAlloc(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
|
||||
}
|
||||
@ -1444,7 +1513,7 @@ test "std.zon unions" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(Union, gpa, ".{}", &diag, .{}),
|
||||
fromSliceAlloc(Union, gpa, ".{}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
|
||||
}
|
||||
@ -1454,7 +1523,7 @@ test "std.zon unions" {
|
||||
const Union = union { x: void };
|
||||
var diag: Diagnostics = .{};
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
|
||||
try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
|
||||
}
|
||||
|
||||
@ -1463,7 +1532,7 @@ test "std.zon unions" {
|
||||
const Union = union(enum) { x: void };
|
||||
var diag: Diagnostics = .{};
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".y", &diag, .{}));
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".y", &diag, .{}));
|
||||
try std.testing.expectFmt(
|
||||
\\1:2: error: unexpected field 'y'
|
||||
\\1:2: note: supported: 'x'
|
||||
@ -1479,7 +1548,7 @@ test "std.zon unions" {
|
||||
const Union = union(enum) { x: f32 };
|
||||
var diag: Diagnostics = .{};
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
|
||||
try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
|
||||
}
|
||||
}
|
||||
@ -1511,7 +1580,7 @@ test "std.zon structs" {
|
||||
{
|
||||
const Foo = struct { bar: []const u8, baz: []const []const u8 };
|
||||
|
||||
const parsed = try fromSlice(
|
||||
const parsed = try fromSliceAlloc(
|
||||
Foo,
|
||||
gpa,
|
||||
".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
|
||||
@ -1668,7 +1737,7 @@ test "std.zon structs" {
|
||||
{
|
||||
var diag: Diagnostics = .{};
|
||||
defer diag.deinit(gpa);
|
||||
const parsed = fromSlice([]u8, gpa, "[]u8{1, 2, 3}", &diag, .{});
|
||||
const parsed = fromSliceAlloc([]u8, gpa, "[]u8{1, 2, 3}", &diag, .{});
|
||||
try std.testing.expectError(error.ParseZon, parsed);
|
||||
try std.testing.expectFmt(
|
||||
\\1:1: error: types are not available in ZON
|
||||
@ -1737,7 +1806,7 @@ test "std.zon tuples" {
|
||||
// Deep free
|
||||
{
|
||||
const Tuple = struct { []const u8, []const u8 };
|
||||
const parsed = try fromSlice(Tuple, gpa, ".{\"hello\", \"world\"}", null, .{});
|
||||
const parsed = try fromSliceAlloc(Tuple, gpa, ".{\"hello\", \"world\"}", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
|
||||
}
|
||||
@ -1847,27 +1916,27 @@ test "std.zon arrays and slices" {
|
||||
|
||||
// Slice literals
|
||||
{
|
||||
const zero = try fromSlice([]const u8, gpa, ".{}", null, .{});
|
||||
const zero = try fromSliceAlloc([]const u8, gpa, ".{}", null, .{});
|
||||
defer free(gpa, zero);
|
||||
try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
|
||||
|
||||
const one = try fromSlice([]u8, gpa, ".{'a'}", null, .{});
|
||||
const one = try fromSliceAlloc([]u8, gpa, ".{'a'}", null, .{});
|
||||
defer free(gpa, one);
|
||||
try std.testing.expectEqualSlices(u8, &.{'a'}, one);
|
||||
|
||||
const two = try fromSlice([]const u8, gpa, ".{'a', 'b'}", null, .{});
|
||||
const two = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b'}", null, .{});
|
||||
defer free(gpa, two);
|
||||
try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
|
||||
|
||||
const two_comma = try fromSlice([]const u8, gpa, ".{'a', 'b',}", null, .{});
|
||||
const two_comma = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b',}", null, .{});
|
||||
defer free(gpa, two_comma);
|
||||
try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
|
||||
|
||||
const three = try fromSlice([]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
|
||||
const three = try fromSliceAlloc([]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
|
||||
defer free(gpa, three);
|
||||
try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
|
||||
|
||||
const sentinel = try fromSlice([:'z']const u8, gpa, ".{'a', 'b', 'c'}", null, .{});
|
||||
const sentinel = try fromSliceAlloc([:'z']const u8, gpa, ".{'a', 'b', 'c'}", null, .{});
|
||||
defer free(gpa, sentinel);
|
||||
const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
|
||||
try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
|
||||
@ -1878,7 +1947,7 @@ test "std.zon arrays and slices" {
|
||||
{
|
||||
// Arrays
|
||||
{
|
||||
const parsed = try fromSlice([1][]const u8, gpa, ".{\"abc\"}", null, .{});
|
||||
const parsed = try fromSliceAlloc([1][]const u8, gpa, ".{\"abc\"}", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
const expected: [1][]const u8 = .{"abc"};
|
||||
try std.testing.expectEqualDeep(expected, parsed);
|
||||
@ -1886,7 +1955,7 @@ test "std.zon arrays and slices" {
|
||||
|
||||
// Slice literals
|
||||
{
|
||||
const parsed = try fromSlice([]const []const u8, gpa, ".{\"abc\"}", null, .{});
|
||||
const parsed = try fromSliceAlloc([]const []const u8, gpa, ".{\"abc\"}", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
const expected: []const []const u8 = &.{"abc"};
|
||||
try std.testing.expectEqualDeep(expected, parsed);
|
||||
@ -1905,7 +1974,7 @@ test "std.zon arrays and slices" {
|
||||
|
||||
// Slice literals
|
||||
{
|
||||
const sentinel = try fromSlice([:2]align(4) u8, gpa, ".{1}", null, .{});
|
||||
const sentinel = try fromSliceAlloc([:2]align(4) u8, gpa, ".{1}", null, .{});
|
||||
defer free(gpa, sentinel);
|
||||
try std.testing.expectEqual(@as(usize, 1), sentinel.len);
|
||||
try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
|
||||
@ -1992,7 +2061,7 @@ test "std.zon arrays and slices" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
|
||||
fromSliceAlloc([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2017,7 +2086,7 @@ test "std.zon arrays and slices" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]u8, gpa, "'a'", &diag, .{}),
|
||||
fromSliceAlloc([]u8, gpa, "'a'", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2029,7 +2098,7 @@ test "std.zon arrays and slices" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]u8, gpa, " &.{'a', 'b', 'c'}", &diag, .{}),
|
||||
fromSliceAlloc([]u8, gpa, " &.{'a', 'b', 'c'}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt(
|
||||
"1:3: error: pointers are not available in ZON\n",
|
||||
@ -2044,21 +2113,21 @@ test "std.zon string literal" {
|
||||
|
||||
// Basic string literal
|
||||
{
|
||||
const parsed = try fromSlice([]const u8, gpa, "\"abc\"", null, .{});
|
||||
const parsed = try fromSliceAlloc([]const u8, gpa, "\"abc\"", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
|
||||
}
|
||||
|
||||
// String literal with escape characters
|
||||
{
|
||||
const parsed = try fromSlice([]const u8, gpa, "\"ab\\nc\"", null, .{});
|
||||
const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\nc\"", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
|
||||
}
|
||||
|
||||
// String literal with embedded null
|
||||
{
|
||||
const parsed = try fromSlice([]const u8, gpa, "\"ab\\x00c\"", null, .{});
|
||||
const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\x00c\"", null, .{});
|
||||
defer free(gpa, parsed);
|
||||
try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
|
||||
}
|
||||
@ -2070,7 +2139,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),
|
||||
fromSliceAlloc([]u8, gpa, "\"abcd\"", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2080,7 +2149,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),
|
||||
fromSliceAlloc([]u8, gpa, "\\\\abcd", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2116,7 +2185,7 @@ test "std.zon string literal" {
|
||||
// Zero terminated slices
|
||||
{
|
||||
{
|
||||
const parsed: [:0]const u8 = try fromSlice(
|
||||
const parsed: [:0]const u8 = try fromSliceAlloc(
|
||||
[:0]const u8,
|
||||
gpa,
|
||||
"\"abc\"",
|
||||
@ -2129,7 +2198,7 @@ test "std.zon string literal" {
|
||||
}
|
||||
|
||||
{
|
||||
const parsed: [:0]const u8 = try fromSlice(
|
||||
const parsed: [:0]const u8 = try fromSliceAlloc(
|
||||
[:0]const u8,
|
||||
gpa,
|
||||
"\\\\abc",
|
||||
@ -2149,7 +2218,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),
|
||||
fromSliceAlloc([:1]const u8, gpa, "\"foo\"", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2159,7 +2228,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),
|
||||
fromSliceAlloc([:1]const u8, gpa, "\\\\foo", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2171,7 +2240,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]const u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc([]const u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2182,7 +2251,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]const u8, gpa, ".{false}", &diag, .{}),
|
||||
fromSliceAlloc([]const u8, gpa, ".{false}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2193,7 +2262,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),
|
||||
fromSliceAlloc([]const i8, gpa, "\"\\a\"", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2205,7 +2274,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),
|
||||
fromSliceAlloc([]const i8, gpa, "\"a\"", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2215,7 +2284,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),
|
||||
fromSliceAlloc([]const i8, gpa, "\\\\a", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2228,7 +2297,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
|
||||
fromSliceAlloc([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2238,7 +2307,7 @@ test "std.zon string literal" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
|
||||
fromSliceAlloc([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -2253,7 +2322,7 @@ test "std.zon string literal" {
|
||||
message2: String,
|
||||
message3: String,
|
||||
};
|
||||
const parsed = try fromSlice(S, gpa,
|
||||
const parsed = try fromSliceAlloc(S, gpa,
|
||||
\\.{
|
||||
\\ .message =
|
||||
\\ \\hello, world!
|
||||
@ -2909,7 +2978,7 @@ test "std.zon free on error" {
|
||||
y: []const u8,
|
||||
z: bool,
|
||||
};
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
|
||||
\\.{
|
||||
\\ .x = "hello",
|
||||
\\ .y = "world",
|
||||
@ -2925,7 +2994,7 @@ test "std.zon free on error" {
|
||||
[]const u8,
|
||||
bool,
|
||||
};
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
|
||||
\\.{
|
||||
\\ "hello",
|
||||
\\ "world",
|
||||
@ -2940,7 +3009,7 @@ test "std.zon free on error" {
|
||||
x: []const u8,
|
||||
y: bool,
|
||||
};
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
|
||||
\\.{
|
||||
\\ .x = "hello",
|
||||
\\}
|
||||
@ -2949,7 +3018,7 @@ test "std.zon free on error" {
|
||||
|
||||
// Test freeing partially allocated arrays
|
||||
{
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(
|
||||
[3][]const u8,
|
||||
std.testing.allocator,
|
||||
\\.{
|
||||
@ -2965,7 +3034,7 @@ test "std.zon free on error" {
|
||||
|
||||
// Test freeing partially allocated slices
|
||||
{
|
||||
try std.testing.expectError(error.ParseZon, fromSlice(
|
||||
try std.testing.expectError(error.ParseZon, fromSliceAlloc(
|
||||
[][]const u8,
|
||||
std.testing.allocator,
|
||||
\\.{
|
||||
@ -2989,7 +3058,7 @@ test "std.zon free on error" {
|
||||
// We can also parse types that can't be freed if it's impossible for an error to occur after
|
||||
// the allocation, as is the case here.
|
||||
{
|
||||
const result = try fromSlice(
|
||||
const result = try fromSliceAlloc(
|
||||
union { x: []const u8 },
|
||||
std.testing.allocator,
|
||||
".{ .x = \"foo\" }",
|
||||
@ -3008,7 +3077,7 @@ test "std.zon free on error" {
|
||||
union { x: []const u8 },
|
||||
bool,
|
||||
};
|
||||
const result = try fromSlice(
|
||||
const result = try fromSliceAlloc(
|
||||
S,
|
||||
std.testing.allocator,
|
||||
".{ .{ .x = \"foo\" }, true }",
|
||||
@ -3026,7 +3095,7 @@ test "std.zon free on error" {
|
||||
a: union { x: []const u8 },
|
||||
b: bool,
|
||||
};
|
||||
const result = try fromSlice(
|
||||
const result = try fromSliceAlloc(
|
||||
S,
|
||||
std.testing.allocator,
|
||||
".{ .a = .{ .x = \"foo\" }, .b = true }",
|
||||
@ -3043,7 +3112,7 @@ test "std.zon free on error" {
|
||||
// Again but for arrays.
|
||||
{
|
||||
const S = [2]union { x: []const u8 };
|
||||
const result = try fromSlice(
|
||||
const result = try fromSliceAlloc(
|
||||
S,
|
||||
std.testing.allocator,
|
||||
".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
|
||||
@ -3061,7 +3130,7 @@ test "std.zon free on error" {
|
||||
// Again but for slices.
|
||||
{
|
||||
const S = []union { x: []const u8 };
|
||||
const result = try fromSlice(
|
||||
const result = try fromSliceAlloc(
|
||||
S,
|
||||
std.testing.allocator,
|
||||
".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
|
||||
@ -3114,9 +3183,9 @@ test "std.zon vector" {
|
||||
{
|
||||
try std.testing.expectEqual(
|
||||
@Vector(0, *const u8){},
|
||||
try fromSlice(@Vector(0, *const u8), gpa, ".{}", null, .{}),
|
||||
try fromSliceAlloc(@Vector(0, *const u8), gpa, ".{}", null, .{}),
|
||||
);
|
||||
const pointers = try fromSlice(@Vector(3, *const u8), gpa, ".{2, 4, 6}", null, .{});
|
||||
const pointers = try fromSliceAlloc(@Vector(3, *const u8), gpa, ".{2, 4, 6}", null, .{});
|
||||
defer free(gpa, pointers);
|
||||
try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
|
||||
}
|
||||
@ -3124,9 +3193,9 @@ test "std.zon vector" {
|
||||
{
|
||||
try std.testing.expectEqual(
|
||||
@Vector(0, ?*const u8){},
|
||||
try fromSlice(@Vector(0, ?*const u8), gpa, ".{}", null, .{}),
|
||||
try fromSliceAlloc(@Vector(0, ?*const u8), gpa, ".{}", null, .{}),
|
||||
);
|
||||
const pointers = try fromSlice(@Vector(3, ?*const u8), gpa, ".{2, null, 6}", null, .{});
|
||||
const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), gpa, ".{2, null, 6}", null, .{});
|
||||
defer free(gpa, pointers);
|
||||
try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
|
||||
}
|
||||
@ -3193,7 +3262,7 @@ test "std.zon vector" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
|
||||
fromSliceAlloc(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3204,77 +3273,77 @@ test "std.zon add pointers" {
|
||||
|
||||
// Primitive with varying levels of pointers
|
||||
{
|
||||
const result = try fromSlice(*u32, gpa, "10", null, .{});
|
||||
const result = try fromSliceAlloc(*u32, gpa, "10", null, .{});
|
||||
defer free(gpa, result);
|
||||
try std.testing.expectEqual(@as(u32, 10), result.*);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try fromSlice(**u32, gpa, "10", null, .{});
|
||||
const result = try fromSliceAlloc(**u32, gpa, "10", null, .{});
|
||||
defer free(gpa, result);
|
||||
try std.testing.expectEqual(@as(u32, 10), result.*.*);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try fromSlice(***u32, gpa, "10", null, .{});
|
||||
const result = try fromSliceAlloc(***u32, gpa, "10", null, .{});
|
||||
defer free(gpa, result);
|
||||
try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
|
||||
}
|
||||
|
||||
// Primitive optional with varying levels of pointers
|
||||
{
|
||||
const some = try fromSlice(?*u32, gpa, "10", null, .{});
|
||||
const some = try fromSliceAlloc(?*u32, gpa, "10", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqual(@as(u32, 10), some.?.*);
|
||||
|
||||
const none = try fromSlice(?*u32, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(?*u32, gpa, "null", null, .{});
|
||||
defer free(gpa, none);
|
||||
try std.testing.expectEqual(null, none);
|
||||
}
|
||||
|
||||
{
|
||||
const some = try fromSlice(*?u32, gpa, "10", null, .{});
|
||||
const some = try fromSliceAlloc(*?u32, gpa, "10", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqual(@as(u32, 10), some.*.?);
|
||||
|
||||
const none = try fromSlice(*?u32, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(*?u32, gpa, "null", null, .{});
|
||||
defer free(gpa, none);
|
||||
try std.testing.expectEqual(null, none.*);
|
||||
}
|
||||
|
||||
{
|
||||
const some = try fromSlice(?**u32, gpa, "10", null, .{});
|
||||
const some = try fromSliceAlloc(?**u32, gpa, "10", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
|
||||
|
||||
const none = try fromSlice(?**u32, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(?**u32, gpa, "null", null, .{});
|
||||
defer free(gpa, none);
|
||||
try std.testing.expectEqual(null, none);
|
||||
}
|
||||
|
||||
{
|
||||
const some = try fromSlice(*?*u32, gpa, "10", null, .{});
|
||||
const some = try fromSliceAlloc(*?*u32, gpa, "10", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
|
||||
|
||||
const none = try fromSlice(*?*u32, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(*?*u32, gpa, "null", null, .{});
|
||||
defer free(gpa, none);
|
||||
try std.testing.expectEqual(null, none.*);
|
||||
}
|
||||
|
||||
{
|
||||
const some = try fromSlice(**?u32, gpa, "10", null, .{});
|
||||
const some = try fromSliceAlloc(**?u32, gpa, "10", null, .{});
|
||||
defer free(gpa, some);
|
||||
try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
|
||||
|
||||
const none = try fromSlice(**?u32, gpa, "null", null, .{});
|
||||
const none = try fromSliceAlloc(**?u32, gpa, "null", null, .{});
|
||||
defer free(gpa, none);
|
||||
try std.testing.expectEqual(null, none.*.*);
|
||||
}
|
||||
|
||||
// Pointer to an array
|
||||
{
|
||||
const result = try fromSlice(*[3]u8, gpa, ".{ 1, 2, 3 }", null, .{});
|
||||
const result = try fromSliceAlloc(*[3]u8, gpa, ".{ 1, 2, 3 }", null, .{});
|
||||
defer free(gpa, result);
|
||||
try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
|
||||
}
|
||||
@ -3297,7 +3366,7 @@ test "std.zon add pointers" {
|
||||
.f2 = &null,
|
||||
};
|
||||
|
||||
const found = try fromSlice(?*Outer, gpa,
|
||||
const found = try fromSliceAlloc(?*Outer, gpa,
|
||||
\\.{
|
||||
\\ .f1 = .{
|
||||
\\ .f1 = null,
|
||||
@ -3317,7 +3386,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3327,7 +3396,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const f32, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3337,7 +3406,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3347,7 +3416,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const bool, gpa, "10", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3357,7 +3426,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3367,7 +3436,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3377,7 +3446,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3387,7 +3456,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const [3]u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3397,7 +3466,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(?[3]u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(?[3]u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3407,7 +3476,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const []u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3417,7 +3486,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(?[]u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(?[]u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3427,7 +3496,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const []const u8, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3437,7 +3506,7 @@ test "std.zon add pointers" {
|
||||
defer diag.deinit(gpa);
|
||||
try std.testing.expectError(
|
||||
error.ParseZon,
|
||||
fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
|
||||
fromSliceAlloc(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
|
||||
);
|
||||
try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
|
||||
}
|
||||
@ -3466,3 +3535,30 @@ test "std.zon stop on node" {
|
||||
try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(diag.zoir));
|
||||
}
|
||||
}
|
||||
|
||||
test "std.zon no alloc" {
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
try std.testing.expectEqual(
|
||||
[3]u8{ 1, 2, 3 },
|
||||
try fromSlice([3]u8, gpa, ".{ 1, 2, 3 }", null, .{}),
|
||||
);
|
||||
|
||||
const Nested = struct { u8, u8, struct { u8, u8 } };
|
||||
|
||||
var ast = try std.zig.Ast.parse(gpa, ".{ 1, 2, .{ 3, 4 } }", .zon);
|
||||
defer ast.deinit(gpa);
|
||||
|
||||
var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
|
||||
defer zoir.deinit(gpa);
|
||||
|
||||
try std.testing.expectEqual(
|
||||
Nested{ 1, 2, .{ 3, 4 } },
|
||||
try fromZoir(Nested, ast, zoir, null, .{}),
|
||||
);
|
||||
|
||||
try std.testing.expectEqual(
|
||||
Nested{ 1, 2, .{ 3, 4 } },
|
||||
try fromZoirNode(Nested, ast, zoir, .root, null, .{}),
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user