| author | |
| committer | |
| log | fced9467e8eaa85315154f9567cf6da23246d1ef |
| tree | 86da1f855dc1ce247764469521a7649dfefd30a9 |
| parent | 221b194f284ecacccd208a2f760381f8d97805d7 |
15 files changed, 208 insertions(+), 230 deletions(-)
lib/std/Build/Step/CheckObject.zig+12-12| ... | @@ -1242,7 +1242,7 @@ const MachODumper = struct { | ... | @@ -1242,7 +1242,7 @@ const MachODumper = struct { |
| 1242 | } | 1242 | } |
| 1243 | 1243 | ||
| 1244 | fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void { | 1244 | fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void { |
| 1245 | var stream = std.io.fixedBufferStream(data); | 1245 | var stream: std.io.FixedBufferStream = .{ .buffer = data }; |
| 1246 | var creader = std.io.countingReader(stream.reader()); | 1246 | var creader = std.io.countingReader(stream.reader()); |
| 1247 | const reader = creader.reader(); | 1247 | const reader = creader.reader(); |
| 1248 | 1248 | ||
| ... | @@ -1354,7 +1354,7 @@ const MachODumper = struct { | ... | @@ -1354,7 +1354,7 @@ const MachODumper = struct { |
| 1354 | } | 1354 | } |
| 1355 | 1355 | ||
| 1356 | fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void { | 1356 | fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void { |
| 1357 | var stream = std.io.fixedBufferStream(data); | 1357 | var stream: std.io.FixedBufferStream = .{ .buffer = data }; |
| 1358 | var creader = std.io.countingReader(stream.reader()); | 1358 | var creader = std.io.countingReader(stream.reader()); |
| 1359 | const reader = creader.reader(); | 1359 | const reader = creader.reader(); |
| 1360 | 1360 | ||
| ... | @@ -1487,8 +1487,8 @@ const MachODumper = struct { | ... | @@ -1487,8 +1487,8 @@ const MachODumper = struct { |
| 1487 | data: []const u8, | 1487 | data: []const u8, |
| 1488 | pos: usize = 0, | 1488 | pos: usize = 0, |
| 1489 | 1489 | ||
| 1490 | fn getStream(it: *TrieIterator) std.io.FixedBufferStream([]const u8) { | 1490 | fn getStream(it: *TrieIterator) std.io.FixedBufferStream { |
| 1491 | return std.io.fixedBufferStream(it.data[it.pos..]); | 1491 | return .{ .buffer = it.data[it.pos..] }; |
| 1492 | } | 1492 | } |
| 1493 | 1493 | ||
| 1494 | fn readUleb128(it: *TrieIterator) !u64 { | 1494 | fn readUleb128(it: *TrieIterator) !u64 { |
| ... | @@ -1748,7 +1748,7 @@ const ElfDumper = struct { | ... | @@ -1748,7 +1748,7 @@ const ElfDumper = struct { |
| 1748 | 1748 | ||
| 1749 | fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 { | 1749 | fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 1750 | const gpa = step.owner.allocator; | 1750 | const gpa = step.owner.allocator; |
| 1751 | var stream = std.io.fixedBufferStream(bytes); | 1751 | var stream: std.io.FixedBufferStream = .{ .buffer = bytes }; |
| 1752 | const reader = stream.reader(); | 1752 | const reader = stream.reader(); |
| 1753 | 1753 | ||
| 1754 | const magic = try reader.readBytesNoEof(elf.ARMAG.len); | 1754 | const magic = try reader.readBytesNoEof(elf.ARMAG.len); |
| ... | @@ -1805,8 +1805,8 @@ const ElfDumper = struct { | ... | @@ -1805,8 +1805,8 @@ const ElfDumper = struct { |
| 1805 | try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size }); | 1805 | try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size }); |
| 1806 | } | 1806 | } |
| 1807 | 1807 | ||
| 1808 | var output = std.ArrayList(u8).init(gpa); | 1808 | var output: std.io.AllocatingWriter = undefined; |
| 1809 | const writer = output.writer(); | 1809 | const writer = output.init(gpa); |
| 1810 | 1810 | ||
| 1811 | switch (check.kind) { | 1811 | switch (check.kind) { |
| 1812 | .archive_symtab => if (ctx.symtab.items.len > 0) { | 1812 | .archive_symtab => if (ctx.symtab.items.len > 0) { |
| ... | @@ -1829,7 +1829,7 @@ const ElfDumper = struct { | ... | @@ -1829,7 +1829,7 @@ const ElfDumper = struct { |
| 1829 | objects: std.ArrayListUnmanaged(struct { name: []const u8, off: usize, len: usize }) = .empty, | 1829 | objects: std.ArrayListUnmanaged(struct { name: []const u8, off: usize, len: usize }) = .empty, |
| 1830 | 1830 | ||
| 1831 | fn parseSymtab(ctx: *ArchiveContext, raw: []const u8, ptr_width: enum { p32, p64 }) !void { | 1831 | fn parseSymtab(ctx: *ArchiveContext, raw: []const u8, ptr_width: enum { p32, p64 }) !void { |
| 1832 | var stream = std.io.fixedBufferStream(raw); | 1832 | var stream: std.io.FixedBufferStream = .{ .buffer = raw }; |
| 1833 | const reader = stream.reader(); | 1833 | const reader = stream.reader(); |
| 1834 | const num = switch (ptr_width) { | 1834 | const num = switch (ptr_width) { |
| 1835 | .p32 => try reader.readInt(u32, .big), | 1835 | .p32 => try reader.readInt(u32, .big), |
| ... | @@ -1914,7 +1914,7 @@ const ElfDumper = struct { | ... | @@ -1914,7 +1914,7 @@ const ElfDumper = struct { |
| 1914 | 1914 | ||
| 1915 | fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 { | 1915 | fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 1916 | const gpa = step.owner.allocator; | 1916 | const gpa = step.owner.allocator; |
| 1917 | var stream = std.io.fixedBufferStream(bytes); | 1917 | var stream: std.io.FixedBufferStream = .{ .buffer = bytes }; |
| 1918 | const reader = stream.reader(); | 1918 | const reader = stream.reader(); |
| 1919 | 1919 | ||
| 1920 | const hdr = try reader.readStruct(elf.Elf64_Ehdr); | 1920 | const hdr = try reader.readStruct(elf.Elf64_Ehdr); |
| ... | @@ -2419,7 +2419,7 @@ const WasmDumper = struct { | ... | @@ -2419,7 +2419,7 @@ const WasmDumper = struct { |
| 2419 | 2419 | ||
| 2420 | fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 { | 2420 | fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 2421 | const gpa = step.owner.allocator; | 2421 | const gpa = step.owner.allocator; |
| 2422 | var fbs = std.io.fixedBufferStream(bytes); | 2422 | var fbs: std.io.FixedBufferStream = .{ .buffer = bytes }; |
| 2423 | const reader = fbs.reader(); | 2423 | const reader = fbs.reader(); |
| 2424 | 2424 | ||
| 2425 | const buf = try reader.readBytesNoEof(8); | 2425 | const buf = try reader.readBytesNoEof(8); |
| ... | @@ -2472,7 +2472,7 @@ const WasmDumper = struct { | ... | @@ -2472,7 +2472,7 @@ const WasmDumper = struct { |
| 2472 | data: []const u8, | 2472 | data: []const u8, |
| 2473 | bw: *std.io.BufferedWriter, | 2473 | bw: *std.io.BufferedWriter, |
| 2474 | ) !void { | 2474 | ) !void { |
| 2475 | var fbs = std.io.fixedBufferStream(data); | 2475 | var fbs: std.io.FixedBufferStream = .{ .buffer = data }; |
| 2476 | const reader = fbs.reader(); | 2476 | const reader = fbs.reader(); |
| 2477 | 2477 | ||
| 2478 | try bw.print( | 2478 | try bw.print( |
| ... | @@ -2524,7 +2524,7 @@ const WasmDumper = struct { | ... | @@ -2524,7 +2524,7 @@ const WasmDumper = struct { |
| 2524 | } | 2524 | } |
| 2525 | 2525 | ||
| 2526 | fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, bw: *std.io.BufferedWriter) !void { | 2526 | fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, bw: *std.io.BufferedWriter) !void { |
| 2527 | var fbs = std.io.fixedBufferStream(data); | 2527 | var fbs: std.io.FixedBufferStream = .{ .buffer = data }; |
| 2528 | const reader = fbs.reader(); | 2528 | const reader = fbs.reader(); |
| 2529 | 2529 | ||
| 2530 | switch (section) { | 2530 | switch (section) { |
lib/std/Build/Step/Compile.zig+13-9| ... | @@ -1964,20 +1964,24 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) | ... | @@ -1964,20 +1964,24 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) |
| 1964 | fn checkCompileErrors(compile: *Compile) !void { | 1964 | fn checkCompileErrors(compile: *Compile) !void { |
| 1965 | // Clear this field so that it does not get printed by the build runner. | 1965 | // Clear this field so that it does not get printed by the build runner. |
| 1966 | const actual_eb = compile.step.result_error_bundle; | 1966 | const actual_eb = compile.step.result_error_bundle; |
| 1967 | compile.step.result_error_bundle = std.zig.ErrorBundle.empty; | 1967 | compile.step.result_error_bundle = .empty; |
| 1968 | 1968 | ||
| 1969 | const arena = compile.step.owner.allocator; | 1969 | const arena = compile.step.owner.allocator; |
| 1970 | 1970 | ||
| 1971 | var actual_errors_list = std.ArrayList(u8).init(arena); | 1971 | const actual_errors = ae: { |
| 1972 | try actual_eb.renderToWriter(.{ | 1972 | var aw: std.io.AllocatingWriter = undefined; |
| 1973 | .ttyconf = .no_color, | 1973 | const bw = aw.init(arena); |
| 1974 | .include_reference_trace = false, | 1974 | defer aw.deinit(); |
| 1975 | .include_source_line = false, | 1975 | try actual_eb.renderToWriter(.{ |
| 1976 | }, actual_errors_list.writer()); | 1976 | .ttyconf = .no_color, |
| 1977 | const actual_errors = try actual_errors_list.toOwnedSlice(); | 1977 | .include_reference_trace = false, |
| 1978 | .include_source_line = false, | ||
| 1979 | }, bw); | ||
| 1980 | break :ae try aw.toOwnedSlice(); | ||
| 1981 | }; | ||
| 1978 | 1982 | ||
| 1979 | // Render the expected lines into a string that we can compare verbatim. | 1983 | // Render the expected lines into a string that we can compare verbatim. |
| 1980 | var expected_generated = std.ArrayList(u8).init(arena); | 1984 | var expected_generated: std.ArrayListUnmanaged(u8) = .empty; |
| 1981 | const expect_errors = compile.expect_errors.?; | 1985 | const expect_errors = compile.expect_errors.?; |
| 1982 | 1986 | ||
| 1983 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); | 1987 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); |
lib/std/Uri.zig+7-7| ... | @@ -34,7 +34,7 @@ pub const Component = union(enum) { | ... | @@ -34,7 +34,7 @@ pub const Component = union(enum) { |
| 34 | return switch (component) { | 34 | return switch (component) { |
| 35 | .raw => |raw| raw, | 35 | .raw => |raw| raw, |
| 36 | .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| | 36 | .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| |
| 37 | try std.fmt.allocPrint(arena, "{raw}", .{component}) | 37 | try std.fmt.allocPrint(arena, "{fraw}", .{component}) |
| 38 | else | 38 | else |
| 39 | percent_encoded, | 39 | percent_encoded, |
| 40 | }; | 40 | }; |
| ... | @@ -44,8 +44,8 @@ pub const Component = union(enum) { | ... | @@ -44,8 +44,8 @@ pub const Component = union(enum) { |
| 44 | component: Component, | 44 | component: Component, |
| 45 | comptime fmt_str: []const u8, | 45 | comptime fmt_str: []const u8, |
| 46 | _: std.fmt.FormatOptions, | 46 | _: std.fmt.FormatOptions, |
| 47 | writer: anytype, | 47 | writer: *std.io.BufferedWriter, |
| 48 | ) @TypeOf(writer).Error!void { | 48 | ) anyerror!void { |
| 49 | if (fmt_str.len == 0) { | 49 | if (fmt_str.len == 0) { |
| 50 | try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{ | 50 | try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{ |
| 51 | @tagName(component), | 51 | @tagName(component), |
| ... | @@ -97,10 +97,10 @@ pub const Component = union(enum) { | ... | @@ -97,10 +97,10 @@ pub const Component = union(enum) { |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | pub fn percentEncode( | 99 | pub fn percentEncode( |
| 100 | writer: anytype, | 100 | writer: *std.io.BufferedWriter, |
| 101 | raw: []const u8, | 101 | raw: []const u8, |
| 102 | comptime isValidChar: fn (u8) bool, | 102 | comptime isValidChar: fn (u8) bool, |
| 103 | ) @TypeOf(writer).Error!void { | 103 | ) anyerror!void { |
| 104 | var start: usize = 0; | 104 | var start: usize = 0; |
| 105 | for (raw, 0..) |char, index| { | 105 | for (raw, 0..) |char, index| { |
| 106 | if (isValidChar(char)) continue; | 106 | if (isValidChar(char)) continue; |
| ... | @@ -822,7 +822,7 @@ test "URI percent decoding" { | ... | @@ -822,7 +822,7 @@ test "URI percent decoding" { |
| 822 | const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; | 822 | const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; |
| 823 | var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*; | 823 | var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*; |
| 824 | 824 | ||
| 825 | try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }}); | 825 | try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); |
| 826 | 826 | ||
| 827 | var output: [expected.len]u8 = undefined; | 827 | var output: [expected.len]u8 = undefined; |
| 828 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); | 828 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); |
| ... | @@ -834,7 +834,7 @@ test "URI percent decoding" { | ... | @@ -834,7 +834,7 @@ test "URI percent decoding" { |
| 834 | const expected = "/abc%"; | 834 | const expected = "/abc%"; |
| 835 | var input = expected.*; | 835 | var input = expected.*; |
| 836 | 836 | ||
| 837 | try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }}); | 837 | try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); |
| 838 | 838 | ||
| 839 | var output: [expected.len]u8 = undefined; | 839 | var output: [expected.len]u8 = undefined; |
| 840 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); | 840 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); |
lib/std/array_list.zig-54| ... | @@ -1828,60 +1828,6 @@ test "ArrayList(T) of struct T" { | ... | @@ -1828,60 +1828,6 @@ test "ArrayList(T) of struct T" { |
| 1828 | } | 1828 | } |
| 1829 | } | 1829 | } |
| 1830 | 1830 | ||
| 1831 | test "ArrayList(u8) implements writer" { | ||
| 1832 | const a = testing.allocator; | ||
| 1833 | |||
| 1834 | { | ||
| 1835 | var buffer = ArrayList(u8).init(a); | ||
| 1836 | defer buffer.deinit(); | ||
| 1837 | |||
| 1838 | const x: i32 = 42; | ||
| 1839 | const y: i32 = 1234; | ||
| 1840 | try buffer.writer().print("x: {}\ny: {}\n", .{ x, y }); | ||
| 1841 | |||
| 1842 | try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); | ||
| 1843 | } | ||
| 1844 | { | ||
| 1845 | var list = ArrayListAligned(u8, .@"2").init(a); | ||
| 1846 | defer list.deinit(); | ||
| 1847 | |||
| 1848 | const writer = list.writer(); | ||
| 1849 | try writer.writeAll("a"); | ||
| 1850 | try writer.writeAll("bc"); | ||
| 1851 | try writer.writeAll("d"); | ||
| 1852 | try writer.writeAll("efg"); | ||
| 1853 | |||
| 1854 | try testing.expectEqualSlices(u8, list.items, "abcdefg"); | ||
| 1855 | } | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | test "ArrayListUnmanaged(u8) implements writer" { | ||
| 1859 | const a = testing.allocator; | ||
| 1860 | |||
| 1861 | { | ||
| 1862 | var buffer: ArrayListUnmanaged(u8) = .empty; | ||
| 1863 | defer buffer.deinit(a); | ||
| 1864 | |||
| 1865 | const x: i32 = 42; | ||
| 1866 | const y: i32 = 1234; | ||
| 1867 | try buffer.writer(a).print("x: {}\ny: {}\n", .{ x, y }); | ||
| 1868 | |||
| 1869 | try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); | ||
| 1870 | } | ||
| 1871 | { | ||
| 1872 | var list: ArrayListAlignedUnmanaged(u8, .@"2") = .empty; | ||
| 1873 | defer list.deinit(a); | ||
| 1874 | |||
| 1875 | const writer = list.writer(a); | ||
| 1876 | try writer.writeAll("a"); | ||
| 1877 | try writer.writeAll("bc"); | ||
| 1878 | try writer.writeAll("d"); | ||
| 1879 | try writer.writeAll("efg"); | ||
| 1880 | |||
| 1881 | try testing.expectEqualSlices(u8, list.items, "abcdefg"); | ||
| 1882 | } | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | test "shrink still sets length when resizing is disabled" { | 1831 | test "shrink still sets length when resizing is disabled" { |
| 1886 | var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 }); | 1832 | var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 }); |
| 1887 | const a = failing_allocator.allocator(); | 1833 | const a = failing_allocator.allocator(); |
lib/std/compress/lzma2.zig+9-6| ... | @@ -15,12 +15,15 @@ pub fn decompress( | ... | @@ -15,12 +15,15 @@ pub fn decompress( |
| 15 | 15 | ||
| 16 | test { | 16 | test { |
| 17 | const expected = "Hello\nWorld!\n"; | 17 | const expected = "Hello\nWorld!\n"; |
| 18 | const compressed = &[_]u8{ 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00 }; | 18 | const compressed = &[_]u8{ |
| 19 | 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, | ||
| 20 | 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00, | ||
| 21 | }; | ||
| 22 | var stream: std.io.FixedBufferStream = .{ .buffer = compressed }; | ||
| 19 | 23 | ||
| 20 | const allocator = std.testing.allocator; | 24 | var decomp: std.io.AllocatingWriter = undefined; |
| 21 | var decomp = std.ArrayList(u8).init(allocator); | 25 | const decomp_bw = decomp.init(std.testing.allocator); |
| 22 | defer decomp.deinit(); | 26 | defer decomp.deinit(); |
| 23 | var stream = std.io.fixedBufferStream(compressed); | 27 | try decompress(std.testing.allocator, stream.reader(), decomp_bw); |
| 24 | try decompress(allocator, stream.reader(), decomp.writer()); | 28 | try std.testing.expectEqualSlices(u8, expected, decomp.getWritten()); |
| 25 | try std.testing.expectEqualSlices(u8, expected, decomp.items); | ||
| 26 | } | 29 | } |
lib/std/compress/zstandard/decode/block.zig+3-3| ... | @@ -631,7 +631,7 @@ pub fn decodeBlock( | ... | @@ -631,7 +631,7 @@ pub fn decodeBlock( |
| 631 | var bytes_read: usize = 0; | 631 | var bytes_read: usize = 0; |
| 632 | const literals = decodeLiteralsSectionSlice(src[0..block_size], &bytes_read) catch | 632 | const literals = decodeLiteralsSectionSlice(src[0..block_size], &bytes_read) catch |
| 633 | return error.MalformedCompressedBlock; | 633 | return error.MalformedCompressedBlock; |
| 634 | var fbs = std.io.fixedBufferStream(src[bytes_read..block_size]); | 634 | var fbs: std.io.FixedBufferStream = .{ .buffer = src[bytes_read..block_size] }; |
| 635 | const fbs_reader = fbs.reader(); | 635 | const fbs_reader = fbs.reader(); |
| 636 | const sequences_header = decodeSequencesHeader(fbs_reader) catch | 636 | const sequences_header = decodeSequencesHeader(fbs_reader) catch |
| 637 | return error.MalformedCompressedBlock; | 637 | return error.MalformedCompressedBlock; |
| ... | @@ -737,7 +737,7 @@ pub fn decodeBlockRingBuffer( | ... | @@ -737,7 +737,7 @@ pub fn decodeBlockRingBuffer( |
| 737 | var bytes_read: usize = 0; | 737 | var bytes_read: usize = 0; |
| 738 | const literals = decodeLiteralsSectionSlice(src[0..block_size], &bytes_read) catch | 738 | const literals = decodeLiteralsSectionSlice(src[0..block_size], &bytes_read) catch |
| 739 | return error.MalformedCompressedBlock; | 739 | return error.MalformedCompressedBlock; |
| 740 | var fbs = std.io.fixedBufferStream(src[bytes_read..block_size]); | 740 | var fbs: std.io.FixedBufferStream = .{ .buffer = src[bytes_read..block_size] }; |
| 741 | const fbs_reader = fbs.reader(); | 741 | const fbs_reader = fbs.reader(); |
| 742 | const sequences_header = decodeSequencesHeader(fbs_reader) catch | 742 | const sequences_header = decodeSequencesHeader(fbs_reader) catch |
| 743 | return error.MalformedCompressedBlock; | 743 | return error.MalformedCompressedBlock; |
| ... | @@ -931,7 +931,7 @@ pub fn decodeLiteralsSectionSlice( | ... | @@ -931,7 +931,7 @@ pub fn decodeLiteralsSectionSlice( |
| 931 | ) (error{ MalformedLiteralsHeader, MalformedLiteralsSection, EndOfStream } || huffman.Error)!LiteralsSection { | 931 | ) (error{ MalformedLiteralsHeader, MalformedLiteralsSection, EndOfStream } || huffman.Error)!LiteralsSection { |
| 932 | var bytes_read: usize = 0; | 932 | var bytes_read: usize = 0; |
| 933 | const header = header: { | 933 | const header = header: { |
| 934 | var fbs = std.io.fixedBufferStream(src); | 934 | var fbs: std.io.FixedBufferStream = .{ .buffer = src }; |
| 935 | defer bytes_read = fbs.pos; | 935 | defer bytes_read = fbs.pos; |
| 936 | break :header decodeLiteralsHeader(fbs.reader()) catch return error.MalformedLiteralsHeader; | 936 | break :header decodeLiteralsHeader(fbs.reader()) catch return error.MalformedLiteralsHeader; |
| 937 | }; | 937 | }; |
lib/std/compress/zstandard/decode/huffman.zig+2-2| ... | @@ -41,7 +41,7 @@ fn decodeFseHuffmanTree( | ... | @@ -41,7 +41,7 @@ fn decodeFseHuffmanTree( |
| 41 | 41 | ||
| 42 | fn decodeFseHuffmanTreeSlice(src: []const u8, compressed_size: usize, weights: *[256]u4) !usize { | 42 | fn decodeFseHuffmanTreeSlice(src: []const u8, compressed_size: usize, weights: *[256]u4) !usize { |
| 43 | if (src.len < compressed_size) return error.MalformedHuffmanTree; | 43 | if (src.len < compressed_size) return error.MalformedHuffmanTree; |
| 44 | var stream = std.io.fixedBufferStream(src[0..compressed_size]); | 44 | var stream: std.io.FixedBufferStream = .{ .buffer = src[0..compressed_size] }; |
| 45 | var counting_reader = std.io.countingReader(stream.reader()); | 45 | var counting_reader = std.io.countingReader(stream.reader()); |
| 46 | var bit_reader = readers.bitReader(counting_reader.reader()); | 46 | var bit_reader = readers.bitReader(counting_reader.reader()); |
| 47 | 47 | ||
| ... | @@ -213,7 +213,7 @@ pub fn decodeHuffmanTreeSlice( | ... | @@ -213,7 +213,7 @@ pub fn decodeHuffmanTreeSlice( |
| 213 | bytes_read += header; | 213 | bytes_read += header; |
| 214 | break :count try decodeFseHuffmanTreeSlice(src[1..], header, &weights); | 214 | break :count try decodeFseHuffmanTreeSlice(src[1..], header, &weights); |
| 215 | } else count: { | 215 | } else count: { |
| 216 | var fbs = std.io.fixedBufferStream(src[1..]); | 216 | var fbs: std.io.FixedBufferStream = .{ .buffer = src[1..] }; |
| 217 | defer bytes_read += fbs.pos; | 217 | defer bytes_read += fbs.pos; |
| 218 | break :count try decodeDirectHuffmanTree(fbs.reader(), header - 127, &weights); | 218 | break :count try decodeDirectHuffmanTree(fbs.reader(), header - 127, &weights); |
| 219 | }; | 219 | }; |
lib/std/compress/zstandard/decompress.zig+4-4| ... | @@ -186,7 +186,7 @@ pub fn decodeFrame( | ... | @@ -186,7 +186,7 @@ pub fn decodeFrame( |
| 186 | DictionaryIdFlagUnsupported, | 186 | DictionaryIdFlagUnsupported, |
| 187 | SkippableSizeTooLarge, | 187 | SkippableSizeTooLarge, |
| 188 | } || FrameError)!ReadWriteCount { | 188 | } || FrameError)!ReadWriteCount { |
| 189 | var fbs = std.io.fixedBufferStream(src); | 189 | var fbs: std.io.FixedBufferStream = .{ .buffer = src }; |
| 190 | switch (try decodeFrameType(fbs.reader())) { | 190 | switch (try decodeFrameType(fbs.reader())) { |
| 191 | .zstandard => return decodeZstandardFrame(dest, src, verify_checksum), | 191 | .zstandard => return decodeZstandardFrame(dest, src, verify_checksum), |
| 192 | .skippable => { | 192 | .skippable => { |
| ... | @@ -233,7 +233,7 @@ pub fn decodeFrameArrayList( | ... | @@ -233,7 +233,7 @@ pub fn decodeFrameArrayList( |
| 233 | verify_checksum: bool, | 233 | verify_checksum: bool, |
| 234 | window_size_max: usize, | 234 | window_size_max: usize, |
| 235 | ) (error{ BadMagic, OutOfMemory, SkippableSizeTooLarge } || FrameContext.Error || FrameError)!usize { | 235 | ) (error{ BadMagic, OutOfMemory, SkippableSizeTooLarge } || FrameContext.Error || FrameError)!usize { |
| 236 | var fbs = std.io.fixedBufferStream(src); | 236 | var fbs: std.io.FixedBufferStream = .{ .buffer = src }; |
| 237 | const reader = fbs.reader(); | 237 | const reader = fbs.reader(); |
| 238 | const magic = try reader.readInt(u32, .little); | 238 | const magic = try reader.readInt(u32, .little); |
| 239 | switch (try frameType(magic)) { | 239 | switch (try frameType(magic)) { |
| ... | @@ -303,7 +303,7 @@ pub fn decodeZstandardFrame( | ... | @@ -303,7 +303,7 @@ pub fn decodeZstandardFrame( |
| 303 | var consumed_count: usize = 4; | 303 | var consumed_count: usize = 4; |
| 304 | 304 | ||
| 305 | var frame_context = context: { | 305 | var frame_context = context: { |
| 306 | var fbs = std.io.fixedBufferStream(src[consumed_count..]); | 306 | var fbs: std.io.FixedBufferStream = .{ .buffer = src[consumed_count..] }; |
| 307 | const source = fbs.reader(); | 307 | const source = fbs.reader(); |
| 308 | const frame_header = try decodeZstandardHeader(source); | 308 | const frame_header = try decodeZstandardHeader(source); |
| 309 | consumed_count += fbs.pos; | 309 | consumed_count += fbs.pos; |
| ... | @@ -446,7 +446,7 @@ pub fn decodeZstandardFrameArrayList( | ... | @@ -446,7 +446,7 @@ pub fn decodeZstandardFrameArrayList( |
| 446 | var consumed_count: usize = 4; | 446 | var consumed_count: usize = 4; |
| 447 | 447 | ||
| 448 | var frame_context = context: { | 448 | var frame_context = context: { |
| 449 | var fbs = std.io.fixedBufferStream(src[consumed_count..]); | 449 | var fbs: std.io.FixedBufferStream = .{ .buffer = src[consumed_count..] }; |
| 450 | const source = fbs.reader(); | 450 | const source = fbs.reader(); |
| 451 | const frame_header = try decodeZstandardHeader(source); | 451 | const frame_header = try decodeZstandardHeader(source); |
| 452 | consumed_count += fbs.pos; | 452 | consumed_count += fbs.pos; |
lib/std/debug.zig+26-30| ... | @@ -242,50 +242,44 @@ pub fn getSelfDebugInfo() !*SelfInfo { | ... | @@ -242,50 +242,44 @@ pub fn getSelfDebugInfo() !*SelfInfo { |
| 242 | /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. | 242 | /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. |
| 243 | /// Obtains the stderr mutex while dumping. | 243 | /// Obtains the stderr mutex while dumping. |
| 244 | pub fn dumpHex(bytes: []const u8) void { | 244 | pub fn dumpHex(bytes: []const u8) void { |
| 245 | lockStdErr(); | 245 | var bw = lockStdErr2(); |
| 246 | defer unlockStdErr(); | 246 | defer unlockStdErr(); |
| 247 | dumpHexFallible(bytes) catch {}; | 247 | const ttyconf = std.io.tty.detectConfig(std.io.getStdErr()); |
| 248 | } | 248 | dumpHexFallible(&bw, ttyconf, bytes) catch {}; |
| 249 | |||
| 250 | /// Prints a hexadecimal view of the bytes, unbuffered, returning any error that occurs. | ||
| 251 | pub fn dumpHexFallible(bytes: []const u8) !void { | ||
| 252 | const stderr = std.io.getStdErr(); | ||
| 253 | const ttyconf = std.io.tty.detectConfig(stderr); | ||
| 254 | const writer = stderr.writer(); | ||
| 255 | try dumpHexInternal(bytes, ttyconf, writer); | ||
| 256 | } | 249 | } |
| 257 | 250 | ||
| 258 | fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytype) !void { | 251 | /// Prints a hexadecimal view of the bytes, returning any error that occurs. |
| 252 | pub fn dumpHexFallible(bw: *std.io.BufferedWriter, ttyconf: std.io.tty.Config, bytes: []const u8) !void { | ||
| 259 | var chunks = mem.window(u8, bytes, 16, 16); | 253 | var chunks = mem.window(u8, bytes, 16, 16); |
| 260 | while (chunks.next()) |window| { | 254 | while (chunks.next()) |window| { |
| 261 | // 1. Print the address. | 255 | // 1. Print the address. |
| 262 | const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10; | 256 | const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10; |
| 263 | try ttyconf.setColor(writer, .dim); | 257 | try ttyconf.setColor(bw, .dim); |
| 264 | // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. | 258 | // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. |
| 265 | // Also, make sure all lines are aligned by padding the address. | 259 | // Also, make sure all lines are aligned by padding the address. |
| 266 | try writer.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); | 260 | try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); |
| 267 | try ttyconf.setColor(writer, .reset); | 261 | try ttyconf.setColor(bw, .reset); |
| 268 | 262 | ||
| 269 | // 2. Print the bytes. | 263 | // 2. Print the bytes. |
| 270 | for (window, 0..) |byte, index| { | 264 | for (window, 0..) |byte, index| { |
| 271 | try writer.print("{X:0>2} ", .{byte}); | 265 | try bw.print("{X:0>2} ", .{byte}); |
| 272 | if (index == 7) try writer.writeByte(' '); | 266 | if (index == 7) try bw.writeByte(' '); |
| 273 | } | 267 | } |
| 274 | try writer.writeByte(' '); | 268 | try bw.writeByte(' '); |
| 275 | if (window.len < 16) { | 269 | if (window.len < 16) { |
| 276 | var missing_columns = (16 - window.len) * 3; | 270 | var missing_columns = (16 - window.len) * 3; |
| 277 | if (window.len < 8) missing_columns += 1; | 271 | if (window.len < 8) missing_columns += 1; |
| 278 | try writer.splatByteAll(' ', missing_columns); | 272 | try bw.splatByteAll(' ', missing_columns); |
| 279 | } | 273 | } |
| 280 | 274 | ||
| 281 | // 3. Print the characters. | 275 | // 3. Print the characters. |
| 282 | for (window) |byte| { | 276 | for (window) |byte| { |
| 283 | if (std.ascii.isPrint(byte)) { | 277 | if (std.ascii.isPrint(byte)) { |
| 284 | try writer.writeByte(byte); | 278 | try bw.writeByte(byte); |
| 285 | } else { | 279 | } else { |
| 286 | // Related: https://github.com/ziglang/zig/issues/7600 | 280 | // Related: https://github.com/ziglang/zig/issues/7600 |
| 287 | if (ttyconf == .windows_api) { | 281 | if (ttyconf == .windows_api) { |
| 288 | try writer.writeByte('.'); | 282 | try bw.writeByte('.'); |
| 289 | continue; | 283 | continue; |
| 290 | } | 284 | } |
| 291 | 285 | ||
| ... | @@ -293,22 +287,24 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp | ... | @@ -293,22 +287,24 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp |
| 293 | // We don't want to do this for all control codes because most control codes apart from | 287 | // We don't want to do this for all control codes because most control codes apart from |
| 294 | // the ones that Zig has escape sequences for are likely not very useful to print as symbols. | 288 | // the ones that Zig has escape sequences for are likely not very useful to print as symbols. |
| 295 | switch (byte) { | 289 | switch (byte) { |
| 296 | '\n' => try writer.writeAll("␊"), | 290 | '\n' => try bw.writeAll("␊"), |
| 297 | '\r' => try writer.writeAll("␍"), | 291 | '\r' => try bw.writeAll("␍"), |
| 298 | '\t' => try writer.writeAll("␉"), | 292 | '\t' => try bw.writeAll("␉"), |
| 299 | else => try writer.writeByte('.'), | 293 | else => try bw.writeByte('.'), |
| 300 | } | 294 | } |
| 301 | } | 295 | } |
| 302 | } | 296 | } |
| 303 | try writer.writeByte('\n'); | 297 | try bw.writeByte('\n'); |
| 304 | } | 298 | } |
| 305 | } | 299 | } |
| 306 | 300 | ||
| 307 | test dumpHexInternal { | 301 | test dumpHexFallible { |
| 308 | const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 }; | 302 | const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 }; |
| 309 | var output = std.ArrayList(u8).init(std.testing.allocator); | 303 | var aw: std.io.AllocatingWriter = undefined; |
| 310 | defer output.deinit(); | 304 | defer aw.deinit(); |
| 311 | try dumpHexInternal(bytes, .no_color, output.writer()); | 305 | var bw = aw.init(std.testing.allocator); |
| 306 | |||
| 307 | try dumpHexFallible(&bw, .no_color, bytes); | ||
| 312 | const expected = try std.fmt.allocPrint(std.testing.allocator, | 308 | const expected = try std.fmt.allocPrint(std.testing.allocator, |
| 313 | \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ | 309 | \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ |
| 314 | \\{x:0>[2]} 01 12 13 ... | 310 | \\{x:0>[2]} 01 12 13 ... |
| ... | @@ -319,7 +315,7 @@ test dumpHexInternal { | ... | @@ -319,7 +315,7 @@ test dumpHexInternal { |
| 319 | @sizeOf(usize) * 2, | 315 | @sizeOf(usize) * 2, |
| 320 | }); | 316 | }); |
| 321 | defer std.testing.allocator.free(expected); | 317 | defer std.testing.allocator.free(expected); |
| 322 | try std.testing.expectEqualStrings(expected, output.items); | 318 | try std.testing.expectEqualStrings(expected, aw.getWritten()); |
| 323 | } | 319 | } |
| 324 | 320 | ||
| 325 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. | 321 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. |
lib/std/fs/File.zig+5| ... | @@ -1496,6 +1496,11 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile | ... | @@ -1496,6 +1496,11 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile |
| 1496 | /// Does not try seeking in either of the File parameters. | 1496 | /// Does not try seeking in either of the File parameters. |
| 1497 | /// See `writeFileAll` as an alternative to calling this. | 1497 | /// See `writeFileAll` as an alternative to calling this. |
| 1498 | pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void { | 1498 | pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void { |
| 1499 | // TODO make `try @errorCast(...)` work | ||
| 1500 | return @errorCast(writeFileAllUnseekableInner(self, in_file, args)); | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | fn writeFileAllUnseekableInner(self: File, in_file: File, args: WriteFileOptions) anyerror!void { | ||
| 1499 | const headers = args.headers_and_trailers[0..args.header_count]; | 1504 | const headers = args.headers_and_trailers[0..args.header_count]; |
| 1500 | const trailers = args.headers_and_trailers[args.header_count..]; | 1505 | const trailers = args.headers_and_trailers[args.header_count..]; |
| 1501 | 1506 |
lib/std/http/Client.zig+10-14| ... | @@ -1283,26 +1283,22 @@ pub const basic_authorization = struct { | ... | @@ -1283,26 +1283,22 @@ pub const basic_authorization = struct { |
| 1283 | } | 1283 | } |
| 1284 | 1284 | ||
| 1285 | pub fn valueLengthFromUri(uri: Uri) usize { | 1285 | pub fn valueLengthFromUri(uri: Uri) usize { |
| 1286 | var stream = std.io.countingWriter(std.io.null_writer); | 1286 | // TODO don't abuse formatted printing to count percent encoded characters |
| 1287 | try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}); | 1287 | const user_len = std.fmt.count("{fuser}", .{uri.user orelse Uri.Component.empty}); |
| 1288 | const user_len = stream.bytes_written; | 1288 | const password_len = std.fmt.count("{fpassword}", .{uri.password orelse Uri.Component.empty}); |
| 1289 | stream.bytes_written = 0; | ||
| 1290 | try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty}); | ||
| 1291 | const password_len = stream.bytes_written; | ||
| 1292 | return valueLength(@intCast(user_len), @intCast(password_len)); | 1289 | return valueLength(@intCast(user_len), @intCast(password_len)); |
| 1293 | } | 1290 | } |
| 1294 | 1291 | ||
| 1295 | pub fn value(uri: Uri, out: []u8) []u8 { | 1292 | pub fn value(uri: Uri, out: []u8) []u8 { |
| 1296 | var buf: [max_user_len + ":".len + max_password_len]u8 = undefined; | 1293 | var buf: [max_user_len + ":".len + max_password_len]u8 = undefined; |
| 1297 | var stream = std.io.fixedBufferStream(&buf); | 1294 | var bw: std.io.BufferedWriter = undefined; |
| 1298 | stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch | 1295 | bw.initFixed(&buf); |
| 1299 | unreachable; | 1296 | bw.print("{fuser}:{fpassword}", .{ |
| 1300 | assert(stream.pos <= max_user_len); | 1297 | uri.user orelse Uri.Component.empty, |
| 1301 | stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch | 1298 | uri.password orelse Uri.Component.empty, |
| 1302 | unreachable; | 1299 | }) catch unreachable; |
| 1303 | |||
| 1304 | @memcpy(out[0..prefix.len], prefix); | 1300 | @memcpy(out[0..prefix.len], prefix); |
| 1305 | const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], stream.getWritten()); | 1301 | const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], bw.getWritten()); |
| 1306 | return out[0 .. prefix.len + base64.len]; | 1302 | return out[0 .. prefix.len + base64.len]; |
| 1307 | } | 1303 | } |
| 1308 | }; | 1304 | }; |
lib/std/io/AllocatingWriter.zig+18-1| ... | @@ -1,4 +1,3 @@ | ... | @@ -1,4 +1,3 @@ |
| 1 | //! TODO rename to AllocatingWriter. | ||
| 2 | //! While it is possible to use `std.ArrayList` as the underlying writer when | 1 | //! While it is possible to use `std.ArrayList` as the underlying writer when |
| 3 | //! using `std.io.BufferedWriter` by populating the `std.io.Writer` interface | 2 | //! using `std.io.BufferedWriter` by populating the `std.io.Writer` interface |
| 4 | //! and then using an empty buffer, it means that every use of | 3 | //! and then using an empty buffer, it means that every use of |
| ... | @@ -41,6 +40,12 @@ pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) *std.io.Buffere | ... | @@ -41,6 +40,12 @@ pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) *std.io.Buffere |
| 41 | return &aw.buffered_writer; | 40 | return &aw.buffered_writer; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| 43 | pub fn deinit(aw: *AllocatingWriter) void { | ||
| 44 | const written = aw.written; | ||
| 45 | aw.allocator.free(written.ptr[0 .. written.len + aw.buffered_writer.buffer.len]); | ||
| 46 | aw.* = undefined; | ||
| 47 | } | ||
| 48 | |||
| 44 | /// Replaces `array_list` with empty, taking ownership of the memory. | 49 | /// Replaces `array_list` with empty, taking ownership of the memory. |
| 45 | pub fn fromArrayList( | 50 | pub fn fromArrayList( |
| 46 | aw: *AllocatingWriter, | 51 | aw: *AllocatingWriter, |
| ... | @@ -184,3 +189,15 @@ fn writeFile( | ... | @@ -184,3 +189,15 @@ fn writeFile( |
| 184 | for (trailers) |bytes| list.appendSliceAssumeCapacity(bytes); | 189 | for (trailers) |bytes| list.appendSliceAssumeCapacity(bytes); |
| 185 | return list.items.len - start_len; | 190 | return list.items.len - start_len; |
| 186 | } | 191 | } |
| 192 | |||
| 193 | test AllocatingWriter { | ||
| 194 | var aw: AllocatingWriter = undefined; | ||
| 195 | const bw = aw.init(std.testing.allocator); | ||
| 196 | defer aw.deinit(); | ||
| 197 | |||
| 198 | const x: i32 = 42; | ||
| 199 | const y: i32 = 1234; | ||
| 200 | try bw.print("x: {}\ny: {}\n", .{ x, y }); | ||
| 201 | |||
| 202 | try std.testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", aw.getWritten()); | ||
| 203 | } |
lib/std/io/CountingWriter.zig+3| ... | @@ -1,3 +1,6 @@ | ... | @@ -1,3 +1,6 @@ |
| 1 | //! TODO make this more like AllocatingWriter, managing the state of | ||
| 2 | //! BufferedWriter both as the output and the input, but with only | ||
| 3 | //! one buffer. | ||
| 1 | const std = @import("../std.zig"); | 4 | const std = @import("../std.zig"); |
| 2 | const CountingWriter = @This(); | 5 | const CountingWriter = @This(); |
| 3 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
lib/std/testing.zig+26-25| ... | @@ -390,8 +390,9 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const | ... | @@ -390,8 +390,9 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 390 | const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; | 390 | const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; |
| 391 | const actual_truncated = window_start + actual_window.len < actual.len; | 391 | const actual_truncated = window_start + actual_window.len < actual.len; |
| 392 | 392 | ||
| 393 | const stderr = std.io.getStdErr(); | 393 | var bw = std.debug.lockStdErr2(); |
| 394 | const ttyconf = std.io.tty.detectConfig(stderr); | 394 | defer std.debug.unlockStdErr(); |
| 395 | const ttyconf = std.io.tty.detectConfig(std.io.getStdErr()); | ||
| 395 | var differ = if (T == u8) BytesDiffer{ | 396 | var differ = if (T == u8) BytesDiffer{ |
| 396 | .expected = expected_window, | 397 | .expected = expected_window, |
| 397 | .actual = actual_window, | 398 | .actual = actual_window, |
| ... | @@ -415,7 +416,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const | ... | @@ -415,7 +416,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 415 | print("... truncated ...\n", .{}); | 416 | print("... truncated ...\n", .{}); |
| 416 | } | 417 | } |
| 417 | } | 418 | } |
| 418 | differ.write(stderr.writer()) catch {}; | 419 | differ.write(&bw) catch {}; |
| 419 | if (expected_truncated) { | 420 | if (expected_truncated) { |
| 420 | const end_offset = window_start + expected_window.len; | 421 | const end_offset = window_start + expected_window.len; |
| 421 | const num_missing_items = expected.len - (window_start + expected_window.len); | 422 | const num_missing_items = expected.len - (window_start + expected_window.len); |
| ... | @@ -437,7 +438,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const | ... | @@ -437,7 +438,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 437 | print("... truncated ...\n", .{}); | 438 | print("... truncated ...\n", .{}); |
| 438 | } | 439 | } |
| 439 | } | 440 | } |
| 440 | differ.write(stderr.writer()) catch {}; | 441 | differ.write(&bw) catch {}; |
| 441 | if (actual_truncated) { | 442 | if (actual_truncated) { |
| 442 | const end_offset = window_start + actual_window.len; | 443 | const end_offset = window_start + actual_window.len; |
| 443 | const num_missing_items = actual.len - (window_start + actual_window.len); | 444 | const num_missing_items = actual.len - (window_start + actual_window.len); |
| ... | @@ -461,17 +462,17 @@ fn SliceDiffer(comptime T: type) type { | ... | @@ -461,17 +462,17 @@ fn SliceDiffer(comptime T: type) type { |
| 461 | 462 | ||
| 462 | const Self = @This(); | 463 | const Self = @This(); |
| 463 | 464 | ||
| 464 | pub fn write(self: Self, writer: anytype) !void { | 465 | pub fn write(self: Self, bw: *std.io.BufferedWriter) !void { |
| 465 | for (self.expected, 0..) |value, i| { | 466 | for (self.expected, 0..) |value, i| { |
| 466 | const full_index = self.start_index + i; | 467 | const full_index = self.start_index + i; |
| 467 | const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; | 468 | const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; |
| 468 | if (diff) try self.ttyconf.setColor(writer, .red); | 469 | if (diff) try self.ttyconf.setColor(bw, .red); |
| 469 | if (@typeInfo(T) == .pointer) { | 470 | if (@typeInfo(T) == .pointer) { |
| 470 | try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value }); | 471 | try bw.print("[{}]{*}: {any}\n", .{ full_index, value, value }); |
| 471 | } else { | 472 | } else { |
| 472 | try writer.print("[{}]: {any}\n", .{ full_index, value }); | 473 | try bw.print("[{}]: {any}\n", .{ full_index, value }); |
| 473 | } | 474 | } |
| 474 | if (diff) try self.ttyconf.setColor(writer, .reset); | 475 | if (diff) try self.ttyconf.setColor(bw, .reset); |
| 475 | } | 476 | } |
| 476 | } | 477 | } |
| 477 | }; | 478 | }; |
| ... | @@ -482,7 +483,7 @@ const BytesDiffer = struct { | ... | @@ -482,7 +483,7 @@ const BytesDiffer = struct { |
| 482 | actual: []const u8, | 483 | actual: []const u8, |
| 483 | ttyconf: std.io.tty.Config, | 484 | ttyconf: std.io.tty.Config, |
| 484 | 485 | ||
| 485 | pub fn write(self: BytesDiffer, writer: anytype) !void { | 486 | pub fn write(self: BytesDiffer, bw: *std.io.BufferedWriter) !void { |
| 486 | var expected_iterator = std.mem.window(u8, self.expected, 16, 16); | 487 | var expected_iterator = std.mem.window(u8, self.expected, 16, 16); |
| 487 | var row: usize = 0; | 488 | var row: usize = 0; |
| 488 | while (expected_iterator.next()) |chunk| { | 489 | while (expected_iterator.next()) |chunk| { |
| ... | @@ -492,23 +493,23 @@ const BytesDiffer = struct { | ... | @@ -492,23 +493,23 @@ const BytesDiffer = struct { |
| 492 | const absolute_byte_index = col + row * 16; | 493 | const absolute_byte_index = col + row * 16; |
| 493 | const diff = if (absolute_byte_index < self.actual.len) self.actual[absolute_byte_index] != byte else true; | 494 | const diff = if (absolute_byte_index < self.actual.len) self.actual[absolute_byte_index] != byte else true; |
| 494 | if (diff) diffs.set(col); | 495 | if (diff) diffs.set(col); |
| 495 | try self.writeDiff(writer, "{X:0>2} ", .{byte}, diff); | 496 | try self.writeDiff(bw, "{X:0>2} ", .{byte}, diff); |
| 496 | if (col == 7) try writer.writeByte(' '); | 497 | if (col == 7) try bw.writeByte(' '); |
| 497 | } | 498 | } |
| 498 | try writer.writeByte(' '); | 499 | try bw.writeByte(' '); |
| 499 | if (chunk.len < 16) { | 500 | if (chunk.len < 16) { |
| 500 | var missing_columns = (16 - chunk.len) * 3; | 501 | var missing_columns = (16 - chunk.len) * 3; |
| 501 | if (chunk.len < 8) missing_columns += 1; | 502 | if (chunk.len < 8) missing_columns += 1; |
| 502 | try writer.writeByteNTimes(' ', missing_columns); | 503 | try bw.splatByteAll(' ', missing_columns); |
| 503 | } | 504 | } |
| 504 | for (chunk, 0..) |byte, col| { | 505 | for (chunk, 0..) |byte, col| { |
| 505 | const diff = diffs.isSet(col); | 506 | const diff = diffs.isSet(col); |
| 506 | if (std.ascii.isPrint(byte)) { | 507 | if (std.ascii.isPrint(byte)) { |
| 507 | try self.writeDiff(writer, "{c}", .{byte}, diff); | 508 | try self.writeDiff(bw, "{c}", .{byte}, diff); |
| 508 | } else { | 509 | } else { |
| 509 | // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed | 510 | // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed |
| 510 | if (self.ttyconf == .windows_api) { | 511 | if (self.ttyconf == .windows_api) { |
| 511 | try self.writeDiff(writer, ".", .{}, diff); | 512 | try self.writeDiff(bw, ".", .{}, diff); |
| 512 | continue; | 513 | continue; |
| 513 | } | 514 | } |
| 514 | 515 | ||
| ... | @@ -516,22 +517,22 @@ const BytesDiffer = struct { | ... | @@ -516,22 +517,22 @@ const BytesDiffer = struct { |
| 516 | // We don't want to do this for all control codes because most control codes apart from | 517 | // We don't want to do this for all control codes because most control codes apart from |
| 517 | // the ones that Zig has escape sequences for are likely not very useful to print as symbols. | 518 | // the ones that Zig has escape sequences for are likely not very useful to print as symbols. |
| 518 | switch (byte) { | 519 | switch (byte) { |
| 519 | '\n' => try self.writeDiff(writer, "␊", .{}, diff), | 520 | '\n' => try self.writeDiff(bw, "␊", .{}, diff), |
| 520 | '\r' => try self.writeDiff(writer, "␍", .{}, diff), | 521 | '\r' => try self.writeDiff(bw, "␍", .{}, diff), |
| 521 | '\t' => try self.writeDiff(writer, "␉", .{}, diff), | 522 | '\t' => try self.writeDiff(bw, "␉", .{}, diff), |
| 522 | else => try self.writeDiff(writer, ".", .{}, diff), | 523 | else => try self.writeDiff(bw, ".", .{}, diff), |
| 523 | } | 524 | } |
| 524 | } | 525 | } |
| 525 | } | 526 | } |
| 526 | try writer.writeByte('\n'); | 527 | try bw.writeByte('\n'); |
| 527 | row += 1; | 528 | row += 1; |
| 528 | } | 529 | } |
| 529 | } | 530 | } |
| 530 | 531 | ||
| 531 | fn writeDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, args: anytype, diff: bool) !void { | 532 | fn writeDiff(self: BytesDiffer, bw: *std.io.BufferedWriter, comptime fmt: []const u8, args: anytype, diff: bool) !void { |
| 532 | if (diff) try self.ttyconf.setColor(writer, .red); | 533 | if (diff) try self.ttyconf.setColor(bw, .red); |
| 533 | try writer.print(fmt, args); | 534 | try bw.print(fmt, args); |
| 534 | if (diff) try self.ttyconf.setColor(writer, .reset); | 535 | if (diff) try self.ttyconf.setColor(bw, .reset); |
| 535 | } | 536 | } |
| 536 | }; | 537 | }; |
| 537 | 538 |
lib/std/zig/ErrorBundle.zig+70-63| ... | @@ -159,21 +159,26 @@ pub const RenderOptions = struct { | ... | @@ -159,21 +159,26 @@ pub const RenderOptions = struct { |
| 159 | pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { | 159 | pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { |
| 160 | std.debug.lockStdErr(); | 160 | std.debug.lockStdErr(); |
| 161 | defer std.debug.unlockStdErr(); | 161 | defer std.debug.unlockStdErr(); |
| 162 | const stderr = std.io.getStdErr(); | 162 | var buffer: [256]u8 = undefined; |
| 163 | return renderToWriter(eb, options, stderr.writer()) catch return; | 163 | var bw: std.io.BufferedWriter = .{ |
| 164 | .unbuffered_writer = std.io.getStdErr().writer(), | ||
| 165 | .buffer = &buffer, | ||
| 166 | }; | ||
| 167 | renderToWriter(eb, options, &bw) catch return; | ||
| 168 | bw.flush() catch return; | ||
| 164 | } | 169 | } |
| 165 | 170 | ||
| 166 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void { | 171 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, bw: *std.io.BufferedWriter) anyerror!void { |
| 167 | if (eb.extra.len == 0) return; | 172 | if (eb.extra.len == 0) return; |
| 168 | for (eb.getMessages()) |err_msg| { | 173 | for (eb.getMessages()) |err_msg| { |
| 169 | try renderErrorMessageToWriter(eb, options, err_msg, writer, "error", .red, 0); | 174 | try renderErrorMessageToWriter(eb, options, err_msg, bw, "error", .red, 0); |
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | if (options.include_log_text) { | 177 | if (options.include_log_text) { |
| 173 | const log_text = eb.getCompileLogOutput(); | 178 | const log_text = eb.getCompileLogOutput(); |
| 174 | if (log_text.len != 0) { | 179 | if (log_text.len != 0) { |
| 175 | try writer.writeAll("\nCompile Log Output:\n"); | 180 | try bw.writeAll("\nCompile Log Output:\n"); |
| 176 | try writer.writeAll(log_text); | 181 | try bw.writeAll(log_text); |
| 177 | } | 182 | } |
| 178 | } | 183 | } |
| 179 | } | 184 | } |
| ... | @@ -182,74 +187,74 @@ fn renderErrorMessageToWriter( | ... | @@ -182,74 +187,74 @@ fn renderErrorMessageToWriter( |
| 182 | eb: ErrorBundle, | 187 | eb: ErrorBundle, |
| 183 | options: RenderOptions, | 188 | options: RenderOptions, |
| 184 | err_msg_index: MessageIndex, | 189 | err_msg_index: MessageIndex, |
| 185 | stderr: anytype, | 190 | bw: *std.io.BufferedWriter, |
| 186 | kind: []const u8, | 191 | kind: []const u8, |
| 187 | color: std.io.tty.Color, | 192 | color: std.io.tty.Color, |
| 188 | indent: usize, | 193 | indent: usize, |
| 189 | ) anyerror!void { | 194 | ) anyerror!void { |
| 190 | const ttyconf = options.ttyconf; | 195 | const ttyconf = options.ttyconf; |
| 191 | var counting_writer = std.io.countingWriter(stderr); | 196 | var counting_writer: std.io.CountingWriter = .{ .child_writer = bw.writer() }; |
| 192 | const counting_stderr = counting_writer.writer(); | 197 | const counting_bw = counting_writer.unbufferedWriter(); |
| 193 | const err_msg = eb.getErrorMessage(err_msg_index); | 198 | const err_msg = eb.getErrorMessage(err_msg_index); |
| 194 | if (err_msg.src_loc != .none) { | 199 | if (err_msg.src_loc != .none) { |
| 195 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); | 200 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); |
| 196 | try counting_stderr.writeByteNTimes(' ', indent); | 201 | try counting_bw.writeByteNTimes(' ', indent); |
| 197 | try ttyconf.setColor(stderr, .bold); | 202 | try ttyconf.setColor(bw, .bold); |
| 198 | try counting_stderr.print("{s}:{d}:{d}: ", .{ | 203 | try counting_bw.print("{s}:{d}:{d}: ", .{ |
| 199 | eb.nullTerminatedString(src.data.src_path), | 204 | eb.nullTerminatedString(src.data.src_path), |
| 200 | src.data.line + 1, | 205 | src.data.line + 1, |
| 201 | src.data.column + 1, | 206 | src.data.column + 1, |
| 202 | }); | 207 | }); |
| 203 | try ttyconf.setColor(stderr, color); | 208 | try ttyconf.setColor(bw, color); |
| 204 | try counting_stderr.writeAll(kind); | 209 | try counting_bw.writeAll(kind); |
| 205 | try counting_stderr.writeAll(": "); | 210 | try counting_bw.writeAll(": "); |
| 206 | // This is the length of the part before the error message: | 211 | // This is the length of the part before the error message: |
| 207 | // e.g. "file.zig:4:5: error: " | 212 | // e.g. "file.zig:4:5: error: " |
| 208 | const prefix_len: usize = @intCast(counting_stderr.context.bytes_written); | 213 | const prefix_len: usize = @intCast(counting_bw.context.bytes_written); |
| 209 | try ttyconf.setColor(stderr, .reset); | 214 | try ttyconf.setColor(bw, .reset); |
| 210 | try ttyconf.setColor(stderr, .bold); | 215 | try ttyconf.setColor(bw, .bold); |
| 211 | if (err_msg.count == 1) { | 216 | if (err_msg.count == 1) { |
| 212 | try writeMsg(eb, err_msg, stderr, prefix_len); | 217 | try writeMsg(eb, err_msg, bw, prefix_len); |
| 213 | try stderr.writeByte('\n'); | 218 | try bw.writeByte('\n'); |
| 214 | } else { | 219 | } else { |
| 215 | try writeMsg(eb, err_msg, stderr, prefix_len); | 220 | try writeMsg(eb, err_msg, bw, prefix_len); |
| 216 | try ttyconf.setColor(stderr, .dim); | 221 | try ttyconf.setColor(bw, .dim); |
| 217 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | 222 | try bw.print(" ({d} times)\n", .{err_msg.count}); |
| 218 | } | 223 | } |
| 219 | try ttyconf.setColor(stderr, .reset); | 224 | try ttyconf.setColor(bw, .reset); |
| 220 | if (src.data.source_line != 0 and options.include_source_line) { | 225 | if (src.data.source_line != 0 and options.include_source_line) { |
| 221 | const line = eb.nullTerminatedString(src.data.source_line); | 226 | const line = eb.nullTerminatedString(src.data.source_line); |
| 222 | for (line) |b| switch (b) { | 227 | for (line) |b| switch (b) { |
| 223 | '\t' => try stderr.writeByte(' '), | 228 | '\t' => try bw.writeByte(' '), |
| 224 | else => try stderr.writeByte(b), | 229 | else => try bw.writeByte(b), |
| 225 | }; | 230 | }; |
| 226 | try stderr.writeByte('\n'); | 231 | try bw.writeByte('\n'); |
| 227 | // TODO basic unicode code point monospace width | 232 | // TODO basic unicode code point monospace width |
| 228 | const before_caret = src.data.span_main - src.data.span_start; | 233 | const before_caret = src.data.span_main - src.data.span_start; |
| 229 | // -1 since span.main includes the caret | 234 | // -1 since span.main includes the caret |
| 230 | const after_caret = src.data.span_end -| src.data.span_main -| 1; | 235 | const after_caret = src.data.span_end -| src.data.span_main -| 1; |
| 231 | try stderr.writeByteNTimes(' ', src.data.column - before_caret); | 236 | try bw.writeByteNTimes(' ', src.data.column - before_caret); |
| 232 | try ttyconf.setColor(stderr, .green); | 237 | try ttyconf.setColor(bw, .green); |
| 233 | try stderr.writeByteNTimes('~', before_caret); | 238 | try bw.writeByteNTimes('~', before_caret); |
| 234 | try stderr.writeByte('^'); | 239 | try bw.writeByte('^'); |
| 235 | try stderr.writeByteNTimes('~', after_caret); | 240 | try bw.writeByteNTimes('~', after_caret); |
| 236 | try stderr.writeByte('\n'); | 241 | try bw.writeByte('\n'); |
| 237 | try ttyconf.setColor(stderr, .reset); | 242 | try ttyconf.setColor(bw, .reset); |
| 238 | } | 243 | } |
| 239 | for (eb.getNotes(err_msg_index)) |note| { | 244 | for (eb.getNotes(err_msg_index)) |note| { |
| 240 | try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent); | 245 | try renderErrorMessageToWriter(eb, options, note, bw, "note", .cyan, indent); |
| 241 | } | 246 | } |
| 242 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { | 247 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { |
| 243 | try ttyconf.setColor(stderr, .reset); | 248 | try ttyconf.setColor(bw, .reset); |
| 244 | try ttyconf.setColor(stderr, .dim); | 249 | try ttyconf.setColor(bw, .dim); |
| 245 | try stderr.print("referenced by:\n", .{}); | 250 | try bw.print("referenced by:\n", .{}); |
| 246 | var ref_index = src.end; | 251 | var ref_index = src.end; |
| 247 | for (0..src.data.reference_trace_len) |_| { | 252 | for (0..src.data.reference_trace_len) |_| { |
| 248 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); | 253 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); |
| 249 | ref_index = ref_trace.end; | 254 | ref_index = ref_trace.end; |
| 250 | if (ref_trace.data.src_loc != .none) { | 255 | if (ref_trace.data.src_loc != .none) { |
| 251 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); | 256 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); |
| 252 | try stderr.print(" {s}: {s}:{d}:{d}\n", .{ | 257 | try bw.print(" {s}: {s}:{d}:{d}\n", .{ |
| 253 | eb.nullTerminatedString(ref_trace.data.decl_name), | 258 | eb.nullTerminatedString(ref_trace.data.decl_name), |
| 254 | eb.nullTerminatedString(ref_src.src_path), | 259 | eb.nullTerminatedString(ref_src.src_path), |
| 255 | ref_src.line + 1, | 260 | ref_src.line + 1, |
| ... | @@ -257,36 +262,36 @@ fn renderErrorMessageToWriter( | ... | @@ -257,36 +262,36 @@ fn renderErrorMessageToWriter( |
| 257 | }); | 262 | }); |
| 258 | } else if (ref_trace.data.decl_name != 0) { | 263 | } else if (ref_trace.data.decl_name != 0) { |
| 259 | const count = ref_trace.data.decl_name; | 264 | const count = ref_trace.data.decl_name; |
| 260 | try stderr.print( | 265 | try bw.print( |
| 261 | " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n", | 266 | " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n", |
| 262 | .{ count, count + src.data.reference_trace_len - 1 }, | 267 | .{ count, count + src.data.reference_trace_len - 1 }, |
| 263 | ); | 268 | ); |
| 264 | } else { | 269 | } else { |
| 265 | try stderr.print( | 270 | try bw.print( |
| 266 | " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n", | 271 | " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n", |
| 267 | .{}, | 272 | .{}, |
| 268 | ); | 273 | ); |
| 269 | } | 274 | } |
| 270 | } | 275 | } |
| 271 | try ttyconf.setColor(stderr, .reset); | 276 | try ttyconf.setColor(bw, .reset); |
| 272 | } | 277 | } |
| 273 | } else { | 278 | } else { |
| 274 | try ttyconf.setColor(stderr, color); | 279 | try ttyconf.setColor(bw, color); |
| 275 | try stderr.writeByteNTimes(' ', indent); | 280 | try bw.writeByteNTimes(' ', indent); |
| 276 | try stderr.writeAll(kind); | 281 | try bw.writeAll(kind); |
| 277 | try stderr.writeAll(": "); | 282 | try bw.writeAll(": "); |
| 278 | try ttyconf.setColor(stderr, .reset); | 283 | try ttyconf.setColor(bw, .reset); |
| 279 | const msg = eb.nullTerminatedString(err_msg.msg); | 284 | const msg = eb.nullTerminatedString(err_msg.msg); |
| 280 | if (err_msg.count == 1) { | 285 | if (err_msg.count == 1) { |
| 281 | try stderr.print("{s}\n", .{msg}); | 286 | try bw.print("{s}\n", .{msg}); |
| 282 | } else { | 287 | } else { |
| 283 | try stderr.print("{s}", .{msg}); | 288 | try bw.print("{s}", .{msg}); |
| 284 | try ttyconf.setColor(stderr, .dim); | 289 | try ttyconf.setColor(bw, .dim); |
| 285 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | 290 | try bw.print(" ({d} times)\n", .{err_msg.count}); |
| 286 | } | 291 | } |
| 287 | try ttyconf.setColor(stderr, .reset); | 292 | try ttyconf.setColor(bw, .reset); |
| 288 | for (eb.getNotes(err_msg_index)) |note| { | 293 | for (eb.getNotes(err_msg_index)) |note| { |
| 289 | try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent + 4); | 294 | try renderErrorMessageToWriter(eb, options, note, bw, "note", .cyan, indent + 4); |
| 290 | } | 295 | } |
| 291 | } | 296 | } |
| 292 | } | 297 | } |
| ... | @@ -295,13 +300,13 @@ fn renderErrorMessageToWriter( | ... | @@ -295,13 +300,13 @@ fn renderErrorMessageToWriter( |
| 295 | /// to allow for long, good-looking error messages. | 300 | /// to allow for long, good-looking error messages. |
| 296 | /// | 301 | /// |
| 297 | /// This is used to split the message in `@compileError("hello\nworld")` for example. | 302 | /// This is used to split the message in `@compileError("hello\nworld")` for example. |
| 298 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, stderr: anytype, indent: usize) !void { | 303 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter, indent: usize) !void { |
| 299 | var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n'); | 304 | var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n'); |
| 300 | while (lines.next()) |line| { | 305 | while (lines.next()) |line| { |
| 301 | try stderr.writeAll(line); | 306 | try bw.writeAll(line); |
| 302 | if (lines.index == null) break; | 307 | if (lines.index == null) break; |
| 303 | try stderr.writeByte('\n'); | 308 | try bw.writeByte('\n'); |
| 304 | try stderr.writeByteNTimes(' ', indent); | 309 | try bw.writeByteNTimes(' ', indent); |
| 305 | } | 310 | } |
| 306 | } | 311 | } |
| 307 | 312 | ||
| ... | @@ -398,7 +403,7 @@ pub const Wip = struct { | ... | @@ -398,7 +403,7 @@ pub const Wip = struct { |
| 398 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String { | 403 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String { |
| 399 | const gpa = wip.gpa; | 404 | const gpa = wip.gpa; |
| 400 | const index: String = @intCast(wip.string_bytes.items.len); | 405 | const index: String = @intCast(wip.string_bytes.items.len); |
| 401 | try wip.string_bytes.writer(gpa).print(fmt, args); | 406 | try wip.string_bytes.print(gpa, fmt, args); |
| 402 | try wip.string_bytes.append(gpa, 0); | 407 | try wip.string_bytes.append(gpa, 0); |
| 403 | return index; | 408 | return index; |
| 404 | } | 409 | } |
| ... | @@ -788,9 +793,10 @@ pub const Wip = struct { | ... | @@ -788,9 +793,10 @@ pub const Wip = struct { |
| 788 | 793 | ||
| 789 | const ttyconf: std.io.tty.Config = .no_color; | 794 | const ttyconf: std.io.tty.Config = .no_color; |
| 790 | 795 | ||
| 791 | var bundle_buf = std.ArrayList(u8).init(std.testing.allocator); | 796 | var bundle_buf: std.io.AllocatingWriter = undefined; |
| 797 | const bundle_bw = bundle_buf.init(std.testing.allocator); | ||
| 792 | defer bundle_buf.deinit(); | 798 | defer bundle_buf.deinit(); |
| 793 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_buf.writer()); | 799 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw); |
| 794 | 800 | ||
| 795 | var copy = copy: { | 801 | var copy = copy: { |
| 796 | var wip: ErrorBundle.Wip = undefined; | 802 | var wip: ErrorBundle.Wip = undefined; |
| ... | @@ -803,10 +809,11 @@ pub const Wip = struct { | ... | @@ -803,10 +809,11 @@ pub const Wip = struct { |
| 803 | }; | 809 | }; |
| 804 | defer copy.deinit(std.testing.allocator); | 810 | defer copy.deinit(std.testing.allocator); |
| 805 | 811 | ||
| 806 | var copy_buf = std.ArrayList(u8).init(std.testing.allocator); | 812 | var copy_buf: std.io.AllocatingWriter = undefined; |
| 813 | const copy_bw = copy_buf.init(std.testing.allocator); | ||
| 807 | defer copy_buf.deinit(); | 814 | defer copy_buf.deinit(); |
| 808 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_buf.writer()); | 815 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw); |
| 809 | 816 | ||
| 810 | try std.testing.expectEqualStrings(bundle_buf.items, copy_buf.items); | 817 | try std.testing.expectEqualStrings(bundle_bw.getWritten(), copy_bw.getWritten()); |
| 811 | } | 818 | } |
| 812 | }; | 819 | }; |