authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-04-10 18:20:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:26-07:00
log646454beb5026ba50ae6bf4d75d018d1c67fe77a
treeac314609e1a7af58fe5ba2e7b2fe5224dfa5e404
parentfaab6d5cbf18d25628793994e080f79d95adf4ea

maybe it's better to track bytes written in BufferedWriter


13 files changed, 123 insertions(+), 177 deletions(-)

lib/std/Uri.zig+28-29
...@@ -40,22 +40,17 @@ pub const Component = union(enum) {...@@ -40,22 +40,17 @@ pub const Component = union(enum) {
40 };40 };
41 }41 }
4242
43 pub fn format(43 pub fn format(component: Component, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!usize {
44 component: Component,44 var n: usize = 0;
45 comptime fmt: []const u8,
46 options: std.fmt.Options,
47 writer: *std.io.BufferedWriter,
48 ) anyerror!void {
49 _ = options;
50 if (fmt.len == 0) {45 if (fmt.len == 0) {
51 try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{46 n += try bw.printCount("std.Uri.Component{{ .{s} = \"{}\" }}", .{
52 @tagName(component),47 @tagName(component),
53 std.zig.fmtEscapes(switch (component) {48 std.zig.fmtEscapes(switch (component) {
54 .raw, .percent_encoded => |string| string,49 .raw, .percent_encoded => |string| string,
55 }),50 }),
56 });51 });
57 } else if (comptime std.mem.eql(u8, fmt, "raw")) switch (component) {52 } else if (comptime std.mem.eql(u8, fmt, "raw")) switch (component) {
58 .raw => |raw| try writer.writeAll(raw),53 .raw => |raw| n += try bw.writeAllCount(raw),
59 .percent_encoded => |percent_encoded| {54 .percent_encoded => |percent_encoded| {
60 var start: usize = 0;55 var start: usize = 0;
61 var index: usize = 0;56 var index: usize = 0;
...@@ -64,51 +59,55 @@ pub const Component = union(enum) {...@@ -64,51 +59,55 @@ pub const Component = union(enum) {
64 if (percent_encoded.len - index < 2) continue;59 if (percent_encoded.len - index < 2) continue;
65 const percent_encoded_char =60 const percent_encoded_char =
66 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;61 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
67 try writer.print("{s}{c}", .{62 n += try bw.printCount("{s}{c}", .{
68 percent_encoded[start..percent],63 percent_encoded[start..percent],
69 percent_encoded_char,64 percent_encoded_char,
70 });65 });
71 start = percent + 3;66 start = percent + 3;
72 index = percent + 3;67 index = percent + 3;
73 }68 }
74 try writer.writeAll(percent_encoded[start..]);69 n += try bw.writeAllCount(percent_encoded[start..]);
75 },70 },
76 } else if (comptime std.mem.eql(u8, fmt, "%")) switch (component) {71 } else if (comptime std.mem.eql(u8, fmt, "%")) switch (component) {
77 .raw => |raw| try percentEncode(writer, raw, isUnreserved),72 .raw => |raw| n += try percentEncode(bw, raw, isUnreserved),
78 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),73 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
79 } else if (comptime std.mem.eql(u8, fmt, "user")) switch (component) {74 } else if (comptime std.mem.eql(u8, fmt, "user")) switch (component) {
80 .raw => |raw| try percentEncode(writer, raw, isUserChar),75 .raw => |raw| n += try percentEncode(bw, raw, isUserChar),
81 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),76 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
82 } else if (comptime std.mem.eql(u8, fmt, "password")) switch (component) {77 } else if (comptime std.mem.eql(u8, fmt, "password")) switch (component) {
83 .raw => |raw| try percentEncode(writer, raw, isPasswordChar),78 .raw => |raw| n += try percentEncode(bw, raw, isPasswordChar),
84 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),79 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
85 } else if (comptime std.mem.eql(u8, fmt, "host")) switch (component) {80 } else if (comptime std.mem.eql(u8, fmt, "host")) switch (component) {
86 .raw => |raw| try percentEncode(writer, raw, isHostChar),81 .raw => |raw| n += try percentEncode(bw, raw, isHostChar),
87 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),82 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
88 } else if (comptime std.mem.eql(u8, fmt, "path")) switch (component) {83 } else if (comptime std.mem.eql(u8, fmt, "path")) switch (component) {
89 .raw => |raw| try percentEncode(writer, raw, isPathChar),84 .raw => |raw| n += try percentEncode(bw, raw, isPathChar),
90 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),85 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
91 } else if (comptime std.mem.eql(u8, fmt, "query")) switch (component) {86 } else if (comptime std.mem.eql(u8, fmt, "query")) switch (component) {
92 .raw => |raw| try percentEncode(writer, raw, isQueryChar),87 .raw => |raw| n += try percentEncode(bw, raw, isQueryChar),
93 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),88 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
94 } else if (comptime std.mem.eql(u8, fmt, "fragment")) switch (component) {89 } else if (comptime std.mem.eql(u8, fmt, "fragment")) switch (component) {
95 .raw => |raw| try percentEncode(writer, raw, isFragmentChar),90 .raw => |raw| n += try percentEncode(bw, raw, isFragmentChar),
96 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),91 .percent_encoded => |percent_encoded| n += try bw.writeAllCount(percent_encoded),
97 } else @compileError("invalid format string '" ++ fmt ++ "'");92 } else @compileError("invalid format string '" ++ fmt ++ "'");
93
94 return n;
98 }95 }
9996
100 pub fn percentEncode(97 pub fn percentEncode(
101 writer: *std.io.BufferedWriter,98 bw: *std.io.BufferedWriter,
102 raw: []const u8,99 raw: []const u8,
103 comptime isValidChar: fn (u8) bool,100 comptime isValidChar: fn (u8) bool,
104 ) anyerror!void {101 ) anyerror!usize {
102 var n: usize = 0;
105 var start: usize = 0;103 var start: usize = 0;
106 for (raw, 0..) |char, index| {104 for (raw, 0..) |char, index| {
107 if (isValidChar(char)) continue;105 if (isValidChar(char)) continue;
108 try writer.print("{s}%{X:0>2}", .{ raw[start..index], char });106 n += try bw.printCount("{s}%{X:0>2}", .{ raw[start..index], char });
109 start = index + 1;107 start = index + 1;
110 }108 }
111 try writer.writeAll(raw[start..]);109 n += try bw.writeAllCount(raw[start..]);
110 return n;
112 }111 }
113};112};
114113
lib/std/builtin.zig+12-14
...@@ -34,28 +34,26 @@ pub const StackTrace = struct {...@@ -34,28 +34,26 @@ pub const StackTrace = struct {
34 index: usize,34 index: usize,
35 instruction_addresses: []usize,35 instruction_addresses: []usize,
3636
37 pub fn format(37 pub fn format(st: StackTrace, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!usize {
38 self: StackTrace,38 comptime std.debug.assert(fmt.len == 0);
39 comptime fmt: []const u8,
40 options: std.fmt.FormatOptions,
41 writer: anytype,
42 ) !void {
43 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
4439
45 // TODO: re-evaluate whether to use format() methods at all.40 // TODO: re-evaluate whether to use format() methods at all.
46 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly41 // Until then, avoid an error when using DebugAllocator with WebAssembly
47 // where it tries to call detectTTYConfig here.42 // where it tries to call detectTTYConfig here.
48 if (builtin.os.tag == .freestanding) return;43 if (builtin.os.tag == .freestanding) return 0;
4944
50 _ = options;
51 const debug_info = std.debug.getSelfDebugInfo() catch |err| {45 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
52 return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});46 return bw.printCount("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{
47 @errorName(err),
48 });
53 };49 };
54 const tty_config = std.io.tty.detectConfig(.stderr());50 const tty_config = std.io.tty.detectConfig(.stderr());
55 try writer.writeAll("\n");51 var n: usize = 0;
56 std.debug.writeStackTrace(self, writer, debug_info, tty_config) catch |err| {52 n += try bw.writeAllCount("\n");
57 try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)});53 n += std.debug.writeStackTrace(st, bw, debug_info, tty_config) catch |err| {
54 try bw.print("Unable to print stack trace: {s}\n", .{@errorName(err)});
58 };55 };
56 return n;
59 }57 }
60};58};
6159
lib/std/compress/gzip.zig+9-36
...@@ -1,66 +1,39 @@...@@ -1,66 +1,39 @@
1const std = @import("../std.zig");
1const deflate = @import("flate/deflate.zig");2const deflate = @import("flate/deflate.zig");
2const inflate = @import("flate/inflate.zig");3const inflate = @import("flate/inflate.zig");
34
4/// Decompress compressed data from reader and write plain data to the writer.5/// Decompress compressed data from reader and write plain data to the writer.
5pub fn decompress(reader: anytype, writer: anytype) !void {6pub fn decompress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
6 try inflate.decompress(.gzip, reader, writer);7 try inflate.decompress(.gzip, reader, writer);
7}8}
89
9/// Decompressor type10pub const Decompressor = inflate.Decompressor(.gzip);
10pub fn Decompressor(comptime ReaderType: type) type {
11 return inflate.Decompressor(.gzip, ReaderType);
12}
13
14/// Create Decompressor which will read compressed data from reader.
15pub fn decompressor(reader: anytype) Decompressor(@TypeOf(reader)) {
16 return inflate.decompressor(.gzip, reader);
17}
1811
19/// Compression level, trades between speed and compression size.12/// Compression level, trades between speed and compression size.
20pub const Options = deflate.Options;13pub const Options = deflate.Options;
2114
22/// Compress plain data from reader and write compressed data to the writer.15/// Compress plain data from reader and write compressed data to the writer.
23pub fn compress(reader: anytype, writer: anytype, options: Options) !void {16pub fn compress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter, options: Options) !void {
24 try deflate.compress(.gzip, reader, writer, options);17 try deflate.compress(.gzip, reader, writer, options);
25}18}
2619
27/// Compressor type20pub const Compressor = deflate.Compressor(.gzip);
28pub fn Compressor(comptime WriterType: type) type {
29 return deflate.Compressor(.gzip, WriterType);
30}
31
32/// Create Compressor which outputs compressed data to the writer.
33pub fn compressor(writer: anytype, options: Options) !Compressor(@TypeOf(writer)) {
34 return try deflate.compressor(.gzip, writer, options);
35}
3621
37/// Huffman only compression. Without Lempel-Ziv match searching. Faster22/// Huffman only compression. Without Lempel-Ziv match searching. Faster
38/// compression, less memory requirements but bigger compressed sizes.23/// compression, less memory requirements but bigger compressed sizes.
39pub const huffman = struct {24pub const huffman = struct {
40 pub fn compress(reader: anytype, writer: anytype) !void {25 pub fn compress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
41 try deflate.huffman.compress(.gzip, reader, writer);26 try deflate.huffman.compress(.gzip, reader, writer);
42 }27 }
4328
44 pub fn Compressor(comptime WriterType: type) type {29 pub const Compressor = deflate.huffman.Compressor(.gzip);
45 return deflate.huffman.Compressor(.gzip, WriterType);
46 }
47
48 pub fn compressor(writer: anytype) !huffman.Compressor(@TypeOf(writer)) {
49 return deflate.huffman.compressor(.gzip, writer);
50 }
51};30};
5231
53// No compression store only. Compressed size is slightly bigger than plain.32// No compression store only. Compressed size is slightly bigger than plain.
54pub const store = struct {33pub const store = struct {
55 pub fn compress(reader: anytype, writer: anytype) !void {34 pub fn compress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
56 try deflate.store.compress(.gzip, reader, writer);35 try deflate.store.compress(.gzip, reader, writer);
57 }36 }
5837
59 pub fn Compressor(comptime WriterType: type) type {38 pub const Compressor = deflate.store.Compressor(.gzip);
60 return deflate.store.Compressor(.gzip, WriterType);
61 }
62
63 pub fn compressor(writer: anytype) !store.Compressor(@TypeOf(writer)) {
64 return deflate.store.compressor(.gzip, writer);
65 }
66};39};
lib/std/compress/zstandard.zig+19-25
...@@ -7,21 +7,10 @@ pub const compressed_block = types.compressed_block;...@@ -7,21 +7,10 @@ pub const compressed_block = types.compressed_block;
77
8pub const decompress = @import("zstandard/decompress.zig");8pub const decompress = @import("zstandard/decompress.zig");
99
10pub const DecompressorOptions = struct {
11 verify_checksum: bool = true,
12 window_buffer: []u8,
13
14 /// Recommended amount by the standard. Lower than this may result
15 /// in inability to decompress common streams.
16 pub const default_window_buffer_len = 8 * 1024 * 1024;
17};
18
19pub const Decompressor = struct {10pub const Decompressor = struct {
20 const Self = @This();
21
22 const table_size_max = types.compressed_block.table_size_max;11 const table_size_max = types.compressed_block.table_size_max;
2312
24 source: std.io.CountingReader,13 source: *std.io.BufferedReader,
25 state: enum { NewFrame, InFrame, LastBlock },14 state: enum { NewFrame, InFrame, LastBlock },
26 decode_state: decompress.block.DecodeState,15 decode_state: decompress.block.DecodeState,
27 frame_context: decompress.FrameContext,16 frame_context: decompress.FrameContext,
...@@ -35,6 +24,15 @@ pub const Decompressor = struct {...@@ -35,6 +24,15 @@ pub const Decompressor = struct {
35 checksum: ?u32,24 checksum: ?u32,
36 current_frame_decompressed_size: usize,25 current_frame_decompressed_size: usize,
3726
27 pub const Options = struct {
28 verify_checksum: bool = true,
29 window_buffer: []u8,
30
31 /// Recommended amount by the standard. Lower than this may result
32 /// in inability to decompress common streams.
33 pub const default_window_buffer_len = 8 * 1024 * 1024;
34 };
35
38 const WindowBuffer = struct {36 const WindowBuffer = struct {
39 data: []u8 = undefined,37 data: []u8 = undefined,
40 read_index: usize = 0,38 read_index: usize = 0,
...@@ -49,9 +47,9 @@ pub const Decompressor = struct {...@@ -49,9 +47,9 @@ pub const Decompressor = struct {
49 OutOfMemory,47 OutOfMemory,
50 };48 };
5149
52 pub fn init(source: *std.io.BufferedReader, options: DecompressorOptions) Self {50 pub fn init(source: *std.io.BufferedReader, options: Options) Decompressor {
53 return .{51 return .{
54 .source = std.io.countingReader(source),52 .source = source,
55 .state = .NewFrame,53 .state = .NewFrame,
56 .decode_state = undefined,54 .decode_state = undefined,
57 .frame_context = undefined,55 .frame_context = undefined,
...@@ -67,7 +65,7 @@ pub const Decompressor = struct {...@@ -67,7 +65,7 @@ pub const Decompressor = struct {
67 };65 };
68 }66 }
6967
70 fn frameInit(self: *Self) !void {68 fn frameInit(self: *Decompressor) !void {
71 const source_reader = self.source;69 const source_reader = self.source;
72 switch (try decompress.decodeFrameHeader(source_reader)) {70 switch (try decompress.decodeFrameHeader(source_reader)) {
73 .skippable => |header| {71 .skippable => |header| {
...@@ -98,11 +96,11 @@ pub const Decompressor = struct {...@@ -98,11 +96,11 @@ pub const Decompressor = struct {
98 }96 }
99 }97 }
10098
101 pub fn reader(self: *Self) std.io.Reader {99 pub fn reader(self: *Decompressor) std.io.Reader {
102 return .{ .context = self };100 return .{ .context = self };
103 }101 }
104102
105 pub fn read(self: *Self, buffer: []u8) Error!usize {103 pub fn read(self: *Decompressor, buffer: []u8) Error!usize {
106 if (buffer.len == 0) return 0;104 if (buffer.len == 0) return 0;
107105
108 var size: usize = 0;106 var size: usize = 0;
...@@ -123,7 +121,7 @@ pub const Decompressor = struct {...@@ -123,7 +121,7 @@ pub const Decompressor = struct {
123 return size;121 return size;
124 }122 }
125123
126 fn readInner(self: *Self, buffer: []u8) Error!usize {124 fn readInner(self: *Decompressor, buffer: []u8) Error!usize {
127 std.debug.assert(self.state != .NewFrame);125 std.debug.assert(self.state != .NewFrame);
128126
129 var ring_buffer = RingBuffer{127 var ring_buffer = RingBuffer{
...@@ -198,16 +196,12 @@ pub const Decompressor = struct {...@@ -198,16 +196,12 @@ pub const Decompressor = struct {
198 }196 }
199};197};
200198
201pub fn decompressor(reader: anytype, options: DecompressorOptions) Decompressor(@TypeOf(reader)) {
202 return Decompressor(@TypeOf(reader)).init(reader, options);
203}
204
205fn testDecompress(data: []const u8) ![]u8 {199fn testDecompress(data: []const u8) ![]u8 {
206 const window_buffer = try std.testing.allocator.alloc(u8, 1 << 23);200 const window_buffer = try std.testing.allocator.alloc(u8, 1 << 23);
207 defer std.testing.allocator.free(window_buffer);201 defer std.testing.allocator.free(window_buffer);
208202
209 var in_stream = std.io.fixedBufferStream(data);203 var in_stream = std.io.fixedBufferStream(data);
210 var zstd_stream = decompressor(in_stream.reader(), .{ .window_buffer = window_buffer });204 var zstd_stream: Decompressor = .init(in_stream.reader(), .{ .window_buffer = window_buffer });
211 const result = zstd_stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize));205 const result = zstd_stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize));
212 return result;206 return result;
213}207}
...@@ -260,7 +254,7 @@ fn expectEqualDecodedStreaming(expected: []const u8, input: []const u8) !void {...@@ -260,7 +254,7 @@ fn expectEqualDecodedStreaming(expected: []const u8, input: []const u8) !void {
260 defer std.testing.allocator.free(window_buffer);254 defer std.testing.allocator.free(window_buffer);
261255
262 var in_stream = std.io.fixedBufferStream(input);256 var in_stream = std.io.fixedBufferStream(input);
263 var stream = decompressor(in_stream.reader(), .{ .window_buffer = window_buffer });257 var stream: Decompressor = .init(in_stream.reader(), .{ .window_buffer = window_buffer });
264258
265 const result = try stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize));259 const result = try stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize));
266 defer std.testing.allocator.free(result);260 defer std.testing.allocator.free(result);
...@@ -299,7 +293,7 @@ test "declared raw literals size too large" {...@@ -299,7 +293,7 @@ test "declared raw literals size too large" {
299293
300 var fbs = std.io.fixedBufferStream(input_raw);294 var fbs = std.io.fixedBufferStream(input_raw);
301 var window: [1024]u8 = undefined;295 var window: [1024]u8 = undefined;
302 var stream = decompressor(fbs.reader(), .{ .window_buffer = &window });296 var stream: Decompressor = .init(fbs.reader(), .{ .window_buffer = &window });
303297
304 var buf: [1024]u8 = undefined;298 var buf: [1024]u8 = undefined;
305 try std.testing.expectError(error.MalformedBlock, stream.read(&buf));299 try std.testing.expectError(error.MalformedBlock, stream.read(&buf));
lib/std/compress/zstandard/decompress.zig+3-1
...@@ -629,5 +629,7 @@ pub fn decodeZstandardHeader(...@@ -629,5 +629,7 @@ pub fn decodeZstandardHeader(
629}629}
630630
631test {631test {
632 std.testing.refAllDecls(@This());632 _ = types;
633 _ = block;
634 _ = readers;
633}635}
lib/std/compress/zstandard/readers.zig+3-23
...@@ -31,11 +31,11 @@ pub const ReversedByteReader = struct {...@@ -31,11 +31,11 @@ pub const ReversedByteReader = struct {
31/// FSE compressed data.31/// FSE compressed data.
32pub const ReverseBitReader = struct {32pub const ReverseBitReader = struct {
33 byte_reader: ReversedByteReader,33 byte_reader: ReversedByteReader,
34 bit_reader: std.io.BitReader(.big, ReversedByteReader.Reader),34 bit_reader: std.io.BitReader(.big),
3535
36 pub fn init(self: *ReverseBitReader, bytes: []const u8) error{BitStreamHasNoStartBit}!void {36 pub fn init(self: *ReverseBitReader, bytes: []const u8) error{BitStreamHasNoStartBit}!void {
37 self.byte_reader = ReversedByteReader.init(bytes);37 self.byte_reader = ReversedByteReader.init(bytes);
38 self.bit_reader = std.io.bitReader(.big, self.byte_reader.reader());38 self.bit_reader = .init(self.byte_reader.reader());
39 if (bytes.len == 0) return;39 if (bytes.len == 0) return;
40 var i: usize = 0;40 var i: usize = 0;
41 while (i < 8 and 0 == self.readBitsNoEof(u1, 1) catch unreachable) : (i += 1) {}41 while (i < 8 and 0 == self.readBitsNoEof(u1, 1) catch unreachable) : (i += 1) {}
...@@ -59,24 +59,4 @@ pub const ReverseBitReader = struct {...@@ -59,24 +59,4 @@ pub const ReverseBitReader = struct {
59 }59 }
60};60};
6161
62pub fn BitReader(comptime Reader: type) type {62pub const BitReader = std.io.BitReader(.little);
63 return struct {
64 underlying: std.io.BitReader(.little, Reader),
65
66 pub fn readBitsNoEof(self: *@This(), comptime U: type, num_bits: u16) !U {
67 return self.underlying.readBitsNoEof(U, num_bits);
68 }
69
70 pub fn readBits(self: *@This(), comptime U: type, num_bits: u16, out_bits: *u16) !U {
71 return self.underlying.readBits(U, num_bits, out_bits);
72 }
73
74 pub fn alignToByte(self: *@This()) void {
75 self.underlying.alignToByte();
76 }
77 };
78}
79
80pub fn bitReader(reader: anytype) BitReader(@TypeOf(reader)) {
81 return .{ .underlying = std.io.bitReader(.little, reader) };
82}
lib/std/debug.zig+13-6
...@@ -733,26 +733,28 @@ pub fn writeStackTrace(...@@ -733,26 +733,28 @@ pub fn writeStackTrace(
733 writer: *std.io.BufferedWriter,733 writer: *std.io.BufferedWriter,
734 debug_info: *SelfInfo,734 debug_info: *SelfInfo,
735 tty_config: io.tty.Config,735 tty_config: io.tty.Config,
736) !void {736) !usize {
737 if (builtin.strip_debug_info) return error.MissingDebugInfo;737 if (builtin.strip_debug_info) return error.MissingDebugInfo;
738 var frame_index: usize = 0;738 var frame_index: usize = 0;
739 var frames_left: usize = @min(stack_trace.index, stack_trace.instruction_addresses.len);739 var frames_left: usize = @min(stack_trace.index, stack_trace.instruction_addresses.len);
740 var n: usize = 0;
740741
741 while (frames_left != 0) : ({742 while (frames_left != 0) : ({
742 frames_left -= 1;743 frames_left -= 1;
743 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;744 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
744 }) {745 }) {
745 const return_address = stack_trace.instruction_addresses[frame_index];746 const return_address = stack_trace.instruction_addresses[frame_index];
746 try printSourceAtAddress(debug_info, writer, return_address - 1, tty_config);747 n += try printSourceAtAddress(debug_info, writer, return_address - 1, tty_config);
747 }748 }
748749
749 if (stack_trace.index > stack_trace.instruction_addresses.len) {750 if (stack_trace.index > stack_trace.instruction_addresses.len) {
750 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;751 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
751752
752 tty_config.setColor(writer, .bold) catch {};753 n += tty_config.setColor(writer, .bold) catch {};
753 try writer.print("({d} additional stack frames skipped...)\n", .{dropped_frames});754 n += try writer.printCount("({d} additional stack frames skipped...)\n", .{dropped_frames});
754 tty_config.setColor(writer, .reset) catch {};755 n += tty_config.setColor(writer, .reset) catch {};
755 }756 }
757 return n;
756}758}
757759
758pub const UnwindError = if (have_ucontext)760pub const UnwindError = if (have_ucontext)
...@@ -1100,7 +1102,12 @@ fn printUnwindError(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, addre...@@ -1100,7 +1102,12 @@ fn printUnwindError(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, addre
1100 try tty_config.setColor(writer, .reset);1102 try tty_config.setColor(writer, .reset);
1101}1103}
11021104
1103pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, address: usize, tty_config: io.tty.Config) !void {1105pub fn printSourceAtAddress(
1106 debug_info: *SelfInfo,
1107 writer: *std.io.BufferedWriter,
1108 address: usize,
1109 tty_config: io.tty.Config,
1110) !void {
1104 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {1111 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
1105 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),1112 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
1106 else => return err,1113 else => return err,
lib/std/heap/debug_allocator.zig+9-9
...@@ -436,7 +436,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -436,7 +436,7 @@ pub fn DebugAllocator(comptime config: Config) type {
436 const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);436 const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
437 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);437 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
438 const addr = page_addr + slot_index * size_class;438 const addr = page_addr + slot_index * size_class;
439 log.err("memory address 0x{x} leaked: {}", .{ addr, stack_trace });439 log.err("memory address 0x{x} leaked: {f}", .{ addr, stack_trace });
440 leaks = true;440 leaks = true;
441 }441 }
442 }442 }
...@@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {
463 while (it.next()) |large_alloc| {463 while (it.next()) |large_alloc| {
464 if (config.retain_metadata and large_alloc.freed) continue;464 if (config.retain_metadata and large_alloc.freed) continue;
465 const stack_trace = large_alloc.getStackTrace(.alloc);465 const stack_trace = large_alloc.getStackTrace(.alloc);
466 log.err("memory address 0x{x} leaked: {}", .{466 log.err("memory address 0x{x} leaked: {f}", .{
467 @intFromPtr(large_alloc.bytes.ptr), stack_trace,467 @intFromPtr(large_alloc.bytes.ptr), stack_trace,
468 });468 });
469 leaks = true;469 leaks = true;
...@@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {
522 .index = 0,522 .index = 0,
523 };523 };
524 std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);524 std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);
525 log.err("Double free detected. Allocation: {} First free: {} Second free: {}", .{525 log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
526 alloc_stack_trace, free_stack_trace, second_free_stack_trace,526 alloc_stack_trace, free_stack_trace, second_free_stack_trace,
527 });527 });
528 }528 }
...@@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {
568 .index = 0,568 .index = 0,
569 };569 };
570 std.debug.captureStackTrace(ret_addr, &free_stack_trace);570 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
571 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{571 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
572 entry.value_ptr.bytes.len,572 entry.value_ptr.bytes.len,
573 old_mem.len,573 old_mem.len,
574 entry.value_ptr.getStackTrace(.alloc),574 entry.value_ptr.getStackTrace(.alloc),
...@@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {
678 .index = 0,678 .index = 0,
679 };679 };
680 std.debug.captureStackTrace(ret_addr, &free_stack_trace);680 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
681 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{681 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
682 entry.value_ptr.bytes.len,682 entry.value_ptr.bytes.len,
683 old_mem.len,683 old_mem.len,
684 entry.value_ptr.getStackTrace(.alloc),684 entry.value_ptr.getStackTrace(.alloc),
...@@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {
907 };907 };
908 std.debug.captureStackTrace(return_address, &free_stack_trace);908 std.debug.captureStackTrace(return_address, &free_stack_trace);
909 if (old_memory.len != requested_size) {909 if (old_memory.len != requested_size) {
910 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{910 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
911 requested_size,911 requested_size,
912 old_memory.len,912 old_memory.len,
913 bucketStackTrace(bucket, slot_count, slot_index, .alloc),913 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {
915 });915 });
916 }916 }
917 if (alignment != slot_alignment) {917 if (alignment != slot_alignment) {
918 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{918 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
919 slot_alignment.toByteUnits(),919 slot_alignment.toByteUnits(),
920 alignment.toByteUnits(),920 alignment.toByteUnits(),
921 bucketStackTrace(bucket, slot_count, slot_index, .alloc),921 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {
1006 };1006 };
1007 std.debug.captureStackTrace(return_address, &free_stack_trace);1007 std.debug.captureStackTrace(return_address, &free_stack_trace);
1008 if (memory.len != requested_size) {1008 if (memory.len != requested_size) {
1009 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{1009 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
1010 requested_size,1010 requested_size,
1011 memory.len,1011 memory.len,
1012 bucketStackTrace(bucket, slot_count, slot_index, .alloc),1012 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {
1014 });1014 });
1015 }1015 }
1016 if (alignment != slot_alignment) {1016 if (alignment != slot_alignment) {
1017 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{1017 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
1018 slot_alignment.toByteUnits(),1018 slot_alignment.toByteUnits(),
1019 alignment.toByteUnits(),1019 alignment.toByteUnits(),
1020 bucketStackTrace(bucket, slot_count, slot_index, .alloc),1020 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
lib/std/http/Server.zig+3-7
...@@ -130,13 +130,9 @@ pub const Request = struct {...@@ -130,13 +130,9 @@ pub const Request = struct {
130 write_error: anyerror,130 write_error: anyerror,
131131
132 pub const Compression = union(enum) {132 pub const Compression = union(enum) {
133 pub const DeflateDecompressor = std.compress.zlib.Decompressor(std.io.AnyReader);133 deflate: std.compress.zlib.Decompressor,
134 pub const GzipDecompressor = std.compress.gzip.Decompressor(std.io.AnyReader);134 gzip: std.compress.gzip.Decompressor,
135 pub const ZstdDecompressor = std.compress.zstd.Decompressor(std.io.AnyReader);135 zstd: std.compress.zstd.Decompressor,
136
137 deflate: DeflateDecompressor,
138 gzip: GzipDecompressor,
139 zstd: ZstdDecompressor,
140 none: void,136 none: void,
141 };137 };
142138
lib/std/http/WebSocket.zig+1-1
...@@ -9,7 +9,7 @@ const native_endian = builtin.cpu.arch.endian();...@@ -9,7 +9,7 @@ const native_endian = builtin.cpu.arch.endian();
9key: []const u8,9key: []const u8,
10request: *std.http.Server.Request,10request: *std.http.Server.Request,
11recv_fifo: std.fifo.LinearFifo(u8, .Slice),11recv_fifo: std.fifo.LinearFifo(u8, .Slice),
12reader: std.io.AnyReader,12reader: *std.io.BufferedReader,
13response: std.http.Server.Response,13response: std.http.Server.Response,
14/// Number of bytes that have been peeked but not discarded yet.14/// Number of bytes that have been peeked but not discarded yet.
15outstanding_len: usize,15outstanding_len: usize,
lib/std/io.zig+1-2
...@@ -30,8 +30,7 @@ pub const limitedReader = @import("io/limited_reader.zig").limitedReader;...@@ -30,8 +30,7 @@ pub const limitedReader = @import("io/limited_reader.zig").limitedReader;
30pub const MultiWriter = @import("io/multi_writer.zig").MultiWriter;30pub const MultiWriter = @import("io/multi_writer.zig").MultiWriter;
31pub const multiWriter = @import("io/multi_writer.zig").multiWriter;31pub const multiWriter = @import("io/multi_writer.zig").multiWriter;
3232
33pub const BitReader = @import("io/bit_reader.zig").BitReader;33pub const BitReader = @import("io/bit_reader.zig").Type;
34pub const bitReader = @import("io/bit_reader.zig").bitReader;
3534
36pub const BitWriter = @import("io/bit_writer.zig").BitWriter;35pub const BitWriter = @import("io/bit_writer.zig").BitWriter;
37pub const bitWriter = @import("io/bit_writer.zig").bitWriter;36pub const bitWriter = @import("io/bit_writer.zig").bitWriter;
lib/std/io/BufferedWriter.zig+9-9
...@@ -614,23 +614,23 @@ pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std....@@ -614,23 +614,23 @@ pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.
614 return alignBuffer(bw, buffer, options.width orelse buffer.len, options.alignment, options.fill);614 return alignBuffer(bw, buffer, options.width orelse buffer.len, options.alignment, options.fill);
615}615}
616616
617pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void {617pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!usize {
618 const T = @TypeOf(value);618 const T = @TypeOf(value);
619619 var n: usize = 0;
620 switch (@typeInfo(T)) {620 switch (@typeInfo(T)) {
621 .pointer => |info| {621 .pointer => |info| {
622 try bw.writeAll(@typeName(info.child) ++ "@");622 n += try bw.writeAllCount(@typeName(info.child) ++ "@");
623 if (info.size == .slice)623 if (info.size == .slice)
624 try printIntOptions(bw, @intFromPtr(value.ptr), 16, .lower, .{})624 n += try printIntOptions(bw, @intFromPtr(value.ptr), 16, .lower, .{})
625 else625 else
626 try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});626 n += try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});
627 return;627 return n;
628 },628 },
629 .optional => |info| {629 .optional => |info| {
630 if (@typeInfo(info.child) == .pointer) {630 if (@typeInfo(info.child) == .pointer) {
631 try bw.writeAll(@typeName(info.child) ++ "@");631 n += try bw.writeAll(@typeName(info.child) ++ "@");
632 try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});632 n += try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});
633 return;633 return n;
634 }634 }
635 },635 },
636 else => {},636 else => {},
lib/std/io/bit_reader.zig+13-15
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const bit_reader = @This();
23
3//General note on endianess:4//General note on endianess:
4//Big endian is packed starting in the most significant part of the byte and subsequent5//Big endian is packed starting in the most significant part of the byte and subsequent
...@@ -13,11 +14,11 @@ const std = @import("../std.zig");...@@ -13,11 +14,11 @@ const std = @import("../std.zig");
13// of the byte.14// of the byte.
1415
15/// Creates a bit reader which allows for reading bits from an underlying standard reader16/// Creates a bit reader which allows for reading bits from an underlying standard reader
16pub fn BitReader(comptime endian: std.builtin.Endian) type {17pub fn Type(comptime endian: std.builtin.Endian) type {
17 return struct {18 return struct {
18 reader: *std.io.BufferedReader,19 reader: *std.io.BufferedReader,
19 bits: u8 = 0,20 bits: u8,
20 count: u4 = 0,21 count: u4,
2122
22 const low_bit_mask = [9]u8{23 const low_bit_mask = [9]u8{
23 0b00000000,24 0b00000000,
...@@ -31,11 +32,12 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {...@@ -31,11 +32,12 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {
31 0b11111111,32 0b11111111,
32 };33 };
3334
35 pub fn init(reader: *std.io.BufferedReader) @This() {
36 return .{ .reader = reader, .bits = 0, .count = 0 };
37 }
38
34 fn Bits(comptime T: type) type {39 fn Bits(comptime T: type) type {
35 return struct {40 return struct { T, u16 };
36 T,
37 u16,
38 };
39 }41 }
4042
41 fn initBits(comptime T: type, out: anytype, num: u16) Bits(T) {43 fn initBits(comptime T: type, out: anytype, num: u16) Bits(T) {
...@@ -82,7 +84,7 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {...@@ -82,7 +84,7 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {
82 const full_bytes_left = (num - out_count) / 8;84 const full_bytes_left = (num - out_count) / 8;
8385
84 for (0..full_bytes_left) |_| {86 for (0..full_bytes_left) |_| {
85 const byte = self.reader.readByte() catch |err| switch (err) {87 const byte = self.reader.takeByte() catch |err| switch (err) {
86 error.EndOfStream => return initBits(T, out, out_count),88 error.EndOfStream => return initBits(T, out, out_count),
87 else => |e| return e,89 else => |e| return e,
88 };90 };
...@@ -105,7 +107,7 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {...@@ -105,7 +107,7 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {
105107
106 if (bits_left == 0) return initBits(T, out, out_count);108 if (bits_left == 0) return initBits(T, out, out_count);
107109
108 const final_byte = self.reader.readByte() catch |err| switch (err) {110 const final_byte = self.reader.takeByte() catch |err| switch (err) {
109 error.EndOfStream => return initBits(T, out, out_count),111 error.EndOfStream => return initBits(T, out, out_count),
110 else => |e| return e,112 else => |e| return e,
111 };113 };
...@@ -157,10 +159,6 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {...@@ -157,10 +159,6 @@ pub fn BitReader(comptime endian: std.builtin.Endian) type {
157 };159 };
158}160}
159161
160pub fn bitReader(comptime endian: std.builtin.Endian, reader: *std.io.BufferedReader) BitReader(endian) {
161 return .{ .reader = reader };
162}
163
164///////////////////////////////162///////////////////////////////
165163
166test "api coverage" {164test "api coverage" {
...@@ -168,7 +166,7 @@ test "api coverage" {...@@ -168,7 +166,7 @@ test "api coverage" {
168 const mem_le = [_]u8{ 0b00011101, 0b10010101 };166 const mem_le = [_]u8{ 0b00011101, 0b10010101 };
169167
170 var mem_in_be = std.io.fixedBufferStream(&mem_be);168 var mem_in_be = std.io.fixedBufferStream(&mem_be);
171 var bit_stream_be = bitReader(.big, mem_in_be.reader());169 var bit_stream_be: bit_reader.Type(.big) = .init(mem_in_be.reader());
172170
173 var out_bits: u16 = undefined;171 var out_bits: u16 = undefined;
174172
...@@ -205,7 +203,7 @@ test "api coverage" {...@@ -205,7 +203,7 @@ test "api coverage" {
205 try expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));203 try expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
206204
207 var mem_in_le = std.io.fixedBufferStream(&mem_le);205 var mem_in_le = std.io.fixedBufferStream(&mem_le);
208 var bit_stream_le = bitReader(.little, mem_in_le.reader());206 var bit_stream_le: bit_reader.Type(.little) = .init(mem_in_le.reader());
209207
210 try expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));208 try expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
211 try expect(out_bits == 1);209 try expect(out_bits == 1);