| author | |
| committer | |
| log | 43db697b46e362e5991005f6c7b8b16ddc9bddbb |
| tree | e53320c89cff35f60a1e11e57a0c938f0b793021 |
| parent | e498fb155051f548071da1a13098b8793f527275 |
| parent | 50a6b0f3acb2a17f74d57301dbf3d4b13e30953b |
| signature |
Stage2 fixes towards `zig2 build test-std` working23 files changed, 363 insertions(+), 177 deletions(-)
lib/compiler_rt/log2.zig+2-1| ... | ... | @@ -147,7 +147,8 @@ pub fn __log2x(a: f80) callconv(.C) f80 { |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | pub fn log2q(a: f128) callconv(.C) f128 { |
| 150 | return math.log2(a); | |
| 150 | // TODO: more correct implementation | |
| 151 | return log2(@floatCast(f64, a)); | |
| 151 | 152 | } |
| 152 | 153 | |
| 153 | 154 | pub fn log2l(x: c_longdouble) callconv(.C) c_longdouble { |
lib/std/compress.zig+1| ... | ... | @@ -5,6 +5,7 @@ pub const gzip = @import("compress/gzip.zig"); |
| 5 | 5 | pub const zlib = @import("compress/zlib.zig"); |
| 6 | 6 | |
| 7 | 7 | test { |
| 8 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 8 | 9 | _ = deflate; |
| 9 | 10 | _ = gzip; |
| 10 | 11 | _ = zlib; |
lib/std/crypto/25519/scalar.zig+8-4| ... | ... | @@ -34,12 +34,14 @@ pub fn rejectNonCanonical(s: CompressedScalar) NonCanonicalError!void { |
| 34 | 34 | |
| 35 | 35 | /// Reduce a scalar to the field size. |
| 36 | 36 | pub fn reduce(s: CompressedScalar) CompressedScalar { |
| 37 | return Scalar.fromBytes(s).toBytes(); | |
| 37 | var scalar = Scalar.fromBytes(s); | |
| 38 | return scalar.toBytes(); | |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | 41 | /// Reduce a 64-bytes scalar to the field size. |
| 41 | 42 | pub fn reduce64(s: [64]u8) CompressedScalar { |
| 42 | return ScalarDouble.fromBytes64(s).toBytes(); | |
| 43 | var scalar = ScalarDouble.fromBytes64(s); | |
| 44 | return scalar.toBytes(); | |
| 43 | 45 | } |
| 44 | 46 | |
| 45 | 47 | /// Perform the X25519 "clamping" operation. |
| ... | ... | @@ -106,12 +108,14 @@ pub const Scalar = struct { |
| 106 | 108 | |
| 107 | 109 | /// Unpack a 32-byte representation of a scalar |
| 108 | 110 | pub fn fromBytes(bytes: CompressedScalar) Scalar { |
| 109 | return ScalarDouble.fromBytes32(bytes).reduce(5); | |
| 111 | var scalar = ScalarDouble.fromBytes32(bytes); | |
| 112 | return scalar.reduce(5); | |
| 110 | 113 | } |
| 111 | 114 | |
| 112 | 115 | /// Unpack a 64-byte representation of a scalar |
| 113 | 116 | pub fn fromBytes64(bytes: [64]u8) Scalar { |
| 114 | return ScalarDouble.fromBytes64(bytes).reduce(5); | |
| 117 | var scalar = ScalarDouble.fromBytes64(bytes); | |
| 118 | return scalar.reduce(5); | |
| 115 | 119 | } |
| 116 | 120 | |
| 117 | 121 | /// Pack a scalar into bytes |
lib/std/crypto/blake3.zig+6-3| ... | ... | @@ -679,9 +679,12 @@ fn testBlake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) !void { |
| 679 | 679 | } |
| 680 | 680 | |
| 681 | 681 | test "BLAKE3 reference test cases" { |
| 682 | var hash = &Blake3.init(.{}); | |
| 683 | var keyed_hash = &Blake3.init(.{ .key = reference_test.key.* }); | |
| 684 | var derive_key = &Blake3.initKdf(reference_test.context_string, .{}); | |
| 682 | var hash_state = Blake3.init(.{}); | |
| 683 | const hash = &hash_state; | |
| 684 | var keyed_hash_state = Blake3.init(.{ .key = reference_test.key.* }); | |
| 685 | const keyed_hash = &keyed_hash_state; | |
| 686 | var derive_key_state = Blake3.initKdf(reference_test.context_string, .{}); | |
| 687 | const derive_key = &derive_key_state; | |
| 685 | 688 | |
| 686 | 689 | for (reference_test.cases) |t| { |
| 687 | 690 | try testBlake3(hash, t.input_len, t.hash.*); |
lib/std/crypto/sha3.zig+3-5| ... | ... | @@ -128,18 +128,16 @@ fn keccakF(comptime F: usize, d: *[F / 8]u8) void { |
| 128 | 128 | r.* = mem.readIntLittle(u64, d[8 * i ..][0..8]); |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | comptime var x: usize = 0; | |
| 132 | comptime var y: usize = 0; | |
| 133 | 131 | for (RC[0..no_rounds]) |round| { |
| 134 | 132 | // theta |
| 135 | x = 0; | |
| 133 | comptime var x: usize = 0; | |
| 136 | 134 | inline while (x < 5) : (x += 1) { |
| 137 | 135 | c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; |
| 138 | 136 | } |
| 139 | 137 | x = 0; |
| 140 | 138 | inline while (x < 5) : (x += 1) { |
| 141 | 139 | t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], @as(usize, 1)); |
| 142 | y = 0; | |
| 140 | comptime var y: usize = 0; | |
| 143 | 141 | inline while (y < 5) : (y += 1) { |
| 144 | 142 | s[x + y * 5] ^= t[0]; |
| 145 | 143 | } |
| ... | ... | @@ -155,7 +153,7 @@ fn keccakF(comptime F: usize, d: *[F / 8]u8) void { |
| 155 | 153 | } |
| 156 | 154 | |
| 157 | 155 | // chi |
| 158 | y = 0; | |
| 156 | comptime var y: usize = 0; | |
| 159 | 157 | inline while (y < 5) : (y += 1) { |
| 160 | 158 | x = 0; |
| 161 | 159 | inline while (x < 5) : (x += 1) { |
lib/std/event/batch.zig+1| ... | ... | @@ -109,6 +109,7 @@ pub fn Batch( |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | test "std.event.Batch" { |
| 112 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 112 | 113 | var count: usize = 0; |
| 113 | 114 | var batch = Batch(void, 2, .auto_async).init(); |
| 114 | 115 | batch.add(&async sleepALittle(&count)); |
lib/std/fmt.zig+5| ... | ... | @@ -2111,6 +2111,7 @@ test "slice" { |
| 2111 | 2111 | } |
| 2112 | 2112 | |
| 2113 | 2113 | test "escape non-printable" { |
| 2114 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2114 | 2115 | try expectFmt("abc", "{s}", .{fmtSliceEscapeLower("abc")}); |
| 2115 | 2116 | try expectFmt("ab\\xffc", "{s}", .{fmtSliceEscapeLower("ab\xffc")}); |
| 2116 | 2117 | try expectFmt("ab\\xFFc", "{s}", .{fmtSliceEscapeUpper("ab\xffc")}); |
| ... | ... | @@ -2122,6 +2123,7 @@ test "pointer" { |
| 2122 | 2123 | try expectFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value}); |
| 2123 | 2124 | try expectFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value}); |
| 2124 | 2125 | } |
| 2126 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2125 | 2127 | { |
| 2126 | 2128 | const value = @intToPtr(fn () void, 0xdeadbeef); |
| 2127 | 2129 | try expectFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); |
| ... | ... | @@ -2146,6 +2148,7 @@ test "cstr" { |
| 2146 | 2148 | } |
| 2147 | 2149 | |
| 2148 | 2150 | test "filesize" { |
| 2151 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2149 | 2152 | try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeDec(42)}); |
| 2150 | 2153 | try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeBin(42)}); |
| 2151 | 2154 | try expectFmt("file size: 63MB\n", "file size: {}\n", .{fmtIntSizeDec(63 * 1000 * 1000)}); |
| ... | ... | @@ -2445,6 +2448,7 @@ test "struct.zero-size" { |
| 2445 | 2448 | } |
| 2446 | 2449 | |
| 2447 | 2450 | test "bytes.hex" { |
| 2451 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2448 | 2452 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 2449 | 2453 | try expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{fmtSliceHexLower(some_bytes)}); |
| 2450 | 2454 | try expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{fmtSliceHexUpper(some_bytes)}); |
| ... | ... | @@ -2476,6 +2480,7 @@ pub fn hexToBytes(out: []u8, input: []const u8) ![]u8 { |
| 2476 | 2480 | } |
| 2477 | 2481 | |
| 2478 | 2482 | test "hexToBytes" { |
| 2483 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2479 | 2484 | var buf: [32]u8 = undefined; |
| 2480 | 2485 | try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))}); |
| 2481 | 2486 | try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))}); |
lib/std/heap.zig+2-1| ... | ... | @@ -1210,7 +1210,8 @@ pub fn testAllocatorAlignedShrink(base_allocator: mem.Allocator) !void { |
| 1210 | 1210 | const allocator = validationAllocator.allocator(); |
| 1211 | 1211 | |
| 1212 | 1212 | var debug_buffer: [1000]u8 = undefined; |
| 1213 | const debug_allocator = FixedBufferAllocator.init(&debug_buffer).allocator(); | |
| 1213 | var fib = FixedBufferAllocator.init(&debug_buffer); | |
| 1214 | const debug_allocator = fib.allocator(); | |
| 1214 | 1215 | |
| 1215 | 1216 | const alloc_size = mem.page_size * 2 + 50; |
| 1216 | 1217 | var slice = try allocator.alignedAlloc(u8, 16, alloc_size); |
lib/std/heap/log_to_writer_allocator.zig+2-1| ... | ... | @@ -91,7 +91,8 @@ test "LogToWriterAllocator" { |
| 91 | 91 | |
| 92 | 92 | var allocator_buf: [10]u8 = undefined; |
| 93 | 93 | var fixedBufferAllocator = std.mem.validationWrap(std.heap.FixedBufferAllocator.init(&allocator_buf)); |
| 94 | const allocator = logToWriterAllocator(fixedBufferAllocator.allocator(), fbs.writer()).allocator(); | |
| 94 | var allocator_state = logToWriterAllocator(fixedBufferAllocator.allocator(), fbs.writer()); | |
| 95 | const allocator = allocator_state.allocator(); | |
| 95 | 96 | |
| 96 | 97 | var a = try allocator.alloc(u8, 10); |
| 97 | 98 | a = allocator.shrink(a, 5); |
lib/std/io/reader.zig+64-32| ... | ... | @@ -344,7 +344,8 @@ pub fn Reader( |
| 344 | 344 | |
| 345 | 345 | test "Reader" { |
| 346 | 346 | var buf = "a\x02".*; |
| 347 | const reader = std.io.fixedBufferStream(&buf).reader(); | |
| 347 | var fis = std.io.fixedBufferStream(&buf); | |
| 348 | const reader = fis.reader(); | |
| 348 | 349 | try testing.expect((try reader.readByte()) == 'a'); |
| 349 | 350 | try testing.expect((try reader.readEnum(enum(u8) { |
| 350 | 351 | a = 0, |
| ... | ... | @@ -356,13 +357,15 @@ test "Reader" { |
| 356 | 357 | } |
| 357 | 358 | |
| 358 | 359 | test "Reader.isBytes" { |
| 359 | const reader = std.io.fixedBufferStream("foobar").reader(); | |
| 360 | var fis = std.io.fixedBufferStream("foobar"); | |
| 361 | const reader = fis.reader(); | |
| 360 | 362 | try testing.expectEqual(true, try reader.isBytes("foo")); |
| 361 | 363 | try testing.expectEqual(false, try reader.isBytes("qux")); |
| 362 | 364 | } |
| 363 | 365 | |
| 364 | 366 | test "Reader.skipBytes" { |
| 365 | const reader = std.io.fixedBufferStream("foobar").reader(); | |
| 367 | var fis = std.io.fixedBufferStream("foobar"); | |
| 368 | const reader = fis.reader(); | |
| 366 | 369 | try reader.skipBytes(3, .{}); |
| 367 | 370 | try testing.expect(try reader.isBytes("bar")); |
| 368 | 371 | try reader.skipBytes(0, .{}); |
| ... | ... | @@ -374,7 +377,8 @@ test "Reader.readUntilDelimiterArrayList returns ArrayLists with bytes read unti |
| 374 | 377 | var list = std.ArrayList(u8).init(a); |
| 375 | 378 | defer list.deinit(); |
| 376 | 379 | |
| 377 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); | |
| 380 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 381 | const reader = fis.reader(); | |
| 378 | 382 | |
| 379 | 383 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| 380 | 384 | try std.testing.expectEqualStrings("0000", list.items); |
| ... | ... | @@ -388,7 +392,8 @@ test "Reader.readUntilDelimiterArrayList returns an empty ArrayList" { |
| 388 | 392 | var list = std.ArrayList(u8).init(a); |
| 389 | 393 | defer list.deinit(); |
| 390 | 394 | |
| 391 | const reader = std.io.fixedBufferStream("\n").reader(); | |
| 395 | var fis = std.io.fixedBufferStream("\n"); | |
| 396 | const reader = fis.reader(); | |
| 392 | 397 | |
| 393 | 398 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| 394 | 399 | try std.testing.expectEqualStrings("", list.items); |
| ... | ... | @@ -399,7 +404,8 @@ test "Reader.readUntilDelimiterArrayList returns StreamTooLong, then an ArrayLis |
| 399 | 404 | var list = std.ArrayList(u8).init(a); |
| 400 | 405 | defer list.deinit(); |
| 401 | 406 | |
| 402 | const reader = std.io.fixedBufferStream("1234567\n").reader(); | |
| 407 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 408 | const reader = fis.reader(); | |
| 403 | 409 | |
| 404 | 410 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5)); |
| 405 | 411 | try std.testing.expectEqualStrings("12345", list.items); |
| ... | ... | @@ -412,7 +418,8 @@ test "Reader.readUntilDelimiterArrayList returns EndOfStream" { |
| 412 | 418 | var list = std.ArrayList(u8).init(a); |
| 413 | 419 | defer list.deinit(); |
| 414 | 420 | |
| 415 | const reader = std.io.fixedBufferStream("1234").reader(); | |
| 421 | var fis = std.io.fixedBufferStream("1234"); | |
| 422 | const reader = fis.reader(); | |
| 416 | 423 | |
| 417 | 424 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5)); |
| 418 | 425 | try std.testing.expectEqualStrings("1234", list.items); |
| ... | ... | @@ -421,7 +428,8 @@ test "Reader.readUntilDelimiterArrayList returns EndOfStream" { |
| 421 | 428 | test "Reader.readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { |
| 422 | 429 | const a = std.testing.allocator; |
| 423 | 430 | |
| 424 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); | |
| 431 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 432 | const reader = fis.reader(); | |
| 425 | 433 | |
| 426 | 434 | { |
| 427 | 435 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| ... | ... | @@ -441,7 +449,8 @@ test "Reader.readUntilDelimiterAlloc returns ArrayLists with bytes read until th |
| 441 | 449 | test "Reader.readUntilDelimiterAlloc returns an empty ArrayList" { |
| 442 | 450 | const a = std.testing.allocator; |
| 443 | 451 | |
| 444 | const reader = std.io.fixedBufferStream("\n").reader(); | |
| 452 | var fis = std.io.fixedBufferStream("\n"); | |
| 453 | const reader = fis.reader(); | |
| 445 | 454 | |
| 446 | 455 | { |
| 447 | 456 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| ... | ... | @@ -453,7 +462,8 @@ test "Reader.readUntilDelimiterAlloc returns an empty ArrayList" { |
| 453 | 462 | test "Reader.readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { |
| 454 | 463 | const a = std.testing.allocator; |
| 455 | 464 | |
| 456 | const reader = std.io.fixedBufferStream("1234567\n").reader(); | |
| 465 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 466 | const reader = fis.reader(); | |
| 457 | 467 | |
| 458 | 468 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5)); |
| 459 | 469 | |
| ... | ... | @@ -465,67 +475,77 @@ test "Reader.readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList wi |
| 465 | 475 | test "Reader.readUntilDelimiterAlloc returns EndOfStream" { |
| 466 | 476 | const a = std.testing.allocator; |
| 467 | 477 | |
| 468 | const reader = std.io.fixedBufferStream("1234").reader(); | |
| 478 | var fis = std.io.fixedBufferStream("1234"); | |
| 479 | const reader = fis.reader(); | |
| 469 | 480 | |
| 470 | 481 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5)); |
| 471 | 482 | } |
| 472 | 483 | |
| 473 | 484 | test "Reader.readUntilDelimiter returns bytes read until the delimiter" { |
| 474 | 485 | var buf: [5]u8 = undefined; |
| 475 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); | |
| 486 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 487 | const reader = fis.reader(); | |
| 476 | 488 | try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n')); |
| 477 | 489 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); |
| 478 | 490 | } |
| 479 | 491 | |
| 480 | 492 | test "Reader.readUntilDelimiter returns an empty string" { |
| 481 | 493 | var buf: [5]u8 = undefined; |
| 482 | const reader = std.io.fixedBufferStream("\n").reader(); | |
| 494 | var fis = std.io.fixedBufferStream("\n"); | |
| 495 | const reader = fis.reader(); | |
| 483 | 496 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); |
| 484 | 497 | } |
| 485 | 498 | |
| 486 | 499 | test "Reader.readUntilDelimiter returns StreamTooLong, then an empty string" { |
| 487 | 500 | var buf: [5]u8 = undefined; |
| 488 | const reader = std.io.fixedBufferStream("12345\n").reader(); | |
| 501 | var fis = std.io.fixedBufferStream("12345\n"); | |
| 502 | const reader = fis.reader(); | |
| 489 | 503 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| 490 | 504 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); |
| 491 | 505 | } |
| 492 | 506 | |
| 493 | 507 | test "Reader.readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" { |
| 494 | 508 | var buf: [5]u8 = undefined; |
| 495 | const reader = std.io.fixedBufferStream("1234567\n").reader(); | |
| 509 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 510 | const reader = fis.reader(); | |
| 496 | 511 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| 497 | 512 | try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n')); |
| 498 | 513 | } |
| 499 | 514 | |
| 500 | 515 | test "Reader.readUntilDelimiter returns EndOfStream" { |
| 501 | 516 | var buf: [5]u8 = undefined; |
| 502 | const reader = std.io.fixedBufferStream("").reader(); | |
| 517 | var fis = std.io.fixedBufferStream(""); | |
| 518 | const reader = fis.reader(); | |
| 503 | 519 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| 504 | 520 | } |
| 505 | 521 | |
| 506 | 522 | test "Reader.readUntilDelimiter returns bytes read until delimiter, then EndOfStream" { |
| 507 | 523 | var buf: [5]u8 = undefined; |
| 508 | const reader = std.io.fixedBufferStream("1234\n").reader(); | |
| 524 | var fis = std.io.fixedBufferStream("1234\n"); | |
| 525 | const reader = fis.reader(); | |
| 509 | 526 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); |
| 510 | 527 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| 511 | 528 | } |
| 512 | 529 | |
| 513 | 530 | test "Reader.readUntilDelimiter returns EndOfStream" { |
| 514 | 531 | var buf: [5]u8 = undefined; |
| 515 | const reader = std.io.fixedBufferStream("1234").reader(); | |
| 532 | var fis = std.io.fixedBufferStream("1234"); | |
| 533 | const reader = fis.reader(); | |
| 516 | 534 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| 517 | 535 | } |
| 518 | 536 | |
| 519 | 537 | test "Reader.readUntilDelimiter returns StreamTooLong, then EndOfStream" { |
| 520 | 538 | var buf: [5]u8 = undefined; |
| 521 | const reader = std.io.fixedBufferStream("12345").reader(); | |
| 539 | var fis = std.io.fixedBufferStream("12345"); | |
| 540 | const reader = fis.reader(); | |
| 522 | 541 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| 523 | 542 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| 524 | 543 | } |
| 525 | 544 | |
| 526 | 545 | test "Reader.readUntilDelimiter writes all bytes read to the output buffer" { |
| 527 | 546 | var buf: [5]u8 = undefined; |
| 528 | const reader = std.io.fixedBufferStream("0000\n12345").reader(); | |
| 547 | var fis = std.io.fixedBufferStream("0000\n12345"); | |
| 548 | const reader = fis.reader(); | |
| 529 | 549 | _ = try reader.readUntilDelimiter(&buf, '\n'); |
| 530 | 550 | try std.testing.expectEqualStrings("0000\n", &buf); |
| 531 | 551 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| ... | ... | @@ -535,7 +555,8 @@ test "Reader.readUntilDelimiter writes all bytes read to the output buffer" { |
| 535 | 555 | test "Reader.readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { |
| 536 | 556 | const a = std.testing.allocator; |
| 537 | 557 | |
| 538 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); | |
| 558 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 559 | const reader = fis.reader(); | |
| 539 | 560 | |
| 540 | 561 | { |
| 541 | 562 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| ... | ... | @@ -555,7 +576,8 @@ test "Reader.readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read unt |
| 555 | 576 | test "Reader.readUntilDelimiterOrEofAlloc returns an empty ArrayList" { |
| 556 | 577 | const a = std.testing.allocator; |
| 557 | 578 | |
| 558 | const reader = std.io.fixedBufferStream("\n").reader(); | |
| 579 | var fis = std.io.fixedBufferStream("\n"); | |
| 580 | const reader = fis.reader(); | |
| 559 | 581 | |
| 560 | 582 | { |
| 561 | 583 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| ... | ... | @@ -567,7 +589,8 @@ test "Reader.readUntilDelimiterOrEofAlloc returns an empty ArrayList" { |
| 567 | 589 | test "Reader.readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { |
| 568 | 590 | const a = std.testing.allocator; |
| 569 | 591 | |
| 570 | const reader = std.io.fixedBufferStream("1234567\n").reader(); | |
| 592 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 593 | const reader = fis.reader(); | |
| 571 | 594 | |
| 572 | 595 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)); |
| 573 | 596 | |
| ... | ... | @@ -578,60 +601,69 @@ test "Reader.readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayLi |
| 578 | 601 | |
| 579 | 602 | test "Reader.readUntilDelimiterOrEof returns bytes read until the delimiter" { |
| 580 | 603 | var buf: [5]u8 = undefined; |
| 581 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); | |
| 604 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 605 | const reader = fis.reader(); | |
| 582 | 606 | try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 583 | 607 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 584 | 608 | } |
| 585 | 609 | |
| 586 | 610 | test "Reader.readUntilDelimiterOrEof returns an empty string" { |
| 587 | 611 | var buf: [5]u8 = undefined; |
| 588 | const reader = std.io.fixedBufferStream("\n").reader(); | |
| 612 | var fis = std.io.fixedBufferStream("\n"); | |
| 613 | const reader = fis.reader(); | |
| 589 | 614 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 590 | 615 | } |
| 591 | 616 | |
| 592 | 617 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then an empty string" { |
| 593 | 618 | var buf: [5]u8 = undefined; |
| 594 | const reader = std.io.fixedBufferStream("12345\n").reader(); | |
| 619 | var fis = std.io.fixedBufferStream("12345\n"); | |
| 620 | const reader = fis.reader(); | |
| 595 | 621 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| 596 | 622 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 597 | 623 | } |
| 598 | 624 | |
| 599 | 625 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" { |
| 600 | 626 | var buf: [5]u8 = undefined; |
| 601 | const reader = std.io.fixedBufferStream("1234567\n").reader(); | |
| 627 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 628 | const reader = fis.reader(); | |
| 602 | 629 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| 603 | 630 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 604 | 631 | } |
| 605 | 632 | |
| 606 | 633 | test "Reader.readUntilDelimiterOrEof returns null" { |
| 607 | 634 | var buf: [5]u8 = undefined; |
| 608 | const reader = std.io.fixedBufferStream("").reader(); | |
| 635 | var fis = std.io.fixedBufferStream(""); | |
| 636 | const reader = fis.reader(); | |
| 609 | 637 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); |
| 610 | 638 | } |
| 611 | 639 | |
| 612 | 640 | test "Reader.readUntilDelimiterOrEof returns bytes read until delimiter, then null" { |
| 613 | 641 | var buf: [5]u8 = undefined; |
| 614 | const reader = std.io.fixedBufferStream("1234\n").reader(); | |
| 642 | var fis = std.io.fixedBufferStream("1234\n"); | |
| 643 | const reader = fis.reader(); | |
| 615 | 644 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 616 | 645 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); |
| 617 | 646 | } |
| 618 | 647 | |
| 619 | 648 | test "Reader.readUntilDelimiterOrEof returns bytes read until end-of-stream" { |
| 620 | 649 | var buf: [5]u8 = undefined; |
| 621 | const reader = std.io.fixedBufferStream("1234").reader(); | |
| 650 | var fis = std.io.fixedBufferStream("1234"); | |
| 651 | const reader = fis.reader(); | |
| 622 | 652 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 623 | 653 | } |
| 624 | 654 | |
| 625 | 655 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" { |
| 626 | 656 | var buf: [5]u8 = undefined; |
| 627 | const reader = std.io.fixedBufferStream("1234567").reader(); | |
| 657 | var fis = std.io.fixedBufferStream("1234567"); | |
| 658 | const reader = fis.reader(); | |
| 628 | 659 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| 629 | 660 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| 630 | 661 | } |
| 631 | 662 | |
| 632 | 663 | test "Reader.readUntilDelimiterOrEof writes all bytes read to the output buffer" { |
| 633 | 664 | var buf: [5]u8 = undefined; |
| 634 | const reader = std.io.fixedBufferStream("0000\n12345").reader(); | |
| 665 | var fis = std.io.fixedBufferStream("0000\n12345"); | |
| 666 | const reader = fis.reader(); | |
| 635 | 667 | _ = try reader.readUntilDelimiterOrEof(&buf, '\n'); |
| 636 | 668 | try std.testing.expectEqualStrings("0000\n", &buf); |
| 637 | 669 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
lib/std/json.zig+136-85| ... | ... | @@ -1506,42 +1506,46 @@ fn skipValue(tokens: *TokenStream) SkipValueError!void { |
| 1506 | 1506 | } |
| 1507 | 1507 | |
| 1508 | 1508 | test "skipValue" { |
| 1509 | try skipValue(&TokenStream.init("false")); | |
| 1510 | try skipValue(&TokenStream.init("true")); | |
| 1511 | try skipValue(&TokenStream.init("null")); | |
| 1512 | try skipValue(&TokenStream.init("42")); | |
| 1513 | try skipValue(&TokenStream.init("42.0")); | |
| 1514 | try skipValue(&TokenStream.init("\"foo\"")); | |
| 1515 | try skipValue(&TokenStream.init("[101, 111, 121]")); | |
| 1516 | try skipValue(&TokenStream.init("{}")); | |
| 1517 | try skipValue(&TokenStream.init("{\"foo\": \"bar\"}")); | |
| 1509 | var ts = TokenStream.init("false"); | |
| 1510 | try skipValue(&ts); | |
| 1511 | ts = TokenStream.init("true"); | |
| 1512 | try skipValue(&ts); | |
| 1513 | ts = TokenStream.init("null"); | |
| 1514 | try skipValue(&ts); | |
| 1515 | ts = TokenStream.init("42"); | |
| 1516 | try skipValue(&ts); | |
| 1517 | ts = TokenStream.init("42.0"); | |
| 1518 | try skipValue(&ts); | |
| 1519 | ts = TokenStream.init("\"foo\""); | |
| 1520 | try skipValue(&ts); | |
| 1521 | ts = TokenStream.init("[101, 111, 121]"); | |
| 1522 | try skipValue(&ts); | |
| 1523 | ts = TokenStream.init("{}"); | |
| 1524 | try skipValue(&ts); | |
| 1525 | ts = TokenStream.init("{\"foo\": \"bar\"}"); | |
| 1526 | try skipValue(&ts); | |
| 1518 | 1527 | |
| 1519 | 1528 | { // An absurd number of nestings |
| 1520 | 1529 | const nestings = StreamingParser.default_max_nestings + 1; |
| 1521 | 1530 | |
| 1522 | try testing.expectError( | |
| 1523 | error.TooManyNestedItems, | |
| 1524 | skipValue(&TokenStream.init("[" ** nestings ++ "]" ** nestings)), | |
| 1525 | ); | |
| 1531 | ts = TokenStream.init("[" ** nestings ++ "]" ** nestings); | |
| 1532 | try testing.expectError(error.TooManyNestedItems, skipValue(&ts)); | |
| 1526 | 1533 | } |
| 1527 | 1534 | |
| 1528 | 1535 | { // Would a number token cause problems in a deeply-nested array? |
| 1529 | 1536 | const nestings = StreamingParser.default_max_nestings; |
| 1530 | 1537 | const deeply_nested_array = "[" ** nestings ++ "0.118, 999, 881.99, 911.9, 725, 3" ++ "]" ** nestings; |
| 1531 | 1538 | |
| 1532 | try skipValue(&TokenStream.init(deeply_nested_array)); | |
| 1539 | ts = TokenStream.init(deeply_nested_array); | |
| 1540 | try skipValue(&ts); | |
| 1533 | 1541 | |
| 1534 | try testing.expectError( | |
| 1535 | error.TooManyNestedItems, | |
| 1536 | skipValue(&TokenStream.init("[" ++ deeply_nested_array ++ "]")), | |
| 1537 | ); | |
| 1542 | ts = TokenStream.init("[" ++ deeply_nested_array ++ "]"); | |
| 1543 | try testing.expectError(error.TooManyNestedItems, skipValue(&ts)); | |
| 1538 | 1544 | } |
| 1539 | 1545 | |
| 1540 | 1546 | // Mismatched brace/square bracket |
| 1541 | try testing.expectError( | |
| 1542 | error.UnexpectedClosingBrace, | |
| 1543 | skipValue(&TokenStream.init("[102, 111, 111}")), | |
| 1544 | ); | |
| 1547 | ts = TokenStream.init("[102, 111, 111}"); | |
| 1548 | try testing.expectError(error.UnexpectedClosingBrace, skipValue(&ts)); | |
| 1545 | 1549 | |
| 1546 | 1550 | { // should fail if no value found (e.g. immediate close of object) |
| 1547 | 1551 | var empty_object = TokenStream.init("{}"); |
| ... | ... | @@ -1980,18 +1984,29 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void { |
| 1980 | 1984 | } |
| 1981 | 1985 | |
| 1982 | 1986 | test "parse" { |
| 1983 | try testing.expectEqual(false, try parse(bool, &TokenStream.init("false"), ParseOptions{})); | |
| 1984 | try testing.expectEqual(true, try parse(bool, &TokenStream.init("true"), ParseOptions{})); | |
| 1985 | try testing.expectEqual(@as(u1, 1), try parse(u1, &TokenStream.init("1"), ParseOptions{})); | |
| 1986 | try testing.expectError(error.Overflow, parse(u1, &TokenStream.init("50"), ParseOptions{})); | |
| 1987 | try testing.expectEqual(@as(u64, 42), try parse(u64, &TokenStream.init("42"), ParseOptions{})); | |
| 1988 | try testing.expectEqual(@as(f64, 42), try parse(f64, &TokenStream.init("42.0"), ParseOptions{})); | |
| 1989 | try testing.expectEqual(@as(?bool, null), try parse(?bool, &TokenStream.init("null"), ParseOptions{})); | |
| 1990 | try testing.expectEqual(@as(?bool, true), try parse(?bool, &TokenStream.init("true"), ParseOptions{})); | |
| 1991 | ||
| 1992 | try testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("\"foo\""), ParseOptions{})); | |
| 1993 | try testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("[102, 111, 111]"), ParseOptions{})); | |
| 1994 | try testing.expectEqual(@as([0]u8, undefined), try parse([0]u8, &TokenStream.init("[]"), ParseOptions{})); | |
| 1987 | var ts = TokenStream.init("false"); | |
| 1988 | try testing.expectEqual(false, try parse(bool, &ts, ParseOptions{})); | |
| 1989 | ts = TokenStream.init("true"); | |
| 1990 | try testing.expectEqual(true, try parse(bool, &ts, ParseOptions{})); | |
| 1991 | ts = TokenStream.init("1"); | |
| 1992 | try testing.expectEqual(@as(u1, 1), try parse(u1, &ts, ParseOptions{})); | |
| 1993 | ts = TokenStream.init("50"); | |
| 1994 | try testing.expectError(error.Overflow, parse(u1, &ts, ParseOptions{})); | |
| 1995 | ts = TokenStream.init("42"); | |
| 1996 | try testing.expectEqual(@as(u64, 42), try parse(u64, &ts, ParseOptions{})); | |
| 1997 | ts = TokenStream.init("42.0"); | |
| 1998 | try testing.expectEqual(@as(f64, 42), try parse(f64, &ts, ParseOptions{})); | |
| 1999 | ts = TokenStream.init("null"); | |
| 2000 | try testing.expectEqual(@as(?bool, null), try parse(?bool, &ts, ParseOptions{})); | |
| 2001 | ts = TokenStream.init("true"); | |
| 2002 | try testing.expectEqual(@as(?bool, true), try parse(?bool, &ts, ParseOptions{})); | |
| 2003 | ||
| 2004 | ts = TokenStream.init("\"foo\""); | |
| 2005 | try testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &ts, ParseOptions{})); | |
| 2006 | ts = TokenStream.init("[102, 111, 111]"); | |
| 2007 | try testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &ts, ParseOptions{})); | |
| 2008 | ts = TokenStream.init("[]"); | |
| 2009 | try testing.expectEqual(@as([0]u8, undefined), try parse([0]u8, &ts, ParseOptions{})); | |
| 1995 | 2010 | } |
| 1996 | 2011 | |
| 1997 | 2012 | test "parse into enum" { |
| ... | ... | @@ -2000,36 +2015,48 @@ test "parse into enum" { |
| 2000 | 2015 | Bar, |
| 2001 | 2016 | @"with\\escape", |
| 2002 | 2017 | }; |
| 2003 | try testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("\"Foo\""), ParseOptions{})); | |
| 2004 | try testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("42"), ParseOptions{})); | |
| 2005 | try testing.expectEqual(@as(T, .@"with\\escape"), try parse(T, &TokenStream.init("\"with\\\\escape\""), ParseOptions{})); | |
| 2006 | try testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("5"), ParseOptions{})); | |
| 2007 | try testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("\"Qux\""), ParseOptions{})); | |
| 2018 | var ts = TokenStream.init("\"Foo\""); | |
| 2019 | try testing.expectEqual(@as(T, .Foo), try parse(T, &ts, ParseOptions{})); | |
| 2020 | ts = TokenStream.init("42"); | |
| 2021 | try testing.expectEqual(@as(T, .Foo), try parse(T, &ts, ParseOptions{})); | |
| 2022 | ts = TokenStream.init("\"with\\\\escape\""); | |
| 2023 | try testing.expectEqual(@as(T, .@"with\\escape"), try parse(T, &ts, ParseOptions{})); | |
| 2024 | ts = TokenStream.init("5"); | |
| 2025 | try testing.expectError(error.InvalidEnumTag, parse(T, &ts, ParseOptions{})); | |
| 2026 | ts = TokenStream.init("\"Qux\""); | |
| 2027 | try testing.expectError(error.InvalidEnumTag, parse(T, &ts, ParseOptions{})); | |
| 2008 | 2028 | } |
| 2009 | 2029 | |
| 2010 | 2030 | test "parse with trailing data" { |
| 2011 | try testing.expectEqual(false, try parse(bool, &TokenStream.init("falsed"), ParseOptions{ .allow_trailing_data = true })); | |
| 2012 | try testing.expectError(error.InvalidTopLevelTrailing, parse(bool, &TokenStream.init("falsed"), ParseOptions{ .allow_trailing_data = false })); | |
| 2031 | var ts = TokenStream.init("falsed"); | |
| 2032 | try testing.expectEqual(false, try parse(bool, &ts, ParseOptions{ .allow_trailing_data = true })); | |
| 2033 | ts = TokenStream.init("falsed"); | |
| 2034 | try testing.expectError(error.InvalidTopLevelTrailing, parse(bool, &ts, ParseOptions{ .allow_trailing_data = false })); | |
| 2013 | 2035 | // trailing whitespace is okay |
| 2014 | try testing.expectEqual(false, try parse(bool, &TokenStream.init("false \n"), ParseOptions{ .allow_trailing_data = false })); | |
| 2036 | ts = TokenStream.init("false \n"); | |
| 2037 | try testing.expectEqual(false, try parse(bool, &ts, ParseOptions{ .allow_trailing_data = false })); | |
| 2015 | 2038 | } |
| 2016 | 2039 | |
| 2017 | 2040 | test "parse into that allocates a slice" { |
| 2018 | try testing.expectError(error.AllocatorRequired, parse([]u8, &TokenStream.init("\"foo\""), ParseOptions{})); | |
| 2041 | var ts = TokenStream.init("\"foo\""); | |
| 2042 | try testing.expectError(error.AllocatorRequired, parse([]u8, &ts, ParseOptions{})); | |
| 2019 | 2043 | |
| 2020 | 2044 | const options = ParseOptions{ .allocator = testing.allocator }; |
| 2021 | 2045 | { |
| 2022 | const r = try parse([]u8, &TokenStream.init("\"foo\""), options); | |
| 2046 | ts = TokenStream.init("\"foo\""); | |
| 2047 | const r = try parse([]u8, &ts, options); | |
| 2023 | 2048 | defer parseFree([]u8, r, options); |
| 2024 | 2049 | try testing.expectEqualSlices(u8, "foo", r); |
| 2025 | 2050 | } |
| 2026 | 2051 | { |
| 2027 | const r = try parse([]u8, &TokenStream.init("[102, 111, 111]"), options); | |
| 2052 | ts = TokenStream.init("[102, 111, 111]"); | |
| 2053 | const r = try parse([]u8, &ts, options); | |
| 2028 | 2054 | defer parseFree([]u8, r, options); |
| 2029 | 2055 | try testing.expectEqualSlices(u8, "foo", r); |
| 2030 | 2056 | } |
| 2031 | 2057 | { |
| 2032 | const r = try parse([]u8, &TokenStream.init("\"with\\\\escape\""), options); | |
| 2058 | ts = TokenStream.init("\"with\\\\escape\""); | |
| 2059 | const r = try parse([]u8, &ts, options); | |
| 2033 | 2060 | defer parseFree([]u8, r, options); |
| 2034 | 2061 | try testing.expectEqualSlices(u8, "with\\escape", r); |
| 2035 | 2062 | } |
| ... | ... | @@ -2042,7 +2069,8 @@ test "parse into tagged union" { |
| 2042 | 2069 | float: f64, |
| 2043 | 2070 | string: []const u8, |
| 2044 | 2071 | }; |
| 2045 | try testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{})); | |
| 2072 | var ts = TokenStream.init("1.5"); | |
| 2073 | try testing.expectEqual(T{ .float = 1.5 }, try parse(T, &ts, ParseOptions{})); | |
| 2046 | 2074 | } |
| 2047 | 2075 | |
| 2048 | 2076 | { // failing allocations should be bubbled up instantly without trying next member |
| ... | ... | @@ -2053,7 +2081,8 @@ test "parse into tagged union" { |
| 2053 | 2081 | string: []const u8, |
| 2054 | 2082 | array: [3]u8, |
| 2055 | 2083 | }; |
| 2056 | try testing.expectError(error.OutOfMemory, parse(T, &TokenStream.init("[1,2,3]"), options)); | |
| 2084 | var ts = TokenStream.init("[1,2,3]"); | |
| 2085 | try testing.expectError(error.OutOfMemory, parse(T, &ts, options)); | |
| 2057 | 2086 | } |
| 2058 | 2087 | |
| 2059 | 2088 | { |
| ... | ... | @@ -2062,7 +2091,8 @@ test "parse into tagged union" { |
| 2062 | 2091 | x: u8, |
| 2063 | 2092 | y: u8, |
| 2064 | 2093 | }; |
| 2065 | try testing.expectEqual(T{ .x = 42 }, try parse(T, &TokenStream.init("42"), ParseOptions{})); | |
| 2094 | var ts = TokenStream.init("42"); | |
| 2095 | try testing.expectEqual(T{ .x = 42 }, try parse(T, &ts, ParseOptions{})); | |
| 2066 | 2096 | } |
| 2067 | 2097 | |
| 2068 | 2098 | { // needs to back out when first union member doesn't match |
| ... | ... | @@ -2070,7 +2100,8 @@ test "parse into tagged union" { |
| 2070 | 2100 | A: struct { x: u32 }, |
| 2071 | 2101 | B: struct { y: u32 }, |
| 2072 | 2102 | }; |
| 2073 | try testing.expectEqual(T{ .B = .{ .y = 42 } }, try parse(T, &TokenStream.init("{\"y\":42}"), ParseOptions{})); | |
| 2103 | var ts = TokenStream.init("{\"y\":42}"); | |
| 2104 | try testing.expectEqual(T{ .B = .{ .y = 42 } }, try parse(T, &ts, ParseOptions{})); | |
| 2074 | 2105 | } |
| 2075 | 2106 | } |
| 2076 | 2107 | |
| ... | ... | @@ -2080,7 +2111,8 @@ test "parse union bubbles up AllocatorRequired" { |
| 2080 | 2111 | string: []const u8, |
| 2081 | 2112 | int: i32, |
| 2082 | 2113 | }; |
| 2083 | try testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("42"), ParseOptions{})); | |
| 2114 | var ts = TokenStream.init("42"); | |
| 2115 | try testing.expectError(error.AllocatorRequired, parse(T, &ts, ParseOptions{})); | |
| 2084 | 2116 | } |
| 2085 | 2117 | |
| 2086 | 2118 | { // string member not first in union (and matching) |
| ... | ... | @@ -2089,7 +2121,8 @@ test "parse union bubbles up AllocatorRequired" { |
| 2089 | 2121 | float: f64, |
| 2090 | 2122 | string: []const u8, |
| 2091 | 2123 | }; |
| 2092 | try testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); | |
| 2124 | var ts = TokenStream.init("\"foo\""); | |
| 2125 | try testing.expectError(error.AllocatorRequired, parse(T, &ts, ParseOptions{})); | |
| 2093 | 2126 | } |
| 2094 | 2127 | } |
| 2095 | 2128 | |
| ... | ... | @@ -2102,7 +2135,8 @@ test "parseFree descends into tagged union" { |
| 2102 | 2135 | string: []const u8, |
| 2103 | 2136 | }; |
| 2104 | 2137 | // use a string with unicode escape so we know result can't be a reference to global constant |
| 2105 | const r = try parse(T, &TokenStream.init("\"with\\u0105unicode\""), options); | |
| 2138 | var ts = TokenStream.init("\"with\\u0105unicode\""); | |
| 2139 | const r = try parse(T, &ts, options); | |
| 2106 | 2140 | try testing.expectEqual(std.meta.Tag(T).string, @as(std.meta.Tag(T), r)); |
| 2107 | 2141 | try testing.expectEqualSlices(u8, "withąunicode", r.string); |
| 2108 | 2142 | try testing.expectEqual(@as(usize, 0), fail_alloc.deallocations); |
| ... | ... | @@ -2116,12 +2150,13 @@ test "parse with comptime field" { |
| 2116 | 2150 | comptime a: i32 = 0, |
| 2117 | 2151 | b: bool, |
| 2118 | 2152 | }; |
| 2119 | try testing.expectEqual(T{ .a = 0, .b = true }, try parse(T, &TokenStream.init( | |
| 2153 | var ts = TokenStream.init( | |
| 2120 | 2154 | \\{ |
| 2121 | 2155 | \\ "a": 0, |
| 2122 | 2156 | \\ "b": true |
| 2123 | 2157 | \\} |
| 2124 | ), ParseOptions{})); | |
| 2158 | ); | |
| 2159 | try testing.expectEqual(T{ .a = 0, .b = true }, try parse(T, &ts, ParseOptions{})); | |
| 2125 | 2160 | } |
| 2126 | 2161 | |
| 2127 | 2162 | { // string comptime values currently require an allocator |
| ... | ... | @@ -2140,12 +2175,13 @@ test "parse with comptime field" { |
| 2140 | 2175 | .allocator = std.testing.allocator, |
| 2141 | 2176 | }; |
| 2142 | 2177 | |
| 2143 | const r = try parse(T, &TokenStream.init( | |
| 2178 | var ts = TokenStream.init( | |
| 2144 | 2179 | \\{ |
| 2145 | 2180 | \\ "kind": "float", |
| 2146 | 2181 | \\ "b": 1.0 |
| 2147 | 2182 | \\} |
| 2148 | ), options); | |
| 2183 | ); | |
| 2184 | const r = try parse(T, &ts, options); | |
| 2149 | 2185 | |
| 2150 | 2186 | // check that parseFree doesn't try to free comptime fields |
| 2151 | 2187 | parseFree(T, r, options); |
| ... | ... | @@ -2154,7 +2190,8 @@ test "parse with comptime field" { |
| 2154 | 2190 | |
| 2155 | 2191 | test "parse into struct with no fields" { |
| 2156 | 2192 | const T = struct {}; |
| 2157 | try testing.expectEqual(T{}, try parse(T, &TokenStream.init("{}"), ParseOptions{})); | |
| 2193 | var ts = TokenStream.init("{}"); | |
| 2194 | try testing.expectEqual(T{}, try parse(T, &ts, ParseOptions{})); | |
| 2158 | 2195 | } |
| 2159 | 2196 | |
| 2160 | 2197 | test "parse into struct with misc fields" { |
| ... | ... | @@ -2186,7 +2223,7 @@ test "parse into struct with misc fields" { |
| 2186 | 2223 | string: []const u8, |
| 2187 | 2224 | }; |
| 2188 | 2225 | }; |
| 2189 | const r = try parse(T, &TokenStream.init( | |
| 2226 | var ts = TokenStream.init( | |
| 2190 | 2227 | \\{ |
| 2191 | 2228 | \\ "int": 420, |
| 2192 | 2229 | \\ "float": 3.14, |
| ... | ... | @@ -2208,7 +2245,8 @@ test "parse into struct with misc fields" { |
| 2208 | 2245 | \\ ], |
| 2209 | 2246 | \\ "a_union": 100000 |
| 2210 | 2247 | \\} |
| 2211 | ), options); | |
| 2248 | ); | |
| 2249 | const r = try parse(T, &ts, options); | |
| 2212 | 2250 | defer parseFree(T, r, options); |
| 2213 | 2251 | try testing.expectEqual(@as(i64, 420), r.int); |
| 2214 | 2252 | try testing.expectEqual(@as(f64, 3.14), r.float); |
| ... | ... | @@ -2239,14 +2277,15 @@ test "parse into struct with strings and arrays with sentinels" { |
| 2239 | 2277 | data: [:99]const i32, |
| 2240 | 2278 | simple_data: []const i32, |
| 2241 | 2279 | }; |
| 2242 | const r = try parse(T, &TokenStream.init( | |
| 2280 | var ts = TokenStream.init( | |
| 2243 | 2281 | \\{ |
| 2244 | 2282 | \\ "language": "zig", |
| 2245 | 2283 | \\ "language_without_sentinel": "zig again!", |
| 2246 | 2284 | \\ "data": [1, 2, 3], |
| 2247 | 2285 | \\ "simple_data": [4, 5, 6] |
| 2248 | 2286 | \\} |
| 2249 | ), options); | |
| 2287 | ); | |
| 2288 | const r = try parse(T, &ts, options); | |
| 2250 | 2289 | defer parseFree(T, r, options); |
| 2251 | 2290 | |
| 2252 | 2291 | try testing.expectEqualSentinel(u8, 0, "zig", r.language); |
| ... | ... | @@ -2275,19 +2314,25 @@ test "parse into struct with duplicate field" { |
| 2275 | 2314 | |
| 2276 | 2315 | const T1 = struct { a: *u64 }; |
| 2277 | 2316 | // both .UseFirst and .UseLast should fail because second "a" value isn't a u64 |
| 2278 | try testing.expectError(error.InvalidNumber, parse(T1, &TokenStream.init(str), options_first)); | |
| 2279 | try testing.expectError(error.InvalidNumber, parse(T1, &TokenStream.init(str), options_last)); | |
| 2317 | var ts = TokenStream.init(str); | |
| 2318 | try testing.expectError(error.InvalidNumber, parse(T1, &ts, options_first)); | |
| 2319 | ts = TokenStream.init(str); | |
| 2320 | try testing.expectError(error.InvalidNumber, parse(T1, &ts, options_last)); | |
| 2280 | 2321 | |
| 2281 | 2322 | const T2 = struct { a: f64 }; |
| 2282 | try testing.expectEqual(T2{ .a = 1.0 }, try parse(T2, &TokenStream.init(str), options_first)); | |
| 2283 | try testing.expectEqual(T2{ .a = 0.25 }, try parse(T2, &TokenStream.init(str), options_last)); | |
| 2323 | ts = TokenStream.init(str); | |
| 2324 | try testing.expectEqual(T2{ .a = 1.0 }, try parse(T2, &ts, options_first)); | |
| 2325 | ts = TokenStream.init(str); | |
| 2326 | try testing.expectEqual(T2{ .a = 0.25 }, try parse(T2, &ts, options_last)); | |
| 2284 | 2327 | |
| 2285 | 2328 | const T3 = struct { comptime a: f64 = 1.0 }; |
| 2286 | 2329 | // .UseFirst should succeed because second "a" value is unconditionally ignored (even though != 1.0) |
| 2287 | 2330 | const t3 = T3{ .a = 1.0 }; |
| 2288 | try testing.expectEqual(t3, try parse(T3, &TokenStream.init(str), options_first)); | |
| 2331 | ts = TokenStream.init(str); | |
| 2332 | try testing.expectEqual(t3, try parse(T3, &ts, options_first)); | |
| 2289 | 2333 | // .UseLast should fail because second "a" value is 0.25 which is not equal to default value of 1.0 |
| 2290 | try testing.expectError(error.UnexpectedValue, parse(T3, &TokenStream.init(str), options_last)); | |
| 2334 | ts = TokenStream.init(str); | |
| 2335 | try testing.expectError(error.UnexpectedValue, parse(T3, &ts, options_last)); | |
| 2291 | 2336 | } |
| 2292 | 2337 | |
| 2293 | 2338 | test "parse into struct ignoring unknown fields" { |
| ... | ... | @@ -2301,7 +2346,7 @@ test "parse into struct ignoring unknown fields" { |
| 2301 | 2346 | .ignore_unknown_fields = true, |
| 2302 | 2347 | }; |
| 2303 | 2348 | |
| 2304 | const r = try parse(T, &std.json.TokenStream.init( | |
| 2349 | var ts = TokenStream.init( | |
| 2305 | 2350 | \\{ |
| 2306 | 2351 | \\ "int": 420, |
| 2307 | 2352 | \\ "float": 3.14, |
| ... | ... | @@ -2323,7 +2368,8 @@ test "parse into struct ignoring unknown fields" { |
| 2323 | 2368 | \\ "a_union": 100000, |
| 2324 | 2369 | \\ "language": "zig" |
| 2325 | 2370 | \\} |
| 2326 | ), ops); | |
| 2371 | ); | |
| 2372 | const r = try parse(T, &ts, ops); | |
| 2327 | 2373 | defer parseFree(T, r, ops); |
| 2328 | 2374 | |
| 2329 | 2375 | try testing.expectEqual(@as(i64, 420), r.int); |
| ... | ... | @@ -2341,7 +2387,8 @@ test "parse into recursive union definition" { |
| 2341 | 2387 | }; |
| 2342 | 2388 | const ops = ParseOptions{ .allocator = testing.allocator }; |
| 2343 | 2389 | |
| 2344 | const r = try parse(T, &std.json.TokenStream.init("{\"values\":[58]}"), ops); | |
| 2390 | var ts = TokenStream.init("{\"values\":[58]}"); | |
| 2391 | const r = try parse(T, &ts, ops); | |
| 2345 | 2392 | defer parseFree(T, r, ops); |
| 2346 | 2393 | |
| 2347 | 2394 | try testing.expectEqual(@as(i64, 58), r.values.array[0].integer); |
| ... | ... | @@ -2363,7 +2410,8 @@ test "parse into double recursive union definition" { |
| 2363 | 2410 | }; |
| 2364 | 2411 | const ops = ParseOptions{ .allocator = testing.allocator }; |
| 2365 | 2412 | |
| 2366 | const r = try parse(T, &std.json.TokenStream.init("{\"values\":[[58]]}"), ops); | |
| 2413 | var ts = TokenStream.init("{\"values\":[[58]]}"); | |
| 2414 | const r = try parse(T, &ts, ops); | |
| 2367 | 2415 | defer parseFree(T, r, ops); |
| 2368 | 2416 | |
| 2369 | 2417 | try testing.expectEqual(@as(i64, 58), r.values.array[0].array[0].integer); |
| ... | ... | @@ -2806,10 +2854,13 @@ test "integer after float has proper type" { |
| 2806 | 2854 | |
| 2807 | 2855 | test "parse exponential into int" { |
| 2808 | 2856 | const T = struct { int: i64 }; |
| 2809 | const r = try parse(T, &TokenStream.init("{ \"int\": 4.2e2 }"), ParseOptions{}); | |
| 2857 | var ts = TokenStream.init("{ \"int\": 4.2e2 }"); | |
| 2858 | const r = try parse(T, &ts, ParseOptions{}); | |
| 2810 | 2859 | try testing.expectEqual(@as(i64, 420), r.int); |
| 2811 | try testing.expectError(error.InvalidNumber, parse(T, &TokenStream.init("{ \"int\": 0.042e2 }"), ParseOptions{})); | |
| 2812 | try testing.expectError(error.Overflow, parse(T, &TokenStream.init("{ \"int\": 18446744073709551616.0 }"), ParseOptions{})); | |
| 2860 | ts = TokenStream.init("{ \"int\": 0.042e2 }"); | |
| 2861 | try testing.expectError(error.InvalidNumber, parse(T, &ts, ParseOptions{})); | |
| 2862 | ts = TokenStream.init("{ \"int\": 18446744073709551616.0 }"); | |
| 2863 | try testing.expectError(error.Overflow, parse(T, &ts, ParseOptions{})); | |
| 2813 | 2864 | } |
| 2814 | 2865 | |
| 2815 | 2866 | test "escaped characters" { |
| ... | ... | @@ -2858,10 +2909,12 @@ test "string copy option" { |
| 2858 | 2909 | defer arena_allocator.deinit(); |
| 2859 | 2910 | const allocator = arena_allocator.allocator(); |
| 2860 | 2911 | |
| 2861 | const tree_nocopy = try Parser.init(allocator, false).parse(input); | |
| 2912 | var parser = Parser.init(allocator, false); | |
| 2913 | const tree_nocopy = try parser.parse(input); | |
| 2862 | 2914 | const obj_nocopy = tree_nocopy.root.Object; |
| 2863 | 2915 | |
| 2864 | const tree_copy = try Parser.init(allocator, true).parse(input); | |
| 2916 | parser = Parser.init(allocator, true); | |
| 2917 | const tree_copy = try parser.parse(input); | |
| 2865 | 2918 | const obj_copy = tree_copy.root.Object; |
| 2866 | 2919 | |
| 2867 | 2920 | for ([_][]const u8{ "noescape", "simple", "unicode", "surrogatepair" }) |field_name| { |
| ... | ... | @@ -3376,14 +3429,12 @@ test "stringify null optional fields" { |
| 3376 | 3429 | StringifyOptions{ .emit_null_optional_fields = false }, |
| 3377 | 3430 | ); |
| 3378 | 3431 | |
| 3379 | try std.testing.expect(try parsesTo( | |
| 3380 | MyStruct, | |
| 3381 | MyStruct{}, | |
| 3382 | &TokenStream.init( | |
| 3383 | \\{"required":"something","another_required":"something else"} | |
| 3384 | ), | |
| 3385 | .{ .allocator = std.testing.allocator }, | |
| 3386 | )); | |
| 3432 | var ts = TokenStream.init( | |
| 3433 | \\{"required":"something","another_required":"something else"} | |
| 3434 | ); | |
| 3435 | try std.testing.expect(try parsesTo(MyStruct, MyStruct{}, &ts, .{ | |
| 3436 | .allocator = std.testing.allocator, | |
| 3437 | })); | |
| 3387 | 3438 | } |
| 3388 | 3439 | |
| 3389 | 3440 | // Same as `stringify` but accepts an Allocator and stores result in dynamically allocated memory instead of using a Writer. |
lib/std/meta.zig+4-1| ... | ... | @@ -311,7 +311,10 @@ pub fn assumeSentinel(p: anytype, comptime sentinel_val: Elem(@TypeOf(p))) Senti |
| 311 | 311 | const ReturnType = Sentinel(T, sentinel_val); |
| 312 | 312 | switch (@typeInfo(T)) { |
| 313 | 313 | .Pointer => |info| switch (info.size) { |
| 314 | .Slice => return @bitCast(ReturnType, p), | |
| 314 | .Slice => if (@import("builtin").zig_backend == .stage1) | |
| 315 | return @bitCast(ReturnType, p) | |
| 316 | else | |
| 317 | return @ptrCast(ReturnType, p), | |
| 315 | 318 | .Many, .One => return @ptrCast(ReturnType, p), |
| 316 | 319 | .C => {}, |
| 317 | 320 | }, |
lib/std/net.zig+7-5| ... | ... | @@ -1141,18 +1141,20 @@ fn linuxLookupNameFromHosts( |
| 1141 | 1141 | }; |
| 1142 | 1142 | defer file.close(); |
| 1143 | 1143 | |
| 1144 | const stream = std.io.bufferedReader(file.reader()).reader(); | |
| 1144 | var buffered_reader = std.io.bufferedReader(file.reader()); | |
| 1145 | const reader = buffered_reader.reader(); | |
| 1145 | 1146 | var line_buf: [512]u8 = undefined; |
| 1146 | while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { | |
| 1147 | while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { | |
| 1147 | 1148 | error.StreamTooLong => blk: { |
| 1148 | // Skip to the delimiter in the stream, to fix parsing | |
| 1149 | try stream.skipUntilDelimiterOrEof('\n'); | |
| 1149 | // Skip to the delimiter in the reader, to fix parsing | |
| 1150 | try reader.skipUntilDelimiterOrEof('\n'); | |
| 1150 | 1151 | // Use the truncated line. A truncated comment or hostname will be handled correctly. |
| 1151 | 1152 | break :blk &line_buf; |
| 1152 | 1153 | }, |
| 1153 | 1154 | else => |e| return e, |
| 1154 | 1155 | }) |line| { |
| 1155 | const no_comment_line = mem.split(u8, line, "#").next().?; | |
| 1156 | var split_it = mem.split(u8, line, "#"); | |
| 1157 | const no_comment_line = split_it.next().?; | |
| 1156 | 1158 | |
| 1157 | 1159 | var line_it = mem.tokenize(u8, no_comment_line, " \t"); |
| 1158 | 1160 | const ip_text = line_it.next() orelse continue; |
lib/std/segmented_list.zig+4-1| ... | ... | @@ -391,7 +391,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | 393 | test "SegmentedList basic usage" { |
| 394 | try testSegmentedList(0); | |
| 394 | if (@import("builtin").zig_backend == .stage1) { | |
| 395 | // https://github.com/ziglang/zig/issues/11787 | |
| 396 | try testSegmentedList(0); | |
| 397 | } | |
| 395 | 398 | try testSegmentedList(1); |
| 396 | 399 | try testSegmentedList(2); |
| 397 | 400 | try testSegmentedList(4); |
lib/std/unicode.zig+1| ... | ... | @@ -804,6 +804,7 @@ pub fn fmtUtf16le(utf16le: []const u16) std.fmt.Formatter(formatUtf16le) { |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | 806 | test "fmtUtf16le" { |
| 807 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 807 | 808 | const expectFmt = std.testing.expectFmt; |
| 808 | 809 | try expectFmt("", "{}", .{fmtUtf16le(utf8ToUtf16LeStringLiteral(""))}); |
| 809 | 810 | try expectFmt("foo", "{}", .{fmtUtf16le(utf8ToUtf16LeStringLiteral("foo"))}); |
lib/std/x.zig+1| ... | ... | @@ -13,6 +13,7 @@ pub const net = struct { |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | 15 | test { |
| 16 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 16 | 17 | inline for (.{ os, net }) |module| { |
| 17 | 18 | std.testing.refAllDecls(module); |
| 18 | 19 | } |
lib/std/zig/c_translation.zig+29-7| ... | ... | @@ -8,10 +8,19 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { |
| 8 | 8 | // this function should behave like transCCast in translate-c, except it's for macros |
| 9 | 9 | const SourceType = @TypeOf(target); |
| 10 | 10 | switch (@typeInfo(DestType)) { |
| 11 | .Fn, .Pointer => return castToPtr(DestType, SourceType, target), | |
| 11 | .Fn => if (@import("builtin").zig_backend == .stage1) | |
| 12 | return castToPtr(DestType, SourceType, target) | |
| 13 | else | |
| 14 | return castToPtr(*const DestType, SourceType, target), | |
| 15 | .Pointer => return castToPtr(DestType, SourceType, target), | |
| 12 | 16 | .Optional => |dest_opt| { |
| 13 | if (@typeInfo(dest_opt.child) == .Pointer or @typeInfo(dest_opt.child) == .Fn) { | |
| 17 | if (@typeInfo(dest_opt.child) == .Pointer) { | |
| 14 | 18 | return castToPtr(DestType, SourceType, target); |
| 19 | } else if (@typeInfo(dest_opt.child) == .Fn) { | |
| 20 | if (@import("builtin").zig_backend == .stage1) | |
| 21 | return castToPtr(DestType, SourceType, target) | |
| 22 | else | |
| 23 | return castToPtr(?*const dest_opt.child, SourceType, target); | |
| 15 | 24 | } |
| 16 | 25 | }, |
| 17 | 26 | .Int => { |
| ... | ... | @@ -124,7 +133,10 @@ test "cast" { |
| 124 | 133 | try testing.expect(cast(?*anyopaque, -1) == @intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1)))); |
| 125 | 134 | try testing.expect(cast(?*anyopaque, foo) == @intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1)))); |
| 126 | 135 | |
| 127 | const FnPtr = ?fn (*anyopaque) void; | |
| 136 | const FnPtr = if (@import("builtin").zig_backend == .stage1) | |
| 137 | ?fn (*anyopaque) void | |
| 138 | else | |
| 139 | ?*const fn (*anyopaque) void; | |
| 128 | 140 | try testing.expect(cast(FnPtr, 0) == @intToPtr(FnPtr, @as(usize, 0))); |
| 129 | 141 | try testing.expect(cast(FnPtr, foo) == @intToPtr(FnPtr, @bitCast(usize, @as(isize, -1)))); |
| 130 | 142 | } |
| ... | ... | @@ -135,9 +147,14 @@ pub fn sizeof(target: anytype) usize { |
| 135 | 147 | switch (@typeInfo(T)) { |
| 136 | 148 | .Float, .Int, .Struct, .Union, .Array, .Bool, .Vector => return @sizeOf(T), |
| 137 | 149 | .Fn => { |
| 138 | // sizeof(main) returns 1, sizeof(&main) returns pointer size. | |
| 139 | // We cannot distinguish those types in Zig, so use pointer size. | |
| 140 | return @sizeOf(T); | |
| 150 | if (@import("builtin").zig_backend == .stage1) { | |
| 151 | // sizeof(main) returns 1, sizeof(&main) returns pointer size. | |
| 152 | // We cannot distinguish those types in Zig, so use pointer size. | |
| 153 | return @sizeOf(T); | |
| 154 | } | |
| 155 | ||
| 156 | // sizeof(main) in C returns 1 | |
| 157 | return 1; | |
| 141 | 158 | }, |
| 142 | 159 | .Null => return @sizeOf(*anyopaque), |
| 143 | 160 | .Void => { |
| ... | ... | @@ -233,7 +250,12 @@ test "sizeof" { |
| 233 | 250 | try testing.expect(sizeof(*const *const [4:0]u8) == ptr_size); |
| 234 | 251 | try testing.expect(sizeof(*const [4]u8) == ptr_size); |
| 235 | 252 | |
| 236 | try testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof))); | |
| 253 | if (@import("builtin").zig_backend == .stage1) { | |
| 254 | try testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof))); | |
| 255 | } else if (false) { // TODO | |
| 256 | try testing.expect(sizeof(&sizeof) == @sizeOf(@TypeOf(&sizeof))); | |
| 257 | try testing.expect(sizeof(sizeof) == 1); | |
| 258 | } | |
| 237 | 259 | |
| 238 | 260 | try testing.expect(sizeof(void) == 1); |
| 239 | 261 | try testing.expect(sizeof(anyopaque) == 1); |
src/Sema.zig+33-12| ... | ... | @@ -3598,7 +3598,7 @@ fn zirValidateArrayInit( |
| 3598 | 3598 | // any ZIR instructions at comptime; we need to do that here. |
| 3599 | 3599 | if (array_ty.sentinel()) |sentinel_val| { |
| 3600 | 3600 | const array_len_ref = try sema.addIntUnsigned(Type.usize, array_len); |
| 3601 | const sentinel_ptr = try sema.elemPtrArray(block, init_src, array_ptr, init_src, array_len_ref); | |
| 3601 | const sentinel_ptr = try sema.elemPtrArray(block, init_src, array_ptr, init_src, array_len_ref, true); | |
| 3602 | 3602 | const sentinel = try sema.addConstant(array_ty.childType(), sentinel_val); |
| 3603 | 3603 | try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store); |
| 3604 | 3604 | } |
| ... | ... | @@ -6654,7 +6654,11 @@ fn zirFunc( |
| 6654 | 6654 | src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data; |
| 6655 | 6655 | } |
| 6656 | 6656 | |
| 6657 | const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported) | |
| 6657 | // If this instruction has a body it means it's the type of the `owner_decl` | |
| 6658 | // otherwise it's a function type without a `callconv` attribute and should | |
| 6659 | // never be `.C`. | |
| 6660 | // NOTE: revisit when doing #1717 | |
| 6661 | const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported and has_body) | |
| 6658 | 6662 | .C |
| 6659 | 6663 | else |
| 6660 | 6664 | .Unspecified; |
| ... | ... | @@ -7540,7 +7544,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 7540 | 7544 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 7541 | 7545 | const array_ptr = try sema.resolveInst(bin_inst.lhs); |
| 7542 | 7546 | const elem_index = try sema.resolveInst(bin_inst.rhs); |
| 7543 | return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); | |
| 7547 | return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src, false); | |
| 7544 | 7548 | } |
| 7545 | 7549 | |
| 7546 | 7550 | fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -7553,7 +7557,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7553 | 7557 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 7554 | 7558 | const array_ptr = try sema.resolveInst(extra.lhs); |
| 7555 | 7559 | const elem_index = try sema.resolveInst(extra.rhs); |
| 7556 | return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | |
| 7560 | return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false); | |
| 7557 | 7561 | } |
| 7558 | 7562 | |
| 7559 | 7563 | fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -7565,7 +7569,7 @@ fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 7565 | 7569 | const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; |
| 7566 | 7570 | const array_ptr = try sema.resolveInst(extra.ptr); |
| 7567 | 7571 | const elem_index = try sema.addIntUnsigned(Type.usize, extra.index); |
| 7568 | return sema.elemPtr(block, src, array_ptr, elem_index, src); | |
| 7572 | return sema.elemPtr(block, src, array_ptr, elem_index, src, true); | |
| 7569 | 7573 | } |
| 7570 | 7574 | |
| 7571 | 7575 | fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -11547,7 +11551,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 11547 | 11551 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 11548 | 11552 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 11549 | 11553 | switch (ty.zigTypeTag()) { |
| 11550 | .Fn => unreachable, | |
| 11554 | .Fn, | |
| 11551 | 11555 | .NoReturn, |
| 11552 | 11556 | .Undefined, |
| 11553 | 11557 | .Null, |
| ... | ... | @@ -13465,7 +13469,12 @@ fn zirStructInit( |
| 13465 | 13469 | } |
| 13466 | 13470 | |
| 13467 | 13471 | if (is_ref) { |
| 13468 | const alloc = try block.addTy(.alloc, resolved_ty); | |
| 13472 | const target = sema.mod.getTarget(); | |
| 13473 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 13474 | .pointee_type = resolved_ty, | |
| 13475 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | |
| 13476 | }); | |
| 13477 | const alloc = try block.addTy(.alloc, alloc_ty); | |
| 13469 | 13478 | const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty); |
| 13470 | 13479 | try sema.storePtr(block, src, field_ptr, init_inst); |
| 13471 | 13480 | return alloc; |
| ... | ... | @@ -18719,6 +18728,7 @@ fn elemPtr( |
| 18719 | 18728 | indexable_ptr: Air.Inst.Ref, |
| 18720 | 18729 | elem_index: Air.Inst.Ref, |
| 18721 | 18730 | elem_index_src: LazySrcLoc, |
| 18731 | init: bool, | |
| 18722 | 18732 | ) CompileError!Air.Inst.Ref { |
| 18723 | 18733 | const indexable_ptr_src = src; // TODO better source location |
| 18724 | 18734 | const indexable_ptr_ty = sema.typeOf(indexable_ptr); |
| ... | ... | @@ -18755,11 +18765,11 @@ fn elemPtr( |
| 18755 | 18765 | }, |
| 18756 | 18766 | .One => { |
| 18757 | 18767 | assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable |
| 18758 | return sema.elemPtrArray(block, indexable_ptr_src, indexable, elem_index_src, elem_index); | |
| 18768 | return sema.elemPtrArray(block, indexable_ptr_src, indexable, elem_index_src, elem_index, init); | |
| 18759 | 18769 | }, |
| 18760 | 18770 | } |
| 18761 | 18771 | }, |
| 18762 | .Array, .Vector => return sema.elemPtrArray(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index), | |
| 18772 | .Array, .Vector => return sema.elemPtrArray(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init), | |
| 18763 | 18773 | .Struct => { |
| 18764 | 18774 | // Tuple field access. |
| 18765 | 18775 | const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index); |
| ... | ... | @@ -18813,7 +18823,7 @@ fn elemVal( |
| 18813 | 18823 | }, |
| 18814 | 18824 | .One => { |
| 18815 | 18825 | assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable |
| 18816 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src); | |
| 18826 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false); | |
| 18817 | 18827 | return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); |
| 18818 | 18828 | }, |
| 18819 | 18829 | }, |
| ... | ... | @@ -18994,6 +19004,7 @@ fn elemPtrArray( |
| 18994 | 19004 | array_ptr: Air.Inst.Ref, |
| 18995 | 19005 | elem_index_src: LazySrcLoc, |
| 18996 | 19006 | elem_index: Air.Inst.Ref, |
| 19007 | init: bool, | |
| 18997 | 19008 | ) CompileError!Air.Inst.Ref { |
| 18998 | 19009 | const target = sema.mod.getTarget(); |
| 18999 | 19010 | const array_ptr_ty = sema.typeOf(array_ptr); |
| ... | ... | @@ -19030,7 +19041,7 @@ fn elemPtrArray( |
| 19030 | 19041 | } |
| 19031 | 19042 | |
| 19032 | 19043 | const valid_rt = try sema.validateRunTimeType(block, elem_index_src, array_ty.elemType2(), false); |
| 19033 | if (!valid_rt) { | |
| 19044 | if (!valid_rt and !init) { | |
| 19034 | 19045 | const msg = msg: { |
| 19035 | 19046 | const msg = try sema.errMsg( |
| 19036 | 19047 | block, |
| ... | ... | @@ -20133,7 +20144,7 @@ fn storePtr2( |
| 20133 | 20144 | const elem_src = operand_src; // TODO better source location |
| 20134 | 20145 | const elem = try tupleField(sema, block, operand_src, uncasted_operand, elem_src, i); |
| 20135 | 20146 | const elem_index = try sema.addIntUnsigned(Type.usize, i); |
| 20136 | const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src); | |
| 20147 | const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false); | |
| 20137 | 20148 | try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store); |
| 20138 | 20149 | } |
| 20139 | 20150 | return; |
| ... | ... | @@ -20400,6 +20411,16 @@ fn beginComptimePtrMutation( |
| 20400 | 20411 | .ty = elem_ty, |
| 20401 | 20412 | }, |
| 20402 | 20413 | |
| 20414 | .the_only_possible_value => { | |
| 20415 | const duped = try sema.arena.create(Value); | |
| 20416 | duped.* = Value.initTag(.the_only_possible_value); | |
| 20417 | return ComptimePtrMutationKit{ | |
| 20418 | .decl_ref_mut = parent.decl_ref_mut, | |
| 20419 | .val = duped, | |
| 20420 | .ty = elem_ty, | |
| 20421 | }; | |
| 20422 | }, | |
| 20423 | ||
| 20403 | 20424 | else => unreachable, |
| 20404 | 20425 | } |
| 20405 | 20426 | }, |
src/codegen/llvm.zig+3-1| ... | ... | @@ -5389,7 +5389,9 @@ pub const FuncGen = struct { |
| 5389 | 5389 | } |
| 5390 | 5390 | llvm_constraints.appendSliceAssumeCapacity(constraint); |
| 5391 | 5391 | |
| 5392 | name_map.putAssumeCapacityNoClobber(name, {}); | |
| 5392 | if (!std.mem.eql(u8, name, "_")) { | |
| 5393 | name_map.putAssumeCapacityNoClobber(name, {}); | |
| 5394 | } | |
| 5393 | 5395 | llvm_param_i += 1; |
| 5394 | 5396 | total_i += 1; |
| 5395 | 5397 | } |
src/type.zig+23-11| ... | ... | @@ -784,7 +784,7 @@ pub const Type = extern union { |
| 784 | 784 | |
| 785 | 785 | .anyframe_T => { |
| 786 | 786 | if (b.zigTypeTag() != .AnyFrame) return false; |
| 787 | return a.childType().eql(b.childType(), mod); | |
| 787 | return a.elemType2().eql(b.elemType2(), mod); | |
| 788 | 788 | }, |
| 789 | 789 | |
| 790 | 790 | .empty_struct => { |
| ... | ... | @@ -2035,7 +2035,11 @@ pub const Type = extern union { |
| 2035 | 2035 | try writer.writeAll("fn("); |
| 2036 | 2036 | for (fn_info.param_types) |param_ty, i| { |
| 2037 | 2037 | if (i != 0) try writer.writeAll(", "); |
| 2038 | try print(param_ty, writer, mod); | |
| 2038 | if (param_ty.tag() == .generic_poison) { | |
| 2039 | try writer.writeAll("anytype"); | |
| 2040 | } else { | |
| 2041 | try print(param_ty, writer, mod); | |
| 2042 | } | |
| 2039 | 2043 | } |
| 2040 | 2044 | if (fn_info.is_var_args) { |
| 2041 | 2045 | if (fn_info.param_types.len != 0) { |
| ... | ... | @@ -2052,7 +2056,11 @@ pub const Type = extern union { |
| 2052 | 2056 | if (fn_info.alignment != 0) { |
| 2053 | 2057 | try writer.print("align({d}) ", .{fn_info.alignment}); |
| 2054 | 2058 | } |
| 2055 | try print(fn_info.return_type, writer, mod); | |
| 2059 | if (fn_info.return_type.tag() == .generic_poison) { | |
| 2060 | try writer.writeAll("anytype"); | |
| 2061 | } else { | |
| 2062 | try print(fn_info.return_type, writer, mod); | |
| 2063 | } | |
| 2056 | 2064 | }, |
| 2057 | 2065 | |
| 2058 | 2066 | .error_union => { |
| ... | ... | @@ -4125,14 +4133,15 @@ pub const Type = extern union { |
| 4125 | 4133 | /// TODO this is deprecated in favor of `childType`. |
| 4126 | 4134 | pub const elemType = childType; |
| 4127 | 4135 | |
| 4128 | /// For *[N]T, returns T. | |
| 4129 | /// For ?*T, returns T. | |
| 4130 | /// For ?*[N]T, returns T. | |
| 4131 | /// For ?[*]T, returns T. | |
| 4132 | /// For *T, returns T. | |
| 4133 | /// For [*]T, returns T. | |
| 4134 | /// For [N]T, returns T. | |
| 4135 | /// For []T, returns T. | |
| 4136 | /// For *[N]T, returns T. | |
| 4137 | /// For ?*T, returns T. | |
| 4138 | /// For ?*[N]T, returns T. | |
| 4139 | /// For ?[*]T, returns T. | |
| 4140 | /// For *T, returns T. | |
| 4141 | /// For [*]T, returns T. | |
| 4142 | /// For [N]T, returns T. | |
| 4143 | /// For []T, returns T. | |
| 4144 | /// For anyframe->T, returns T. | |
| 4136 | 4145 | pub fn elemType2(ty: Type) Type { |
| 4137 | 4146 | return switch (ty.tag()) { |
| 4138 | 4147 | .vector => ty.castTag(.vector).?.data.elem_type, |
| ... | ... | @@ -4173,6 +4182,9 @@ pub const Type = extern union { |
| 4173 | 4182 | .optional_single_mut_pointer => ty.castPointer().?.data, |
| 4174 | 4183 | .optional_single_const_pointer => ty.castPointer().?.data, |
| 4175 | 4184 | |
| 4185 | .anyframe_T => ty.castTag(.anyframe_T).?.data, | |
| 4186 | .@"anyframe" => Type.@"void", | |
| 4187 | ||
| 4176 | 4188 | else => unreachable, |
| 4177 | 4189 | }; |
| 4178 | 4190 | } |
src/value.zig+13-1| ... | ... | @@ -1174,6 +1174,10 @@ pub const Value = extern union { |
| 1174 | 1174 | return; |
| 1175 | 1175 | } |
| 1176 | 1176 | switch (ty.zigTypeTag()) { |
| 1177 | .Void => {}, | |
| 1178 | .Bool => { | |
| 1179 | buffer[0] = @boolToInt(val.toBool()); | |
| 1180 | }, | |
| 1177 | 1181 | .Int => { |
| 1178 | 1182 | var bigint_buffer: BigIntSpace = undefined; |
| 1179 | 1183 | const bigint = val.toBigInt(&bigint_buffer, target); |
| ... | ... | @@ -1291,6 +1295,14 @@ pub const Value = extern union { |
| 1291 | 1295 | ) Allocator.Error!Value { |
| 1292 | 1296 | const target = mod.getTarget(); |
| 1293 | 1297 | switch (ty.zigTypeTag()) { |
| 1298 | .Void => return Value.@"void", | |
| 1299 | .Bool => { | |
| 1300 | if (buffer[0] == 0) { | |
| 1301 | return Value.@"false"; | |
| 1302 | } else { | |
| 1303 | return Value.@"true"; | |
| 1304 | } | |
| 1305 | }, | |
| 1294 | 1306 | .Int => { |
| 1295 | 1307 | if (buffer.len == 0) return Value.zero; |
| 1296 | 1308 | const int_info = ty.intInfo(target); |
| ... | ... | @@ -1311,7 +1323,7 @@ pub const Value = extern union { |
| 1311 | 1323 | 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)), |
| 1312 | 1324 | else => unreachable, |
| 1313 | 1325 | }, |
| 1314 | .Array => { | |
| 1326 | .Array, .Vector => { | |
| 1315 | 1327 | const elem_ty = ty.childType(); |
| 1316 | 1328 | const elem_size = elem_ty.abiSize(target); |
| 1317 | 1329 | const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); |
test/behavior/array.zig+9| ... | ... | @@ -573,3 +573,12 @@ test "type coercion of pointer to anon struct literal to pointer to array" { |
| 573 | 573 | try S.doTheTest(); |
| 574 | 574 | comptime try S.doTheTest(); |
| 575 | 575 | } |
| 576 | ||
| 577 | test "array with comptime only element type" { | |
| 578 | const a = [_]type{ | |
| 579 | u32, | |
| 580 | i32, | |
| 581 | }; | |
| 582 | try testing.expect(a[0] == u32); | |
| 583 | try testing.expect(a[1] == i32); | |
| 584 | } |
test/cases/compile_errors/runtime_indexing_comptime_array.zig+6-6| ... | ... | @@ -23,9 +23,9 @@ pub export fn entry3() void { |
| 23 | 23 | // error |
| 24 | 24 | // backend=stage2,llvm |
| 25 | 25 | // |
| 26 | // :6:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known | |
| 27 | // :6:33: note: use '*const fn() callconv(.C) void' for a function pointer type | |
| 28 | // :13:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known | |
| 29 | // :13:33: note: use '*const fn() callconv(.C) void' for a function pointer type | |
| 30 | // :19:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known | |
| 31 | // :19:33: note: use '*const fn() callconv(.C) void' for a function pointer type | |
| 26 | // :6:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known | |
| 27 | // :6:5: note: use '*const fn() void' for a function pointer type | |
| 28 | // :13:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known | |
| 29 | // :13:5: note: use '*const fn() void' for a function pointer type | |
| 30 | // :19:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known | |
| 31 | // :19:5: note: use '*const fn() void' for a function pointer type |