authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-05-29 17:11:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:29-07:00
log3c98e2c826e1a8650090a889cf3a1560335b2968
tree7511982b72d00266ba33347e7d92f0f6cc1436b3
parent2ed47f1ed813d786e4d7d4adf18bd95d81e8e931

std: combine BufferedReader into Reader


59 files changed, 1520 insertions(+), 1727 deletions(-)

lib/compiler/resinator/errors.zig+2-4
......@@ -1082,11 +1082,9 @@ const CorrespondingLines = struct {
10821082 at_eof: bool = false,
10831083 span: SourceMappings.CorrespondingSpan,
10841084 file: std.fs.File,
1085 buffered_reader: BufferedReaderType,
1085 buffered_reader: *std.io.Reader,
10861086 code_page: SupportedCodePage,
10871087
1088 const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.Reader);
1089
10901088 pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines {
10911089 // We don't do line comparison for this error, so don't print the note if the line
10921090 // number is different
......@@ -1105,7 +1103,7 @@ const CorrespondingLines = struct {
11051103 .buffered_reader = undefined,
11061104 .code_page = err_details.code_page,
11071105 };
1108 corresponding_lines.buffered_reader = BufferedReaderType{
1106 corresponding_lines.buffered_reader = .{
11091107 .unbuffered_reader = corresponding_lines.file.reader(),
11101108 };
11111109 errdefer corresponding_lines.deinit();
lib/compiler/std-docs.zig+1-1
......@@ -390,7 +390,7 @@ fn receiveWasmMessage(
390390 gpa: Allocator,
391391 arena: Allocator,
392392 context: *Context,
393 br: *std.io.BufferedReader,
393 br: *std.io.Reader,
394394 result: *?Cache.Path,
395395 result_error_bundle: *std.zig.ErrorBundle,
396396) !void {
lib/docs/wasm/main.zig+1-2
......@@ -778,8 +778,7 @@ export fn decl_type_html(decl_index: Decl.Index) String {
778778const Oom = error{OutOfMemory};
779779
780780fn unpackInner(tar_bytes: []u8) !void {
781 var br: std.io.BufferedReader = undefined;
782 br.initFixed(tar_bytes);
781 var br: std.io.Reader = .fixed(tar_bytes);
783782 var file_name_buffer: [1024]u8 = undefined;
784783 var link_name_buffer: [1024]u8 = undefined;
785784 var it = std.tar.Iterator.init(&br, .{
lib/std/Build/Step/CheckObject.zig+19-20
......@@ -1238,8 +1238,7 @@ const MachODumper = struct {
12381238 }
12391239
12401240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1241 var br: std.io.BufferedReader = undefined;
1242 br.initFixed(@constCast(data));
1241 var br: std.io.Reader = .fixed(data);
12431242
12441243 var seg_id: ?u8 = null;
12451244 var offset: u64 = 0;
......@@ -1349,7 +1348,7 @@ const MachODumper = struct {
13491348 }
13501349
13511350 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1352 var br: std.io.BufferedReader = undefined;
1351 var br: std.io.Reader = undefined;
13531352 br.initFixed(@constCast(data));
13541353
13551354 var seg_id: ?u8 = null;
......@@ -1447,7 +1446,7 @@ const MachODumper = struct {
14471446 defer arena.deinit();
14481447
14491448 var exports: std.ArrayList(Export) = .init(arena.allocator());
1450 var br: std.io.BufferedReader = undefined;
1449 var br: std.io.Reader = undefined;
14511450 br.initFixed(@constCast(data));
14521451 try parseTrieNode(arena.allocator(), &br, "", &exports);
14531452
......@@ -1517,7 +1516,7 @@ const MachODumper = struct {
15171516
15181517 fn parseTrieNode(
15191518 arena: Allocator,
1520 br: *std.io.BufferedReader,
1519 br: *std.io.Reader,
15211520 prefix: []const u8,
15221521 exports: *std.ArrayList(Export),
15231522 ) !void {
......@@ -1705,7 +1704,7 @@ const ElfDumper = struct {
17051704
17061705 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
17071706 const gpa = step.owner.allocator;
1708 var br: std.io.BufferedReader = undefined;
1707 var br: std.io.Reader = undefined;
17091708 br.initFixed(@constCast(bytes));
17101709
17111710 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
......@@ -1780,7 +1779,7 @@ const ElfDumper = struct {
17801779 }
17811780
17821781 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {
1783 var br: std.io.BufferedReader = undefined;
1782 var br: std.io.Reader = undefined;
17841783 br.initFixed(@constCast(data));
17851784 const num = switch (ptr_width) {
17861785 .p32 => try br.takeInt(u32, .big),
......@@ -1851,7 +1850,7 @@ const ElfDumper = struct {
18511850
18521851 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
18531852 const gpa = step.owner.allocator;
1854 var br: std.io.BufferedReader = undefined;
1853 var br: std.io.Reader = undefined;
18551854 br.initFixed(@constCast(bytes));
18561855
18571856 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
......@@ -2354,7 +2353,7 @@ const WasmDumper = struct {
23542353
23552354 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
23562355 const gpa = step.owner.allocator;
2357 var br: std.io.BufferedReader = undefined;
2356 var br: std.io.Reader = undefined;
23582357 br.initFixed(@constCast(bytes));
23592358
23602359 const buf = try br.takeArray(8);
......@@ -2376,10 +2375,10 @@ const WasmDumper = struct {
23762375 fn parseAndDumpInner(
23772376 step: *Step,
23782377 check: Check,
2379 br: *std.io.BufferedReader,
2378 br: *std.io.Reader,
23802379 bw: *std.io.BufferedWriter,
23812380 ) !void {
2382 var section_br: std.io.BufferedReader = undefined;
2381 var section_br: std.io.Reader = undefined;
23832382 switch (check.kind) {
23842383 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
23852384 section_br.initFixed(try br.take(try br.takeLeb128(u32)));
......@@ -2396,7 +2395,7 @@ const WasmDumper = struct {
23962395 fn parseAndDumpSection(
23972396 step: *Step,
23982397 section: std.wasm.Section,
2399 br: *std.io.BufferedReader,
2398 br: *std.io.Reader,
24002399 bw: *std.io.BufferedWriter,
24012400 ) !void {
24022401 try bw.print(
......@@ -2445,7 +2444,7 @@ const WasmDumper = struct {
24452444 }
24462445 }
24472446
2448 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.BufferedReader, entries: u32, bw: *std.io.BufferedWriter) !void {
2447 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.Reader, entries: u32, bw: *std.io.BufferedWriter) !void {
24492448 switch (section) {
24502449 .type => {
24512450 var i: u32 = 0;
......@@ -2576,7 +2575,7 @@ const WasmDumper = struct {
25762575 }
25772576 }
25782577
2579 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !E {
2578 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.Reader, bw: *std.io.BufferedWriter) !E {
25802579 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
25812580 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
25822581 else => |e| return e,
......@@ -2585,7 +2584,7 @@ const WasmDumper = struct {
25852584 return tag;
25862585 }
25872586
2588 fn parseDumpLimits(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2587 fn parseDumpLimits(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
25892588 const flags = try br.takeLeb128(u8);
25902589 const min = try br.takeLeb128(u32);
25912590
......@@ -2593,7 +2592,7 @@ const WasmDumper = struct {
25932592 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
25942593 }
25952594
2596 fn parseDumpInit(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2595 fn parseDumpInit(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
25972596 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
25982597 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
25992598 else => |e| return e,
......@@ -2613,8 +2612,8 @@ const WasmDumper = struct {
26132612 }
26142613
26152614 /// https://webassembly.github.io/spec/core/appendix/custom.html
2616 fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2617 var subsection_br: std.io.BufferedReader = undefined;
2615 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
2616 var subsection_br: std.io.Reader = undefined;
26182617 while (br.seek < br.buffer.len) {
26192618 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
26202619 // The module name subsection ... consists of a single name
......@@ -2662,7 +2661,7 @@ const WasmDumper = struct {
26622661 }
26632662 }
26642663
2665 fn parseDumpProducers(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2664 fn parseDumpProducers(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
26662665 const field_count = try br.takeLeb128(u32);
26672666 try bw.print(
26682667 \\fields {d}
......@@ -2690,7 +2689,7 @@ const WasmDumper = struct {
26902689 }
26912690 }
26922691
2693 fn parseDumpFeatures(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2692 fn parseDumpFeatures(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
26942693 const feature_count = try br.takeLeb128(u32);
26952694 try bw.print(
26962695 \\features {d}
lib/std/coff.zig+6-8
......@@ -1087,10 +1087,9 @@ pub const Coff = struct {
10871087 const pe_pointer_offset = 0x3C;
10881088 const pe_magic = "PE\x00\x00";
10891089
1090 var reader: std.io.BufferedReader = undefined;
1091 reader.initFixed(data[pe_pointer_offset..]);
1090 var reader: std.io.Reader = .fixed(data[pe_pointer_offset..]);
10921091 const coff_header_offset = try reader.readInt(u32, .little);
1093 reader.initFixed(data[coff_header_offset..]);
1092 reader = .fixed(data[coff_header_offset..]);
10941093 const magic = try reader.peek(4);
10951094 const is_image = mem.eql(u8, pe_magic, magic);
10961095
......@@ -1121,16 +1120,15 @@ pub const Coff = struct {
11211120 if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null;
11221121
11231122 const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];
1124 var reader: std.io.BufferedReader = undefined;
1125 reader.initFixed(self.data);
1123 var reader: std.io.Reader = .fixed(self.data);
11261124
11271125 if (self.is_loaded) {
1128 reader.initFixed(self.data[debug_dir.virtual_address..]);
1126 reader = .fixed(self.data[debug_dir.virtual_address..]);
11291127 } else {
11301128 // Find what section the debug_dir is in, in order to convert the RVA to a file offset
11311129 for (self.getSectionHeaders()) |*sect| {
11321130 if (debug_dir.virtual_address >= sect.virtual_address and debug_dir.virtual_address < sect.virtual_address + sect.virtual_size) {
1133 reader.initFixed(self.data[sect.pointer_to_raw_data + (debug_dir.virtual_address - sect.virtual_address) ..]);
1131 reader = .fixed(self.data[sect.pointer_to_raw_data + (debug_dir.virtual_address - sect.virtual_address) ..]);
11341132 break;
11351133 }
11361134 } else return error.InvalidDebugDirectory;
......@@ -1144,7 +1142,7 @@ pub const Coff = struct {
11441142 const debug_dir_entry = try reader.takeStruct(DebugDirectoryEntry);
11451143 if (debug_dir_entry.type == .CODEVIEW) {
11461144 const dir_offset = if (self.is_loaded) debug_dir_entry.address_of_raw_data else debug_dir_entry.pointer_to_raw_data;
1147 reader.initFixed(self.data[dir_offset..]);
1145 reader = .fixed(self.data[dir_offset..]);
11481146 break;
11491147 }
11501148 } else return null;
lib/std/compress/flate.zig+22-44
......@@ -229,8 +229,7 @@ test "compress/decompress" {
229229
230230 // compress original stream to compressed stream
231231 {
232 var original: std.io.BufferedReader = undefined;
233 original.initFixed(@constCast(data));
232 var original: std.io.Reader = .fixed(data);
234233 var compressed: std.io.BufferedWriter = undefined;
235234 compressed.initFixed(&cmp_buf);
236235 var compress: Compress = .init(&original, .raw);
......@@ -246,8 +245,7 @@ test "compress/decompress" {
246245 }
247246 // decompress compressed stream to decompressed stream
248247 {
249 var compressed: std.io.BufferedReader = undefined;
250 compressed.initFixed(cmp_buf[0..compressed_size]);
248 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
251249 var decompressed: std.io.BufferedWriter = undefined;
252250 decompressed.initFixed(&dcm_buf);
253251 try Decompress.pump(container, &compressed, &decompressed);
......@@ -267,8 +265,7 @@ test "compress/decompress" {
267265 }
268266 // decompressor reader interface
269267 {
270 var compressed: std.io.BufferedReader = undefined;
271 compressed.initFixed(cmp_buf[0..compressed_size]);
268 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
272269 var dcm = Decompress.pump(container, &compressed);
273270 var dcm_rdr = dcm.reader();
274271 const n = try dcm_rdr.readAll(&dcm_buf);
......@@ -287,8 +284,7 @@ test "compress/decompress" {
287284
288285 // compress original stream to compressed stream
289286 {
290 var original: std.io.BufferedReader = undefined;
291 original.initFixed(data);
287 var original: std.io.Reader = .fixed(data);
292288 var compressed: std.io.BufferedWriter = undefined;
293289 compressed.initFixed(&cmp_buf);
294290 var cmp = try Compress.Huffman.init(container, &compressed);
......@@ -303,8 +299,7 @@ test "compress/decompress" {
303299 }
304300 // decompress compressed stream to decompressed stream
305301 {
306 var compressed: std.io.BufferedReader = undefined;
307 compressed.initFixed(cmp_buf[0..compressed_size]);
302 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
308303 var decompressed: std.io.BufferedWriter = undefined;
309304 decompressed.initFixed(&dcm_buf);
310305 try Decompress.pump(container, &compressed, &decompressed);
......@@ -323,8 +318,7 @@ test "compress/decompress" {
323318
324319 // compress original stream to compressed stream
325320 {
326 var original: std.io.BufferedReader = undefined;
327 original.initFixed(data);
321 var original: std.io.Reader = .fixed(data);
328322 var compressed: std.io.BufferedWriter = undefined;
329323 compressed.initFixed(&cmp_buf);
330324 var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed);
......@@ -340,8 +334,7 @@ test "compress/decompress" {
340334 }
341335 // decompress compressed stream to decompressed stream
342336 {
343 var compressed: std.io.BufferedReader = undefined;
344 compressed.initFixed(cmp_buf[0..compressed_size]);
337 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
345338 var decompressed: std.io.BufferedWriter = undefined;
346339 decompressed.initFixed(&dcm_buf);
347340 try Decompress.pump(container, &compressed, &decompressed);
......@@ -353,8 +346,7 @@ test "compress/decompress" {
353346}
354347
355348fn testDecompress(comptime container: Container, compressed: []const u8, expected_plain: []const u8) !void {
356 var in: std.io.BufferedReader = undefined;
357 in.initFixed(compressed);
349 var in: std.io.Reader = .fixed(compressed);
358350 var out: std.io.AllocatingWriter = undefined;
359351 out.init(testing.allocator);
360352 defer out.deinit();
......@@ -502,8 +494,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
502494 var plain: std.io.BufferedWriter = undefined;
503495 plain.initFixed(&buffer2);
504496
505 var in: std.io.BufferedReader = undefined;
506 in.initFixed(gzip_data);
497 var in: std.io.Reader = .fixed(gzip_data);
507498 try pkg.decompress(&in, &plain);
508499 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
509500 }
......@@ -515,12 +506,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
515506 var compressed: std.io.BufferedWriter = undefined;
516507 compressed.initFixed(&buffer1);
517508
518 var in: std.io.BufferedReader = undefined;
519 in.initFixed(plain_data);
509 var in: std.io.Reader = .fixed(plain_data);
520510 try pkg.compress(&in, &compressed, .{});
521511
522 var compressed_br: std.io.BufferedReader = undefined;
523 compressed_br.initFixed(&buffer1);
512 var compressed_br: std.io.Reader = .fixed(&buffer1);
524513 try pkg.decompress(&compressed_br, &plain);
525514 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
526515 }
......@@ -532,14 +521,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
532521 var compressed: std.io.BufferedWriter = undefined;
533522 compressed.initFixed(&buffer1);
534523
535 var in: std.io.BufferedReader = undefined;
536 in.initFixed(plain_data);
524 var in: std.io.Reader = .fixed(plain_data);
537525 var cmp = try pkg.compressor(&compressed, .{});
538526 try cmp.compress(&in);
539527 try cmp.finish();
540528
541 var compressed_br: std.io.BufferedReader = undefined;
542 compressed_br.initFixed(&buffer1);
529 var compressed_br: std.io.Reader = .fixed(&buffer1);
543530 var dcp = pkg.decompressor(&compressed_br);
544531 try dcp.decompress(&plain);
545532 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
......@@ -554,12 +541,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
554541 var compressed: std.io.BufferedWriter = undefined;
555542 compressed.initFixed(&buffer1);
556543
557 var in: std.io.BufferedReader = undefined;
558 in.initFixed(plain_data);
544 var in: std.io.Reader = .fixed(plain_data);
559545 try pkg.huffman.compress(&in, &compressed);
560546
561 var compressed_br: std.io.BufferedReader = undefined;
562 compressed_br.initFixed(&buffer1);
547 var compressed_br: std.io.Reader = .fixed(&buffer1);
563548 try pkg.decompress(&compressed_br, &plain);
564549 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
565550 }
......@@ -571,14 +556,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
571556 var compressed: std.io.BufferedWriter = undefined;
572557 compressed.initFixed(&buffer1);
573558
574 var in: std.io.BufferedReader = undefined;
575 in.initFixed(plain_data);
559 var in: std.io.Reader = .fixed(plain_data);
576560 var cmp = try pkg.huffman.compressor(&compressed);
577561 try cmp.compress(&in);
578562 try cmp.finish();
579563
580 var compressed_br: std.io.BufferedReader = undefined;
581 compressed_br.initFixed(&buffer1);
564 var compressed_br: std.io.Reader = .fixed(&buffer1);
582565 try pkg.decompress(&compressed_br, &plain);
583566 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
584567 }
......@@ -593,12 +576,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
593576 var compressed: std.io.BufferedWriter = undefined;
594577 compressed.initFixed(&buffer1);
595578
596 var in: std.io.BufferedReader = undefined;
597 in.initFixed(plain_data);
579 var in: std.io.Reader = .fixed(plain_data);
598580 try pkg.store.compress(&in, &compressed);
599581
600 var compressed_br: std.io.BufferedReader = undefined;
601 compressed_br.initFixed(&buffer1);
582 var compressed_br: std.io.Reader = .fixed(&buffer1);
602583 try pkg.decompress(&compressed_br, &plain);
603584 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
604585 }
......@@ -610,14 +591,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
610591 var compressed: std.io.BufferedWriter = undefined;
611592 compressed.initFixed(&buffer1);
612593
613 var in: std.io.BufferedReader = undefined;
614 in.initFixed(plain_data);
594 var in: std.io.Reader = .fixed(plain_data);
615595 var cmp = try pkg.store.compressor(&compressed);
616596 try cmp.compress(&in);
617597 try cmp.finish();
618598
619 var compressed_br: std.io.BufferedReader = undefined;
620 compressed_br.initFixed(&buffer1);
599 var compressed_br: std.io.Reader = .fixed(&buffer1);
621600 try pkg.decompress(&compressed_br, &plain);
622601 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
623602 }
......@@ -650,8 +629,7 @@ test "zlib should not overshoot" {
650629 0x03, 0x00, 0x8b, 0x61, 0x0f, 0xa4, 0x52, 0x5a, 0x94, 0x12,
651630 };
652631
653 var stream: std.io.BufferedReader = undefined;
654 stream.initFixed(&data);
632 var stream: std.io.Reader = .fixed(&data);
655633 const reader = stream.reader();
656634
657635 var dcp = Decompress.init(reader);
lib/std/compress/flate/Compress.zig+5-5
......@@ -59,7 +59,7 @@ const huffman = flate.huffman;
5959lookup: Lookup = .{},
6060tokens: Tokens = .{},
6161/// Asserted to have a buffer capacity of at least `flate.max_window_len`.
62input: *std.io.BufferedReader,
62input: *std.io.Reader,
6363block_writer: BlockWriter,
6464level: LevelArgs,
6565hasher: Container.Hasher,
......@@ -69,7 +69,7 @@ hasher: Container.Hasher,
6969prev_match: ?Token = null,
7070prev_literal: ?u8 = null,
7171
72pub fn readable(c: *Compress, buffer: []u8) std.io.BufferedReader {
72pub fn readable(c: *Compress, buffer: []u8) std.io.Reader {
7373 return .{
7474 .unbuffered_reader = .{
7575 .context = c,
......@@ -126,7 +126,7 @@ const LevelArgs = struct {
126126 }
127127};
128128
129pub fn init(input: *std.io.BufferedReader, options: Options) Compress {
129pub fn init(input: *std.io.Reader, options: Options) Compress {
130130 return .{
131131 .input = input,
132132 .block_writer = undefined,
......@@ -1147,7 +1147,7 @@ test "file tokenization" {
11471147 const data = case.data;
11481148
11491149 for (levels, 0..) |level, i| { // for each compression level
1150 var original: std.io.BufferedReader = undefined;
1150 var original: std.io.Reader = undefined;
11511151 original.initFixed(data);
11521152
11531153 // buffer for decompressed data
......@@ -1222,7 +1222,7 @@ test "store simple compressor" {
12221222 //0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
12231223 };
12241224
1225 var fbs: std.io.BufferedReader = undefined;
1225 var fbs: std.io.Reader = undefined;
12261226 fbs.initFixed(data);
12271227 var al = std.ArrayList(u8).init(testing.allocator);
12281228 defer al.deinit();
lib/std/compress/flate/Decompress.zig+9-9
......@@ -24,7 +24,7 @@ const Token = @import("Token.zig");
2424const testing = std.testing;
2525const Decompress = @This();
2626
27input: *std.io.BufferedReader,
27input: *std.io.Reader,
2828// Hashes, produces checksum, of uncompressed data for gzip/zlib footer.
2929hasher: Container.Hasher,
3030
......@@ -67,7 +67,7 @@ pub const Error = Container.Error || error{
6767 MissingEndOfBlockCode,
6868};
6969
70pub fn init(input: *std.io.BufferedReader, container: Container) Decompress {
70pub fn init(input: *std.io.Reader, container: Container) Decompress {
7171 return .{
7272 .input = input,
7373 .hasher = .init(container),
......@@ -361,7 +361,7 @@ pub fn reader(self: *Decompress) std.io.Reader {
361361 };
362362}
363363
364pub fn readable(self: *Decompress, buffer: []u8) std.io.BufferedReader {
364pub fn readable(self: *Decompress, buffer: []u8) std.io.Reader {
365365 return reader(self).buffered(buffer);
366366}
367367
......@@ -727,7 +727,7 @@ test "decompress" {
727727 },
728728 };
729729 for (cases) |c| {
730 var fb: std.io.BufferedReader = undefined;
730 var fb: std.io.Reader = undefined;
731731 fb.initFixed(@constCast(c.in));
732732 var aw: std.io.AllocatingWriter = undefined;
733733 aw.init(testing.allocator);
......@@ -788,7 +788,7 @@ test "gzip decompress" {
788788 },
789789 };
790790 for (cases) |c| {
791 var fb: std.io.BufferedReader = undefined;
791 var fb: std.io.Reader = undefined;
792792 fb.initFixed(@constCast(c.in));
793793 var aw: std.io.AllocatingWriter = undefined;
794794 aw.init(testing.allocator);
......@@ -818,7 +818,7 @@ test "zlib decompress" {
818818 },
819819 };
820820 for (cases) |c| {
821 var fb: std.io.BufferedReader = undefined;
821 var fb: std.io.Reader = undefined;
822822 fb.initFixed(@constCast(c.in));
823823 var aw: std.io.AllocatingWriter = undefined;
824824 aw.init(testing.allocator);
......@@ -880,7 +880,7 @@ test "fuzzing tests" {
880880 };
881881
882882 inline for (cases, 0..) |c, case_no| {
883 var in: std.io.BufferedReader = undefined;
883 var in: std.io.Reader = undefined;
884884 in.initFixed(@constCast(@embedFile("testdata/fuzz/" ++ c.input ++ ".input")));
885885 var aw: std.io.AllocatingWriter = undefined;
886886 aw.init(testing.allocator);
......@@ -903,7 +903,7 @@ test "bug 18966" {
903903 const input = @embedFile("testdata/fuzz/bug_18966.input");
904904 const expect = @embedFile("testdata/fuzz/bug_18966.expect");
905905
906 var in: std.io.BufferedReader = undefined;
906 var in: std.io.Reader = undefined;
907907 in.initFixed(@constCast(input));
908908 var aw: std.io.AllocatingWriter = undefined;
909909 aw.init(testing.allocator);
......@@ -921,7 +921,7 @@ test "reading into empty buffer" {
921921 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen
922922 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0a, // non compressed data
923923 };
924 var in: std.io.BufferedReader = undefined;
924 var in: std.io.Reader = undefined;
925925 in.initFixed(@constCast(input));
926926 var decomp: Decompress = .init(&in, .raw);
927927 var decompress_br = decomp.readable(&.{});
lib/std/compress/lzma.zig+21-21
......@@ -11,7 +11,7 @@ pub const RangeDecoder = struct {
1111 range: u32,
1212 code: u32,
1313
14 pub fn init(rd: *RangeDecoder, br: *std.io.BufferedReader) std.io.Reader.Error!usize {
14 pub fn init(rd: *RangeDecoder, br: *std.io.Reader) std.io.Reader.Error!usize {
1515 const reserved = try br.takeByte();
1616 if (reserved != 0) return error.CorruptInput;
1717 rd.* = .{
......@@ -25,14 +25,14 @@ pub const RangeDecoder = struct {
2525 return self.code == 0;
2626 }
2727
28 inline fn normalize(self: *RangeDecoder, br: *std.io.BufferedReader) !void {
28 inline fn normalize(self: *RangeDecoder, br: *std.io.Reader) !void {
2929 if (self.range < 0x0100_0000) {
3030 self.range <<= 8;
3131 self.code = (self.code << 8) ^ @as(u32, try br.takeByte());
3232 }
3333 }
3434
35 inline fn getBit(self: *RangeDecoder, br: *std.io.BufferedReader) !bool {
35 inline fn getBit(self: *RangeDecoder, br: *std.io.Reader) !bool {
3636 self.range >>= 1;
3737
3838 const bit = self.code >= self.range;
......@@ -43,7 +43,7 @@ pub const RangeDecoder = struct {
4343 return bit;
4444 }
4545
46 pub fn get(self: *RangeDecoder, br: *std.io.BufferedReader, count: usize) !u32 {
46 pub fn get(self: *RangeDecoder, br: *std.io.Reader, count: usize) !u32 {
4747 var result: u32 = 0;
4848 var i: usize = 0;
4949 while (i < count) : (i += 1)
......@@ -51,7 +51,7 @@ pub const RangeDecoder = struct {
5151 return result;
5252 }
5353
54 pub inline fn decodeBit(self: *RangeDecoder, br: *std.io.BufferedReader, prob: *u16, update: bool) !bool {
54 pub inline fn decodeBit(self: *RangeDecoder, br: *std.io.Reader, prob: *u16, update: bool) !bool {
5555 const bound = (self.range >> 11) * prob.*;
5656
5757 if (self.code < bound) {
......@@ -74,7 +74,7 @@ pub const RangeDecoder = struct {
7474
7575 fn parseBitTree(
7676 self: *RangeDecoder,
77 br: *std.io.BufferedReader,
77 br: *std.io.Reader,
7878 num_bits: u5,
7979 probs: []u16,
8080 update: bool,
......@@ -90,7 +90,7 @@ pub const RangeDecoder = struct {
9090
9191 pub fn parseReverseBitTree(
9292 self: *RangeDecoder,
93 br: *std.io.BufferedReader,
93 br: *std.io.Reader,
9494 num_bits: u5,
9595 probs: []u16,
9696 offset: usize,
......@@ -117,7 +117,7 @@ pub const LenDecoder = struct {
117117
118118 pub fn decode(
119119 self: *LenDecoder,
120 br: *std.io.BufferedReader,
120 br: *std.io.Reader,
121121 decoder: *RangeDecoder,
122122 pos_state: usize,
123123 update: bool,
......@@ -148,7 +148,7 @@ pub fn BitTree(comptime num_bits: usize) type {
148148
149149 pub fn parse(
150150 self: *Self,
151 br: *std.io.BufferedReader,
151 br: *std.io.Reader,
152152 decoder: *RangeDecoder,
153153 update: bool,
154154 ) !u32 {
......@@ -157,7 +157,7 @@ pub fn BitTree(comptime num_bits: usize) type {
157157
158158 pub fn parseReverse(
159159 self: *Self,
160 br: *std.io.BufferedReader,
160 br: *std.io.Reader,
161161 decoder: *RangeDecoder,
162162 update: bool,
163163 ) !u32 {
......@@ -222,7 +222,7 @@ pub const Decode = struct {
222222 dict_size: u32,
223223 unpacked_size: ?u64,
224224
225 pub fn readHeader(br: *std.io.BufferedReader, options: Options) std.io.Reader.Error!Params {
225 pub fn readHeader(br: *std.io.Reader, options: Options) std.io.Reader.Error!Params {
226226 var props = try br.readByte();
227227 if (props >= 225) {
228228 return error.CorruptInput;
......@@ -319,7 +319,7 @@ pub const Decode = struct {
319319 fn processNextInner(
320320 self: *Decode,
321321 allocator: Allocator,
322 br: *std.io.BufferedReader,
322 br: *std.io.Reader,
323323 bw: *std.io.BufferedWriter,
324324 buffer: anytype,
325325 decoder: *RangeDecoder,
......@@ -416,7 +416,7 @@ pub const Decode = struct {
416416 fn processNext(
417417 self: *Decode,
418418 allocator: Allocator,
419 br: *std.io.BufferedReader,
419 br: *std.io.Reader,
420420 bw: *std.io.BufferedWriter,
421421 buffer: anytype,
422422 decoder: *RangeDecoder,
......@@ -428,7 +428,7 @@ pub const Decode = struct {
428428 pub fn process(
429429 self: *Decode,
430430 allocator: Allocator,
431 br: *std.io.BufferedReader,
431 br: *std.io.Reader,
432432 bw: *std.io.BufferedWriter,
433433 buffer: anytype,
434434 decoder: *RangeDecoder,
......@@ -460,7 +460,7 @@ pub const Decode = struct {
460460
461461 fn decodeLiteral(
462462 self: *Decode,
463 br: *std.io.BufferedReader,
463 br: *std.io.Reader,
464464 buffer: anytype,
465465 decoder: *RangeDecoder,
466466 update: bool,
......@@ -502,7 +502,7 @@ pub const Decode = struct {
502502
503503 fn decodeDistance(
504504 self: *Decode,
505 br: *std.io.BufferedReader,
505 br: *std.io.Reader,
506506 decoder: *RangeDecoder,
507507 length: usize,
508508 update: bool,
......@@ -542,19 +542,19 @@ pub const Decompress = struct {
542542 error{ CorruptInput, EndOfStream, Overflow };
543543
544544 allocator: Allocator,
545 in_reader: *std.io.BufferedReader,
545 in_reader: *std.io.Reader,
546546 to_read: std.ArrayListUnmanaged(u8),
547547
548548 buffer: LzCircularBuffer,
549549 decoder: RangeDecoder,
550550 state: Decode,
551551
552 pub fn initOptions(allocator: Allocator, br: *std.io.BufferedReader, options: Decode.Options) !Decompress {
552 pub fn initOptions(allocator: Allocator, br: *std.io.Reader, options: Decode.Options) !Decompress {
553553 const params = try Decode.Params.readHeader(br, options);
554554 return init(allocator, br, params, options.memlimit);
555555 }
556556
557 pub fn init(allocator: Allocator, source: *std.io.BufferedReader, params: Decode.Params, memlimit: ?usize) !Decompress {
557 pub fn init(allocator: Allocator, source: *std.io.Reader, params: Decode.Params, memlimit: ?usize) !Decompress {
558558 return .{
559559 .allocator = allocator,
560560 .in_reader = source,
......@@ -839,7 +839,7 @@ test "Vec2D get addition overflow" {
839839
840840fn testDecompress(compressed: []const u8) ![]u8 {
841841 const allocator = std.testing.allocator;
842 var br: std.io.BufferedReader = undefined;
842 var br: std.io.Reader = undefined;
843843 br.initFixed(compressed);
844844 var decompressor = try Decompress.initOptions(allocator, &br, .{});
845845 defer decompressor.deinit();
......@@ -927,7 +927,7 @@ test "too small uncompressed size in header" {
927927
928928test "reading one byte" {
929929 const compressed = @embedFile("testdata/good-known_size-with_eopm.lzma");
930 var br: std.io.BufferedReader = undefined;
930 var br: std.io.Reader = undefined;
931931 br.initFixed(compressed);
932932 var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{});
933933 defer decompressor.deinit();
lib/std/compress/lzma2.zig+5-5
......@@ -2,7 +2,7 @@ const std = @import("../std.zig");
22const Allocator = std.mem.Allocator;
33const lzma = std.compress.lzma;
44
5pub fn decompress(gpa: Allocator, reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) std.io.Reader.StreamError!void {
5pub fn decompress(gpa: Allocator, reader: *std.io.Reader, writer: *std.io.BufferedWriter) std.io.Reader.StreamError!void {
66 var decoder = try Decode.init(gpa);
77 defer decoder.deinit(gpa);
88 return decoder.decompress(gpa, reader, writer);
......@@ -33,7 +33,7 @@ pub const Decode = struct {
3333 pub fn decompress(
3434 self: *Decode,
3535 allocator: Allocator,
36 reader: *std.io.BufferedReader,
36 reader: *std.io.Reader,
3737 writer: *std.io.BufferedWriter,
3838 ) !void {
3939 var accum = LzAccumBuffer.init(std.math.maxInt(usize));
......@@ -56,7 +56,7 @@ pub const Decode = struct {
5656 fn parseLzma(
5757 self: *Decode,
5858 allocator: Allocator,
59 br: *std.io.BufferedReader,
59 br: *std.io.Reader,
6060 writer: *std.io.BufferedWriter,
6161 accum: *LzAccumBuffer,
6262 status: u8,
......@@ -149,7 +149,7 @@ pub const Decode = struct {
149149
150150 fn parseUncompressed(
151151 allocator: Allocator,
152 reader: *std.io.BufferedReader,
152 reader: *std.io.Reader,
153153 writer: *std.io.BufferedWriter,
154154 accum: *LzAccumBuffer,
155155 reset_dict: bool,
......@@ -276,7 +276,7 @@ test decompress {
276276 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02,
277277 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00,
278278 };
279 var stream: std.io.BufferedReader = undefined;
279 var stream: std.io.Reader = undefined;
280280 stream.initFixed(&compressed);
281281 var decomp: std.io.AllocatingWriter = undefined;
282282 const decomp_bw = decomp.init(std.testing.allocator);
lib/std/compress/xz/test.zig+2-3
......@@ -3,10 +3,9 @@ const testing = std.testing;
33const xz = std.compress.xz;
44
55fn decompress(data: []const u8) ![]u8 {
6 var in_stream: std.io.BufferedReader = undefined;
7 in_stream.initFixed(data);
6 var r: std.io.Reader = .fixed(data);
87
9 var xz_stream = try xz.decompress(testing.allocator, &in_stream);
8 var xz_stream = try xz.decompress(testing.allocator, &r);
109 defer xz_stream.deinit();
1110
1211 return xz_stream.reader().readAllAlloc(testing.allocator, std.math.maxInt(usize));
lib/std/compress/zstd.zig+2-4
......@@ -82,8 +82,7 @@ fn testDecompress(gpa: std.mem.Allocator, compressed: []const u8) ![]u8 {
8282 var out: std.ArrayListUnmanaged(u8) = .empty;
8383 defer out.deinit(gpa);
8484
85 var in: std.io.BufferedReader = undefined;
86 in.initFixed(@constCast(compressed));
85 var in: std.io.Reader = .fixed(compressed);
8786 var zstd_stream: Decompress = .init(&in, .{});
8887 try zstd_stream.reader().readRemainingArrayList(gpa, null, &out, .unlimited, default_window_len);
8988
......@@ -103,8 +102,7 @@ fn testExpectDecompressError(err: anyerror, compressed: []const u8) !void {
103102 var out: std.ArrayListUnmanaged(u8) = .empty;
104103 defer out.deinit(gpa);
105104
106 var in: std.io.BufferedReader = undefined;
107 in.initFixed(@constCast(compressed));
105 var in: std.io.Reader = .fixed(compressed);
108106 var zstd_stream: Decompress = .init(&in, .{});
109107 try std.testing.expectError(
110108 error.ReadFailed,
lib/std/compress/zstd/Decompress.zig+11-12
......@@ -4,10 +4,9 @@ const assert = std.debug.assert;
44const Reader = std.io.Reader;
55const Limit = std.io.Limit;
66const BufferedWriter = std.io.BufferedWriter;
7const BufferedReader = std.io.BufferedReader;
87const zstd = @import("../zstd.zig");
98
10input: *BufferedReader,
9input: *Reader,
1110state: State,
1211verify_checksum: bool,
1312err: ?Error = null,
......@@ -63,7 +62,7 @@ pub const Error = error{
6362 WindowSizeUnknown,
6463};
6564
66pub fn init(input: *BufferedReader, options: Options) Decompress {
65pub fn init(input: *Reader, options: Options) Decompress {
6766 return .{
6867 .input = input,
6968 .state = .new_frame,
......@@ -305,7 +304,7 @@ pub const Frame = struct {
305304
306305 pub const DecodeError = Reader.Error || error{ReservedBitSet};
307306
308 pub fn decode(in: *BufferedReader) DecodeError!Header {
307 pub fn decode(in: *Reader) DecodeError!Header {
309308 const descriptor: Descriptor = @bitCast(try in.takeByte());
310309
311310 if (descriptor.reserved) return error.ReservedBitSet;
......@@ -446,7 +445,7 @@ pub const Frame = struct {
446445 /// FSE tables from `in`.
447446 pub fn prepare(
448447 self: *Decode,
449 in: *BufferedReader,
448 in: *Reader,
450449 remaining: *Limit,
451450 literals: LiteralsSection,
452451 sequences_header: SequencesSection.Header,
......@@ -536,7 +535,7 @@ pub const Frame = struct {
536535 /// TODO: don't use `@field`
537536 fn updateFseTable(
538537 self: *Decode,
539 in: *BufferedReader,
538 in: *Reader,
540539 remaining: *Limit,
541540 comptime choice: DataType,
542541 mode: SequencesSection.Header.Mode,
......@@ -858,7 +857,7 @@ pub const LiteralsSection = struct {
858857 compressed_size: ?u18,
859858
860859 /// Decode a literals section header.
861 pub fn decode(in: *BufferedReader, remaining: *Limit) !Header {
860 pub fn decode(in: *Reader, remaining: *Limit) !Header {
862861 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
863862 const byte0 = try in.takeByte();
864863 const block_type: BlockType = @enumFromInt(byte0 & 0b11);
......@@ -965,7 +964,7 @@ pub const LiteralsSection = struct {
965964 MissingStartBit,
966965 };
967966
968 pub fn decode(in: *BufferedReader, remaining: *Limit) HuffmanTree.DecodeError!HuffmanTree {
967 pub fn decode(in: *Reader, remaining: *Limit) HuffmanTree.DecodeError!HuffmanTree {
969968 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
970969 const header = try in.takeByte();
971970 if (header < 128) {
......@@ -976,7 +975,7 @@ pub const LiteralsSection = struct {
976975 }
977976
978977 fn decodeDirect(
979 in: *BufferedReader,
978 in: *Reader,
980979 remaining: *Limit,
981980 encoded_symbol_count: usize,
982981 ) HuffmanTree.DecodeError!HuffmanTree {
......@@ -993,7 +992,7 @@ pub const LiteralsSection = struct {
993992 }
994993
995994 fn decodeFse(
996 in: *BufferedReader,
995 in: *Reader,
997996 remaining: *Limit,
998997 compressed_size: usize,
999998 ) HuffmanTree.DecodeError!HuffmanTree {
......@@ -1162,7 +1161,7 @@ pub const LiteralsSection = struct {
11621161 MissingStartBit,
11631162 };
11641163
1165 pub fn decode(in: *BufferedReader, remaining: *Limit, buffer: []u8) DecodeError!LiteralsSection {
1164 pub fn decode(in: *Reader, remaining: *Limit, buffer: []u8) DecodeError!LiteralsSection {
11661165 const header = try Header.decode(in, remaining);
11671166 switch (header.block_type) {
11681167 .raw => {
......@@ -1233,7 +1232,7 @@ pub const SequencesSection = struct {
12331232 ReadFailed,
12341233 };
12351234
1236 pub fn decode(in: *BufferedReader, remaining: *Limit) DecodeError!Header {
1235 pub fn decode(in: *Reader, remaining: *Limit) DecodeError!Header {
12371236 var sequence_count: u24 = undefined;
12381237
12391238 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
lib/std/crypto/codecs/asn1.zig+2-4
......@@ -154,8 +154,7 @@ pub const Tag = struct {
154154
155155test Tag {
156156 const buf = [_]u8{0xa3};
157 var stream: std.io.BufferedReader = undefined;
158 stream.initFixed(&buf);
157 var stream: std.io.Reader = .fixed(&buf);
159158 const t = Tag.decode(stream.reader());
160159 try std.testing.expectEqual(Tag.init(@enumFromInt(3), true, .context_specific), t);
161160}
......@@ -185,8 +184,7 @@ pub const Element = struct {
185184 /// - Ensures length is within `bytes`
186185 /// - Ensures length is less than `std.math.maxInt(Index)`
187186 pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {
188 var reader: std.io.BufferedReader = undefined;
189 reader.initFixed(bytes[index..]);
187 var reader: std.io.Reader = .fixed(bytes[index..]);
190188
191189 const tag = try Tag.decode(reader);
192190 const size_or_len_size = try reader.readByte();
lib/std/crypto/ecdsa.zig+10-11
......@@ -155,20 +155,20 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
155155 }
156156
157157 // Read a DER-encoded integer.
158 // Asserts `br` has storage capacity >= 2.
159 fn readDerInt(out: []u8, br: *std.io.BufferedReader) EncodingError!void {
160 const buf = br.take(2) catch return error.InvalidEncoding;
158 // Asserts `r` has storage capacity >= 2.
159 fn readDerInt(out: []u8, r: *std.io.Reader) EncodingError!void {
160 const buf = r.take(2) catch return error.InvalidEncoding;
161161 if (buf[0] != 0x02) return error.InvalidEncoding;
162162 var expected_len: usize = buf[1];
163163 if (expected_len == 0 or expected_len > 1 + out.len) return error.InvalidEncoding;
164164 var has_top_bit = false;
165165 if (expected_len == 1 + out.len) {
166 if ((br.takeByte() catch return error.InvalidEncoding) != 0) return error.InvalidEncoding;
166 if ((r.takeByte() catch return error.InvalidEncoding) != 0) return error.InvalidEncoding;
167167 expected_len -= 1;
168168 has_top_bit = true;
169169 }
170170 const out_slice = out[out.len - expected_len ..];
171 br.readSlice(out_slice) catch return error.InvalidEncoding;
171 r.readSlice(out_slice) catch return error.InvalidEncoding;
172172 if (@intFromBool(has_top_bit) != out[0] >> 7) return error.InvalidEncoding;
173173 }
174174
......@@ -176,14 +176,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
176176 /// Returns InvalidEncoding if the DER encoding is invalid.
177177 pub fn fromDer(der: []const u8) EncodingError!Signature {
178178 if (der.len < 2) return error.InvalidEncoding;
179 var br: std.io.BufferedReader = undefined;
180 br.initFixed(@constCast(der));
181 const buf = br.take(2) catch return error.InvalidEncoding;
179 var r: std.io.Reader = .fixed(der);
180 const buf = r.take(2) catch return error.InvalidEncoding;
182181 if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) return error.InvalidEncoding;
183182 var sig: Signature = mem.zeroInit(Signature, .{});
184 try readDerInt(&sig.r, &br);
185 try readDerInt(&sig.s, &br);
186 if (br.seek != der.len) return error.InvalidEncoding;
183 try readDerInt(&sig.r, &r);
184 try readDerInt(&sig.s, &r);
185 if (r.seek != der.len) return error.InvalidEncoding;
187186 return sig;
188187 }
189188 };
lib/std/crypto/tls.zig+2-2
......@@ -655,7 +655,7 @@ pub const Decoder = struct {
655655 }
656656
657657 /// Use this function to increase `their_end`.
658 pub fn readAtLeast(d: *Decoder, stream: *std.io.BufferedReader, their_amt: usize) !void {
658 pub fn readAtLeast(d: *Decoder, stream: *std.io.Reader, their_amt: usize) !void {
659659 assert(!d.disable_reads);
660660 const existing_amt = d.cap - d.idx;
661661 d.their_end = d.idx + their_amt;
......@@ -672,7 +672,7 @@ pub const Decoder = struct {
672672
673673 /// Same as `readAtLeast` but also increases `our_end` by exactly `our_amt`.
674674 /// Use when `our_amt` is calculated by us, not by them.
675 pub fn readAtLeastOurAmt(d: *Decoder, stream: *std.io.BufferedReader, our_amt: usize) !void {
675 pub fn readAtLeastOurAmt(d: *Decoder, stream: *std.io.Reader, our_amt: usize) !void {
676676 assert(!d.disable_reads);
677677 try readAtLeast(d, stream, our_amt);
678678 d.our_end = d.idx + our_amt;
lib/std/crypto/tls/Client.zig+3-3
......@@ -21,7 +21,7 @@ const array = tls.array;
2121/// here via `reader`.
2222///
2323/// The buffer is asserted to have capacity at least `min_buffer_len`.
24input: *std.io.BufferedReader,
24input: *std.io.Reader,
2525
2626/// The encrypted stream from the client to the server. Bytes are pushed here
2727/// via `writer`.
......@@ -85,7 +85,7 @@ pub const SslKeyLog = struct {
8585 }
8686};
8787
88/// The `std.io.BufferedReader` supplied to `init` requires a buffer capacity
88/// The `std.io.Reader` supplied to `init` requires a buffer capacity
8989/// at least this amount.
9090pub const min_buffer_len = tls.max_ciphertext_record_len;
9191
......@@ -175,7 +175,7 @@ const InitError = error{
175175/// `input` is asserted to have buffer capacity at least `min_buffer_len`.
176176pub fn init(
177177 client: *Client,
178 input: *std.io.BufferedReader,
178 input: *std.io.Reader,
179179 output: *std.io.BufferedWriter,
180180 options: Options,
181181) InitError!void {
lib/std/debug/Dwarf.zig+1-2
......@@ -2235,8 +2235,7 @@ pub const ElfModule = struct {
22352235
22362236 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
22372237 sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: {
2238 var section_reader: std.io.BufferedReader = undefined;
2239 section_reader.initFixed(@constCast(section_bytes));
2238 var section_reader: std.io.Reader = .fixed(section_bytes);
22402239 const chdr = section_reader.takeStruct(elf.Chdr) catch continue;
22412240 if (chdr.ch_type != .ZLIB) continue;
22422241 const ch_size = chdr.ch_size;
lib/std/debug/Dwarf/call_frame.zig+1-1
......@@ -136,7 +136,7 @@ pub const Instruction = union(Opcode) {
136136 },
137137
138138 pub fn read(
139 reader: *std.io.BufferedReader,
139 reader: *std.io.Reader,
140140 addr_size_bytes: u8,
141141 endian: std.builtin.Endian,
142142 ) !Instruction {
lib/std/debug/Dwarf/expression.zig+1-2
......@@ -774,8 +774,7 @@ pub fn StackMachine(comptime options: Options) type {
774774 }
775775
776776 fn nextLeb128(expression: []const u8, i: *usize, comptime I: type) !I {
777 var br: std.io.BufferedReader = undefined;
778 br.initFixed(@constCast(expression));
777 var br: std.io.Reader = .fixed(expression);
779778 br.seek = i.*;
780779 assert(br.seek <= br.end);
781780 const result = br.takeLeb128(I) catch |err| switch (err) {
lib/std/debug/FixedBufferReader.zig+2-2
......@@ -1,6 +1,6 @@
11//! Optimized for performance in debug builds.
22
3// TODO I'm pretty sure this can be deleted thanks to the new std.io.BufferedReader semantics
3// TODO I'm pretty sure this can be deleted thanks to the new std.io.Reader semantics
44
55const std = @import("../std.zig");
66const MemoryAccessor = std.debug.MemoryAccessor;
......@@ -52,7 +52,7 @@ pub fn readIntChecked(
5252}
5353
5454pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
55 var br: std.io.BufferedReader = undefined;
55 var br: std.io.Reader = undefined;
5656 br.initFixed(@constCast(fbr.buf));
5757 br.seek = fbr.pos;
5858 const result = br.takeLeb128(T);
lib/std/debug/SelfInfo.zig+4-3
......@@ -2025,9 +2025,10 @@ pub const VirtualMachine = struct {
20252025 assert(self.cie_row == null);
20262026 if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return error.AddressOutOfRange;
20272027
2028 var readers: [2]std.io.BufferedReader = undefined;
2029 readers[0].initFixed(@constCast(cie.initial_instructions));
2030 readers[1].initFixed(@constCast(fde.instructions));
2028 var readers: [2]std.io.Reader = .{
2029 .fixed(cie.initial_instructions),
2030 .fixed(fde.instructions),
2031 };
20312032
20322033 var prev_row: Row = self.current_row;
20332034 for (&readers, [2]bool{ true, false }) |*reader, is_initial| {
lib/std/elf.zig+3-3
......@@ -510,10 +510,10 @@ pub const Header = struct {
510510
511511 pub const ReadError = std.io.Reader.Error || ParseError;
512512
513 pub fn read(br: *std.io.BufferedReader) ReadError!Header {
514 const buf = try br.peek(@sizeOf(Elf64_Ehdr));
513 pub fn read(r: *std.io.Reader) ReadError!Header {
514 const buf = try r.peek(@sizeOf(Elf64_Ehdr));
515515 const result = try parse(@ptrCast(buf));
516 br.toss(if (result.is_64) @sizeOf(Elf64_Ehdr) else @sizeOf(Elf32_Ehdr));
516 r.toss(if (result.is_64) @sizeOf(Elf64_Ehdr) else @sizeOf(Elf32_Ehdr));
517517 return result;
518518 }
519519
lib/std/fs/File.zig+18-11
......@@ -904,6 +904,7 @@ pub const Reader = struct {
904904 size: ?u64 = null,
905905 size_err: ?GetEndPosError = null,
906906 seek_err: ?Reader.SeekError = null,
907 interface: std.io.Reader,
907908
908909 pub const SeekError = File.SeekError || error{
909910 /// Seeking fell back to reading, and reached the end before the requested seek position.
......@@ -940,18 +941,24 @@ pub const Reader = struct {
940941 }
941942 };
942943
943 pub fn interface(r: *Reader) std.io.Reader {
944 pub fn initInterface(buffer: []u8) std.io.Reader {
944945 return .{
945 .context = r,
946 .context = undefined,
946947 .vtable = &.{
947 .read = Reader.stream,
948 .stream = Reader.stream,
948949 .discard = Reader.discard,
949950 },
951 .buffer = buffer,
952 .seek = 0,
953 .end = 0,
950954 };
951955 }
952956
953 pub fn readable(r: *Reader, buffer: []u8) std.io.BufferedReader {
954 return interface(r).buffered(buffer);
957 pub fn init(file: File, buffer: []u8) Reader {
958 return .{
959 .file = file,
960 .interface = initInterface(buffer),
961 };
955962 }
956963
957964 pub fn getSize(r: *Reader) GetEndPosError!u64 {
......@@ -1021,11 +1028,11 @@ pub const Reader = struct {
10211028 const max_buffers_len = 16;
10221029
10231030 fn stream(
1024 context: ?*anyopaque,
1031 io_reader: *std.io.Reader,
10251032 bw: *BufferedWriter,
10261033 limit: std.io.Limit,
10271034 ) std.io.Reader.StreamError!usize {
1028 const r: *Reader = @ptrCast(@alignCast(context));
1035 const r: *Reader = @fieldParentPtr("interface", io_reader);
10291036 switch (r.mode) {
10301037 .positional, .streaming => return bw.writeFile(r, limit, &.{}, 0) catch |write_err| switch (write_err) {
10311038 error.ReadFailed => return error.ReadFailed,
......@@ -1051,8 +1058,8 @@ pub const Reader = struct {
10511058 }
10521059 }
10531060
1054 fn discard(context: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize {
1055 const r: *Reader = @ptrCast(@alignCast(context));
1061 fn discard(io_reader: *std.io.Reader, limit: std.io.Limit) std.io.Reader.Error!usize {
1062 const r: *Reader = @fieldParentPtr("interface", io_reader);
10561063 const file = r.file;
10571064 const pos = r.pos;
10581065 switch (r.mode) {
......@@ -1357,8 +1364,8 @@ pub const Writer = struct {
13571364///
13581365/// Positional is more threadsafe, since the global seek position is not
13591366/// affected.
1360pub fn reader(file: File) Reader {
1361 return .{ .file = file };
1367pub fn reader(file: File, buffer: []u8) Reader {
1368 return .init(file, buffer);
13621369}
13631370
13641371/// Positional is more threadsafe, since the global seek position is not
lib/std/http.zig+2-2
......@@ -325,7 +325,7 @@ pub const Header = struct {
325325};
326326
327327pub const Reader = struct {
328 in: *std.io.BufferedReader,
328 in: *std.io.Reader,
329329 /// Keeps track of whether the stream is ready to accept a new request,
330330 /// making invalid API usage cause assertion failures rather than HTTP
331331 /// protocol violations.
......@@ -703,7 +703,7 @@ pub const Reader = struct {
703703
704704pub const Decompressor = struct {
705705 compression: Compression,
706 buffered_reader: std.io.BufferedReader,
706 buffered_reader: std.io.Reader,
707707
708708 pub const Compression = union(enum) {
709709 deflate: std.compress.flate.Decompressor,
lib/std/http/Client.zig+2-2
......@@ -232,7 +232,7 @@ pub const Connection = struct {
232232 writer: std.io.BufferedWriter,
233233 /// HTTP protocol from server to client.
234234 /// This either comes directly from `stream_reader`, or from a TLS client.
235 reader: std.io.BufferedReader,
235 reader: std.io.Reader,
236236 /// Entry in `ConnectionPool.used` or `ConnectionPool.free`.
237237 pool_node: std.DoublyLinkedList.Node,
238238 port: u16,
......@@ -299,7 +299,7 @@ pub const Connection = struct {
299299 /// Data from `client` to `Connection.stream`.
300300 writer: std.io.BufferedWriter,
301301 /// Data from `Connection.stream` to `client`.
302 reader: std.io.BufferedReader,
302 reader: std.io.Reader,
303303 client: std.crypto.tls.Client,
304304 connection: Connection,
305305
lib/std/http/Server.zig+2-2
......@@ -20,7 +20,7 @@ reader: http.Reader,
2020/// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`.
2121///
2222/// The returned `Server` is ready for `receiveHead` to be called.
23pub fn init(in: *std.io.BufferedReader, out: *std.io.BufferedWriter) Server {
23pub fn init(in: *std.io.Reader, out: *std.io.BufferedWriter) Server {
2424 return .{
2525 .reader = .{
2626 .in = in,
......@@ -610,7 +610,7 @@ pub const Request = struct {
610610/// See https://tools.ietf.org/html/rfc6455
611611pub const WebSocket = struct {
612612 key: []const u8,
613 input: *std.io.BufferedReader,
613 input: *std.io.Reader,
614614 output: *std.io.BufferedWriter,
615615
616616 pub const Header0 = packed struct(u8) {
lib/std/io.zig+11-15
......@@ -72,8 +72,6 @@ pub const Limit = enum(usize) {
7272pub const Reader = @import("io/Reader.zig");
7373pub const Writer = @import("io/Writer.zig");
7474
75pub const BufferedReader = @import("io/BufferedReader.zig");
76pub const BufferedWriter = @import("io/BufferedWriter.zig");
7775pub const AllocatingWriter = @import("io/AllocatingWriter.zig");
7876
7977pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;
......@@ -131,7 +129,7 @@ pub fn Poller(comptime StreamEnum: type) type {
131129 const PollFd = if (is_windows) void else posix.pollfd;
132130
133131 gpa: Allocator,
134 readers: [enum_fields.len]BufferedReader,
132 readers: [enum_fields.len]Reader,
135133 poll_fds: [enum_fields.len]PollFd,
136134 windows: if (is_windows) struct {
137135 first_read_done: bool,
......@@ -163,7 +161,7 @@ pub fn Poller(comptime StreamEnum: type) type {
163161 _ = windows.kernel32.CancelIo(h);
164162 }
165163 }
166 inline for (&self.readers) |*br| gpa.free(br.buffer);
164 inline for (&self.readers) |*r| gpa.free(r.buffer);
167165 self.* = undefined;
168166 }
169167
......@@ -183,7 +181,7 @@ pub fn Poller(comptime StreamEnum: type) type {
183181 }
184182 }
185183
186 pub inline fn reader(self: *Self, comptime which: StreamEnum) *BufferedReader {
184 pub inline fn reader(self: *Self, comptime which: StreamEnum) *Reader {
187185 return &self.readers[@intFromEnum(which)];
188186 }
189187
......@@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type {
295293 }
296294
297295 var keep_polling = false;
298 inline for (&self.poll_fds, &self.readers) |*poll_fd, *br| {
296 inline for (&self.poll_fds, &self.readers) |*poll_fd, *r| {
299297 // Try reading whatever is available before checking the error
300298 // conditions.
301299 // It's still possible to read after a POLL.HUP is received,
302300 // always check if there's some data waiting to be read first.
303301 if (poll_fd.revents & posix.POLL.IN != 0) {
304 const buf = try br.writableSliceGreedyAlloc(gpa, bump_amt);
302 const buf = try r.writableSliceGreedyAlloc(gpa, bump_amt);
305303 const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) {
306304 error.BrokenPipe => 0, // Handle the same as EOF.
307305 else => |e| return e,
308306 };
309 br.advanceBufferEnd(amt);
307 r.advanceBufferEnd(amt);
310308 if (amt == 0) {
311309 // Remove the fd when the EOF condition is met.
312310 poll_fd.fd = -1;
......@@ -337,14 +335,14 @@ var win_dummy_bytes_read: u32 = undefined;
337335fn windowsAsyncReadToFifoAndQueueSmallRead(
338336 handle: windows.HANDLE,
339337 overlapped: *windows.OVERLAPPED,
340 br: *BufferedReader,
338 r: *Reader,
341339 small_buf: *[128]u8,
342340 bump_amt: usize,
343341) !enum { empty, populated, closed_populated, closed } {
344342 var read_any_data = false;
345343 while (true) {
346344 const fifo_read_pending = while (true) {
347 const buf = try br.writableWithSize(bump_amt);
345 const buf = try r.writableWithSize(bump_amt);
348346 const buf_len = math.cast(u32, buf.len) orelse math.maxInt(u32);
349347
350348 if (0 == windows.kernel32.ReadFile(
......@@ -366,7 +364,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
366364 };
367365
368366 read_any_data = true;
369 br.update(num_bytes_read);
367 r.update(num_bytes_read);
370368
371369 if (num_bytes_read == buf_len) {
372370 // We filled the buffer, so there's probably more data available.
......@@ -396,7 +394,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
396394 .aborted => break :cancel_read,
397395 };
398396 read_any_data = true;
399 br.update(num_bytes_read);
397 r.update(num_bytes_read);
400398 }
401399
402400 // Try to queue the 1-byte read.
......@@ -421,7 +419,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
421419 .closed => return if (read_any_data) .closed_populated else .closed,
422420 .aborted => unreachable,
423421 };
424 try br.write(small_buf[0..num_bytes_read]);
422 try r.write(small_buf[0..num_bytes_read]);
425423 read_any_data = true;
426424 }
427425}
......@@ -488,8 +486,6 @@ pub fn PollFiles(comptime StreamEnum: type) type {
488486
489487test {
490488 _ = AllocatingWriter;
491 _ = BufferedReader;
492 _ = BufferedWriter;
493489 _ = Reader;
494490 _ = Writer;
495491 _ = @import("io/test.zig");
lib/std/io/AllocatingWriter.zig+1-1
......@@ -6,7 +6,7 @@
66//! `std.io.BufferedWriter` state such that it writes to the unused capacity of
77//! an array list, filling it up completely before making a call through the
88//! vtable, causing a resize. Consequently, the same, optimized, non-generic
9//! machine code that uses `std.io.BufferedReader`, such as formatted printing,
9//! machine code that uses `std.io.Reader`, such as formatted printing,
1010//! takes the hot paths when using this API.
1111
1212const std = @import("../std.zig");
lib/std/io/BufferedReader.zig deleted-1230
......@@ -1,1230 +0,0 @@
1const builtin = @import("builtin");
2const native_endian = builtin.target.cpu.arch.endian();
3
4const std = @import("../std.zig");
5const assert = std.debug.assert;
6const testing = std.testing;
7const BufferedWriter = std.io.BufferedWriter;
8const Reader = std.io.Reader;
9const Writer = std.io.Writer;
10const Allocator = std.mem.Allocator;
11const ArrayList = std.ArrayListUnmanaged;
12const Limit = std.io.Limit;
13
14const BufferedReader = @This();
15
16unbuffered_reader: Reader,
17buffer: []u8,
18/// In `buffer` before this are buffered bytes, after this is `undefined`.
19end: usize,
20/// Number of bytes which have been consumed from `buffer`.
21seek: usize,
22
23/// Constructs `br` such that it will read from `buffer` and then end.
24///
25/// Most methods do not require mutating `buffer`. Those that do are marked,
26/// and if they are avoided then `buffer` can be safely used with `@constCast`.
27pub fn initFixed(br: *BufferedReader, buffer: []u8) void {
28 br.* = .{
29 .unbuffered_reader = .ending,
30 .buffer = buffer,
31 .end = buffer.len,
32 .seek = 0,
33 };
34}
35
36pub fn bufferContents(br: *BufferedReader) []u8 {
37 return br.buffer[br.seek..br.end];
38}
39
40pub fn bufferedLen(br: *const BufferedReader) usize {
41 return br.end - br.seek;
42}
43
44/// Although `BufferedReader` can easily satisfy the `Reader` interface, it's
45/// generally more practical to pass a `BufferedReader` instance itself around,
46/// since it will result in fewer calls across vtable boundaries.
47pub fn reader(br: *BufferedReader) Reader {
48 return .{
49 .context = br,
50 .vtable = &.{
51 .read = passthruRead,
52 .readVec = passthruReadVec,
53 .discard = passthruDiscard,
54 },
55 };
56}
57
58pub fn hashed(br: *BufferedReader, hasher: anytype) Reader.Hashed(@TypeOf(hasher)) {
59 return .{ .in = br, .hasher = hasher };
60}
61
62/// Equivalent semantics to `std.io.Reader.VTable.readVec`.
63pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize {
64 return readVecLimit(br, data, .unlimited);
65}
66
67/// Equivalent semantics to `std.io.Reader.VTable.read`.
68pub fn read(br: *BufferedReader, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {
69 return passthruRead(br, bw, limit);
70}
71
72/// Equivalent semantics to `std.io.Reader.VTable.discard`.
73pub fn discard(br: *BufferedReader, limit: Limit) Reader.Error!usize {
74 return passthruDiscard(br, limit);
75}
76
77pub fn readVecAll(br: *BufferedReader, data: [][]u8) Reader.Error!void {
78 var index: usize = 0;
79 var truncate: usize = 0;
80 while (index < data.len) {
81 {
82 const untruncated = data[index];
83 data[index] = untruncated[truncate..];
84 defer data[index] = untruncated;
85 truncate += try br.readVec(data[index..]);
86 }
87 while (index < data.len and truncate >= data[index].len) {
88 truncate -= data[index].len;
89 index += 1;
90 }
91 }
92}
93
94/// "Pump" data from the reader to the writer.
95pub fn readAll(br: *BufferedReader, bw: *BufferedWriter, limit: Limit) Reader.StreamError!void {
96 var remaining = limit;
97 while (remaining.nonzero()) {
98 const n = try br.read(bw, remaining);
99 remaining = remaining.subtract(n).?;
100 }
101}
102
103/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
104/// a success case.
105///
106/// Returns total number of bytes written to `bw`.
107pub fn readRemaining(br: *BufferedReader, bw: *BufferedWriter) Reader.StreamRemainingError!usize {
108 var offset: usize = 0;
109 while (true) {
110 offset += br.read(bw, .unlimited) catch |err| switch (err) {
111 error.EndOfStream => return offset,
112 else => |e| return e,
113 };
114 }
115}
116
117/// Equivalent to `readVec` but reads at most `limit` bytes.
118pub fn readVecLimit(br: *BufferedReader, data: []const []u8, limit: Limit) Reader.Error!usize {
119 assert(@intFromEnum(Limit.unlimited) == std.math.maxInt(usize));
120 var remaining = @intFromEnum(limit);
121 for (data, 0..) |buf, i| {
122 const buffered = br.buffer[br.seek..br.end];
123 const copy_len = @min(buffered.len, buf.len, remaining);
124 @memcpy(buf[0..copy_len], buffered[0..copy_len]);
125 br.seek += copy_len;
126 remaining -= copy_len;
127 if (remaining == 0) break;
128 if (buf.len - copy_len == 0) continue;
129
130 br.seek = 0;
131 br.end = 0;
132 var vecs: [8][]u8 = undefined; // Arbitrarily chosen value.
133 const available_remaining_buf = buf[copy_len..];
134 vecs[0] = available_remaining_buf[0..@min(available_remaining_buf.len, remaining)];
135 const vec_start_remaining = remaining;
136 remaining -= vecs[0].len;
137 var vecs_i: usize = 1;
138 var data_i: usize = i + 1;
139 while (true) {
140 if (vecs.len - vecs_i == 0) {
141 const n = try br.unbuffered_reader.readVec(&vecs);
142 return @intFromEnum(limit) - vec_start_remaining + n;
143 }
144 if (remaining == 0 or data.len - data_i == 0) {
145 vecs[vecs_i] = br.buffer;
146 vecs_i += 1;
147 const n = try br.unbuffered_reader.readVec(vecs[0..vecs_i]);
148 const cutoff = vec_start_remaining - remaining;
149 if (n > cutoff) {
150 br.end = n - cutoff;
151 return @intFromEnum(limit) - remaining;
152 } else {
153 return @intFromEnum(limit) - vec_start_remaining + n;
154 }
155 }
156 if (data[data_i].len == 0) {
157 data_i += 1;
158 continue;
159 }
160 const data_elem = data[data_i];
161 vecs[vecs_i] = data_elem[0..@min(data_elem.len, remaining)];
162 remaining -= vecs[vecs_i].len;
163 vecs_i += 1;
164 data_i += 1;
165 }
166 }
167 return @intFromEnum(limit) - remaining;
168}
169
170fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {
171 const br: *BufferedReader = @alignCast(@ptrCast(context));
172 const buffer = limit.slice(br.buffer[br.seek..br.end]);
173 if (buffer.len > 0) {
174 const n = try bw.write(buffer);
175 br.seek += n;
176 return n;
177 }
178 return br.unbuffered_reader.read(bw, limit);
179}
180
181fn passthruDiscard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
182 const br: *BufferedReader = @alignCast(@ptrCast(context));
183 const buffered_len = br.end - br.seek;
184 const remaining: Limit = if (limit.toInt()) |n| l: {
185 if (buffered_len >= n) {
186 br.seek += n;
187 return n;
188 }
189 break :l .limited(n - buffered_len);
190 } else .unlimited;
191 br.seek = 0;
192 br.end = 0;
193 const n = if (br.unbuffered_reader.discard) |f| try f(remaining) else try br.defaultDiscard(remaining);
194 return buffered_len + n;
195}
196
197fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize {
198 const br: *BufferedReader = @alignCast(@ptrCast(context));
199 return readVecLimit(br, data, .unlimited);
200}
201
202fn defaultDiscard(br: *BufferedReader, limit: Limit) Reader.Error!usize {
203 assert(br.seek == 0);
204 assert(br.end == 0);
205 var bw: BufferedWriter = .{
206 .unbuffered_writer = .discarding,
207 .buffer = br.buffer,
208 };
209 const n = br.read(&bw, limit) catch |err| switch (err) {
210 error.WriteFailed => unreachable,
211 error.ReadFailed => return error.ReadFailed,
212 error.EndOfStream => return error.EndOfStream,
213 };
214 if (n > @intFromEnum(limit)) {
215 const over_amt = n - @intFromEnum(limit);
216 assert(over_amt <= bw.buffer.end); // limit may be exceeded only by an amount within buffer capacity.
217 br.seek = bw.end - over_amt;
218 br.end = bw.end;
219 return @intFromEnum(limit);
220 }
221 return n;
222}
223
224/// Returns the next `len` bytes from `unbuffered_reader`, filling the buffer as
225/// necessary.
226///
227/// Invalidates previously returned values from `peek`.
228///
229/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
230/// least as big as `len`.
231///
232/// If there are fewer than `len` bytes left in the stream, `error.EndOfStream`
233/// is returned instead.
234///
235/// See also:
236/// * `peek`
237/// * `toss`
238pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {
239 try br.fill(n);
240 return br.buffer[br.seek..][0..n];
241}
242
243/// Returns all the next buffered bytes from `unbuffered_reader`, after filling
244/// the buffer to ensure it contains at least `n` bytes.
245///
246/// Invalidates previously returned values from `peek` and `peekGreedy`.
247///
248/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
249/// least as big as `n`.
250///
251/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
252/// is returned instead.
253///
254/// See also:
255/// * `peek`
256/// * `toss`
257pub fn peekGreedy(br: *BufferedReader, n: usize) Reader.Error![]u8 {
258 try br.fill(n);
259 return br.buffer[br.seek..br.end];
260}
261
262/// Skips the next `n` bytes from the stream, advancing the seek position. This
263/// is typically and safely used after `peek`.
264///
265/// Asserts that the number of bytes buffered is at least as many as `n`.
266///
267/// The "tossed" memory remains alive until a "peek" operation occurs.
268///
269/// See also:
270/// * `peek`.
271/// * `discard`.
272pub fn toss(br: *BufferedReader, n: usize) void {
273 br.seek += n;
274 assert(br.seek <= br.end);
275}
276
277/// Equivalent to `toss(br.bufferedLen())`.
278pub fn tossAll(br: *BufferedReader) void {
279 br.seek = 0;
280 br.end = 0;
281}
282
283/// Equivalent to `peek` followed by `toss`.
284///
285/// The data returned is invalidated by the next call to `take`, `peek`,
286/// `fill`, and functions with those prefixes.
287pub fn take(br: *BufferedReader, n: usize) Reader.Error![]u8 {
288 const result = try br.peek(n);
289 br.toss(n);
290 return result;
291}
292
293/// Returns the next `n` bytes from `unbuffered_reader` as an array, filling
294/// the buffer as necessary and advancing the seek position `n` bytes.
295///
296/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
297/// least as big as `n`.
298///
299/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
300/// is returned instead.
301///
302/// See also:
303/// * `take`
304pub fn takeArray(br: *BufferedReader, comptime n: usize) Reader.Error!*[n]u8 {
305 return (try br.take(n))[0..n];
306}
307
308/// Returns the next `n` bytes from `unbuffered_reader` as an array, filling
309/// the buffer as necessary, without advancing the seek position.
310///
311/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
312/// least as big as `n`.
313///
314/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
315/// is returned instead.
316///
317/// See also:
318/// * `peek`
319/// * `takeArray`
320pub fn peekArray(br: *BufferedReader, comptime n: usize) Reader.Error!*[n]u8 {
321 return (try br.peek(n))[0..n];
322}
323
324/// Skips the next `n` bytes from the stream, advancing the seek position.
325///
326/// Unlike `toss` which is infallible, in this function `n` can be any amount.
327///
328/// Returns `error.EndOfStream` if fewer than `n` bytes could be discarded.
329///
330/// See also:
331/// * `toss`
332/// * `discardRemaining`
333/// * `discardShort`
334/// * `discard`
335pub fn discardAll(br: *BufferedReader, n: usize) Reader.Error!void {
336 if ((try br.discardShort(n)) != n) return error.EndOfStream;
337}
338
339pub fn discardAll64(br: *BufferedReader, n: u64) Reader.Error!void {
340 var remaining: u64 = n;
341 while (remaining > 0) {
342 const limited = std.math.cast(usize, remaining) orelse std.math.maxInt(usize);
343 try discardAll(br, limited);
344 remaining -= limited;
345 }
346}
347
348/// Skips the next `n` bytes from the stream, advancing the seek position.
349///
350/// Unlike `toss` which is infallible, in this function `n` can be any amount.
351///
352/// Returns the number of bytes discarded, which is less than `n` if and only
353/// if the stream reached the end.
354///
355/// See also:
356/// * `discardAll`
357/// * `discardRemaining`
358/// * `discard`
359pub fn discardShort(br: *BufferedReader, n: usize) Reader.ShortError!usize {
360 const proposed_seek = br.seek + n;
361 if (proposed_seek <= br.end) {
362 @branchHint(.likely);
363 br.seek = proposed_seek;
364 return n;
365 }
366 var remaining = n - (br.end - br.seek);
367 br.end = 0;
368 br.seek = 0;
369 while (true) {
370 const discard_len = br.unbuffered_reader.discard(.limited(remaining)) catch |err| switch (err) {
371 error.EndOfStream => return n - remaining,
372 error.ReadFailed => return error.ReadFailed,
373 };
374 remaining -= discard_len;
375 if (remaining == 0) return n;
376 }
377}
378
379/// Reads the stream until the end, ignoring all the data.
380/// Returns the number of bytes discarded.
381pub fn discardRemaining(br: *BufferedReader) Reader.ShortError!usize {
382 const buffered_len = br.end;
383 br.end = 0;
384 return buffered_len + try br.unbuffered_reader.discardRemaining();
385}
386
387/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
388/// the seek position.
389///
390/// Invalidates previously returned values from `peek`.
391///
392/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
393/// returned instead.
394///
395/// See also:
396/// * `peek`
397/// * `readSliceShort`
398pub fn readSlice(br: *BufferedReader, buffer: []u8) Reader.Error!void {
399 const n = try readSliceShort(br, buffer);
400 if (n != buffer.len) return error.EndOfStream;
401}
402
403/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
404/// the seek position.
405///
406/// Invalidates previously returned values from `peek`.
407///
408/// Returns the number of bytes read, which is less than `buffer.len` if and
409/// only if the stream reached the end.
410///
411/// See also:
412/// * `readSlice`
413pub fn readSliceShort(br: *BufferedReader, buffer: []u8) Reader.ShortError!usize {
414 const in_buffer = br.buffer[br.seek..br.end];
415 const copy_len = @min(buffer.len, in_buffer.len);
416 @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]);
417 if (buffer.len - copy_len == 0) {
418 br.seek += copy_len;
419 return buffer.len;
420 }
421 var i: usize = copy_len;
422 br.end = 0;
423 br.seek = 0;
424 while (true) {
425 const remaining = buffer[i..];
426 const n = br.unbuffered_reader.readVec(&.{ remaining, br.buffer }) catch |err| switch (err) {
427 error.EndOfStream => return i,
428 error.ReadFailed => return error.ReadFailed,
429 };
430 if (n < remaining.len) {
431 i += n;
432 continue;
433 }
434 br.end = n - remaining.len;
435 return buffer.len;
436 }
437}
438
439/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
440/// the seek position.
441///
442/// Invalidates previously returned values from `peek`.
443///
444/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
445/// returned instead.
446///
447/// The function is inline to avoid the dead code in case `endian` is
448/// comptime-known and matches host endianness.
449///
450/// See also:
451/// * `readSlice`
452/// * `readSliceEndianAlloc`
453pub inline fn readSliceEndian(
454 br: *BufferedReader,
455 comptime Elem: type,
456 buffer: []Elem,
457 endian: std.builtin.Endian,
458) Reader.Error!void {
459 try readSlice(br, @ptrCast(buffer));
460 if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem);
461}
462
463pub const ReadAllocError = Reader.Error || Allocator.Error;
464
465/// The function is inline to avoid the dead code in case `endian` is
466/// comptime-known and matches host endianness.
467pub inline fn readSliceEndianAlloc(
468 br: *BufferedReader,
469 allocator: Allocator,
470 comptime Elem: type,
471 len: usize,
472 endian: std.builtin.Endian,
473) ReadAllocError![]Elem {
474 const dest = try allocator.alloc(Elem, len);
475 errdefer allocator.free(dest);
476 try readSlice(br, @ptrCast(dest));
477 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
478 return dest;
479}
480
481pub fn readSliceAlloc(br: *BufferedReader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
482 const dest = try allocator.alloc(u8, len);
483 errdefer allocator.free(dest);
484 try readSlice(br, dest);
485 return dest;
486}
487
488/// Transfers all bytes from the current position to the end of the stream, up
489/// to `limit`, returning them as a caller-owned allocated slice.
490///
491/// If `limit` is exceeded, returns `error.StreamTooLong`. In such case, the
492/// stream is advanced an unspecified amount, and the consumed data is
493/// unrecoverable. The other function listed below does not have this caveat.
494///
495/// Asserts `br` was initialized with at least one byte of storage capacity.
496///
497/// See also:
498/// * `readRemainingArrayList`
499pub fn readRemainingAlloc(r: Reader, gpa: Allocator, limit: Limit) Reader.LimitedAllocError![]u8 {
500 var buffer: ArrayList(u8) = .empty;
501 defer buffer.deinit(gpa);
502 try readRemainingArrayList(r, gpa, null, &buffer, limit);
503 return buffer.toOwnedSlice(gpa);
504}
505
506/// Transfers all bytes from the current position to the end of the stream, up
507/// to `limit`, appending them to `list`.
508///
509/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
510/// such case, the stream is in a well-defined state. The next byte that would
511/// be read will be the first one to exceed `limit`, and all preceeding bytes
512/// have been appended to `list`.
513///
514/// Asserts `br` was initialized with at least one byte of storage capacity.
515///
516/// See also:
517/// * `readRemainingAlloc`
518pub fn readRemainingArrayList(
519 br: *BufferedReader,
520 gpa: Allocator,
521 comptime alignment: ?std.mem.Alignment,
522 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
523 limit: Limit,
524) Reader.LimitedAllocError!void {
525 const buffer = br.buffer;
526 const buffered = buffer[br.seek..br.end];
527 const copy_len = limit.minInt(buffered.len);
528 try list.ensureUnusedCapacity(gpa, copy_len);
529 @memcpy(list.unusedCapacitySlice()[0..copy_len], buffer[0..copy_len]);
530 list.items.len += copy_len;
531 br.seek += copy_len;
532 if (copy_len == buffered.len) {
533 br.seek = 0;
534 br.end = 0;
535 }
536 var remaining = limit.subtract(copy_len).?;
537 while (true) {
538 try list.ensureUnusedCapacity(gpa, 1);
539 const dest = remaining.slice(list.unusedCapacitySlice());
540 const additional_buffer = if (@intFromEnum(remaining) == dest.len) buffer else &.{};
541 const n = br.unbuffered_reader.readVec(&.{ dest, additional_buffer }) catch |err| switch (err) {
542 error.EndOfStream => break,
543 error.ReadFailed => return error.ReadFailed,
544 };
545 if (n >= dest.len) {
546 br.end = n - dest.len;
547 list.items.len += dest.len;
548 if (n == dest.len) return;
549 return error.StreamTooLong;
550 }
551 list.items.len += n;
552 remaining = remaining.subtract(n).?;
553 }
554}
555
556pub const DelimiterError = error{
557 /// See the `Reader` implementation for detailed diagnostics.
558 ReadFailed,
559 /// For "inclusive" functions, stream ended before the delimiter was found.
560 /// For "exclusive" functions, stream ended and there are no more bytes to
561 /// return.
562 EndOfStream,
563 /// The delimiter was not found within a number of bytes matching the
564 /// capacity of the `BufferedReader`.
565 StreamTooLong,
566};
567
568/// Returns a slice of the next bytes of buffered data from the stream until
569/// `sentinel` is found, advancing the seek position.
570///
571/// Returned slice has a sentinel.
572///
573/// Invalidates previously returned values from `peek`.
574///
575/// See also:
576/// * `peekSentinel`
577/// * `takeDelimiterExclusive`
578/// * `takeDelimiterInclusive`
579pub fn takeSentinel(br: *BufferedReader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
580 const result = try br.peekSentinel(sentinel);
581 br.toss(result.len + 1);
582 return result;
583}
584
585pub fn peekSentinel(br: *BufferedReader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
586 const result = try br.peekDelimiterInclusive(sentinel);
587 return result[0 .. result.len - 1 :sentinel];
588}
589
590/// Returns a slice of the next bytes of buffered data from the stream until
591/// `delimiter` is found, advancing the seek position.
592///
593/// Returned slice includes the delimiter as the last byte.
594///
595/// Invalidates previously returned values from `peek`.
596///
597/// See also:
598/// * `takeSentinel`
599/// * `takeDelimiterExclusive`
600/// * `peekDelimiterInclusive`
601pub fn takeDelimiterInclusive(br: *BufferedReader, delimiter: u8) DelimiterError![]u8 {
602 const result = try br.peekDelimiterInclusive(delimiter);
603 br.toss(result.len);
604 return result;
605}
606
607/// Returns a slice of the next bytes of buffered data from the stream until
608/// `delimiter` is found, without advancing the seek position.
609///
610/// Returned slice includes the delimiter as the last byte.
611///
612/// Invalidates previously returned values from `peek`.
613///
614/// See also:
615/// * `peekSentinel`
616/// * `peekDelimiterExclusive`
617/// * `takeDelimiterInclusive`
618pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) DelimiterError![]u8 {
619 const buffer = br.buffer[0..br.end];
620 const seek = br.seek;
621 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {
622 @branchHint(.likely);
623 return buffer[seek .. end + 1];
624 }
625 if (seek > 0) {
626 const remainder = buffer[seek..];
627 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
628 br.end = remainder.len;
629 br.seek = 0;
630 }
631 while (br.end < br.buffer.len) {
632 const n = try br.unbuffered_reader.readVec(&.{br.buffer[br.end..]});
633 const prev_end = br.end;
634 br.end = prev_end + n;
635 if (std.mem.indexOfScalarPos(u8, br.buffer[0..br.end], prev_end, delimiter)) |end| {
636 return br.buffer[0 .. end + 1];
637 }
638 }
639 return error.StreamTooLong;
640}
641
642/// Returns a slice of the next bytes of buffered data from the stream until
643/// `delimiter` is found, advancing the seek position.
644///
645/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
646/// to a delimiter, unless it would result in a length 0 return value, in which
647/// case `error.EndOfStream` is returned instead.
648///
649/// If the delimiter is not found within a number of bytes matching the
650/// capacity of this `BufferedReader`, `error.StreamTooLong` is returned. In
651/// such case, the stream state is unmodified as if this function was never
652/// called.
653///
654/// Invalidates previously returned values from `peek`.
655///
656/// See also:
657/// * `takeDelimiterInclusive`
658/// * `peekDelimiterExclusive`
659pub fn takeDelimiterExclusive(br: *BufferedReader, delimiter: u8) DelimiterError![]u8 {
660 const result = br.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
661 error.EndOfStream => {
662 if (br.end == 0) return error.EndOfStream;
663 br.toss(br.end);
664 return br.buffer[0..br.end];
665 },
666 else => |e| return e,
667 };
668 br.toss(result.len);
669 return result[0 .. result.len - 1];
670}
671
672/// Returns a slice of the next bytes of buffered data from the stream until
673/// `delimiter` is found, without advancing the seek position.
674///
675/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
676/// to a delimiter, unless it would result in a length 0 return value, in which
677/// case `error.EndOfStream` is returned instead.
678///
679/// If the delimiter is not found within a number of bytes matching the
680/// capacity of this `BufferedReader`, `error.StreamTooLong` is returned. In
681/// such case, the stream state is unmodified as if this function was never
682/// called.
683///
684/// Invalidates previously returned values from `peek`.
685///
686/// See also:
687/// * `peekDelimiterInclusive`
688/// * `takeDelimiterExclusive`
689pub fn peekDelimiterExclusive(br: *BufferedReader, delimiter: u8) DelimiterError![]u8 {
690 const result = br.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
691 error.EndOfStream => {
692 if (br.end == 0) return error.EndOfStream;
693 return br.buffer[0..br.end];
694 },
695 else => |e| return e,
696 };
697 return result[0 .. result.len - 1];
698}
699
700/// Appends to `bw` contents by reading from the stream until `delimiter` is
701/// found. Does not write the delimiter itself.
702///
703/// Returns number of bytes streamed.
704pub fn readDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.StreamError!usize {
705 const amount, const to = try br.readAny(bw, delimiter, .unlimited);
706 return switch (to) {
707 .delimiter => amount,
708 .limit => unreachable,
709 .end => error.EndOfStream,
710 };
711}
712
713/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
714/// Does not write the delimiter itself.
715///
716/// Succeeds if stream ends before delimiter found.
717///
718/// Returns number of bytes streamed. The end is not signaled to the writer.
719pub fn readDelimiterEnding(
720 br: *BufferedReader,
721 bw: *BufferedWriter,
722 delimiter: u8,
723) Reader.StreamRemainingError!usize {
724 const amount, const to = try br.readAny(bw, delimiter, .unlimited);
725 return switch (to) {
726 .delimiter, .end => amount,
727 .limit => unreachable,
728 };
729}
730
731pub const StreamDelimiterLimitedError = Reader.StreamRemainingError || error{
732 /// Stream ended before the delimiter was found.
733 EndOfStream,
734 /// The delimiter was not found within the limit.
735 StreamTooLong,
736};
737
738/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
739/// Does not write the delimiter itself.
740///
741/// Returns number of bytes streamed.
742pub fn readDelimiterLimit(
743 br: *BufferedReader,
744 bw: *BufferedWriter,
745 delimiter: u8,
746 limit: Limit,
747) StreamDelimiterLimitedError!usize {
748 const amount, const to = try br.readAny(bw, delimiter, limit);
749 return switch (to) {
750 .delimiter => amount,
751 .limit => error.StreamTooLong,
752 .end => error.EndOfStream,
753 };
754}
755
756fn readAny(
757 br: *BufferedReader,
758 bw: *BufferedWriter,
759 delimiter: ?u8,
760 limit: Limit,
761) Reader.StreamRemainingError!struct { usize, enum { delimiter, limit, end } } {
762 var amount: usize = 0;
763 var remaining = limit;
764 while (remaining.nonzero()) {
765 const available = remaining.slice(br.peekGreedy(1) catch |err| switch (err) {
766 error.ReadFailed => |e| return e,
767 error.EndOfStream => return .{ amount, .end },
768 });
769 if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| {
770 try bw.writeAll(available[0..delimiter_index]);
771 br.toss(delimiter_index + 1);
772 return .{ amount + delimiter_index, .delimiter };
773 };
774 try bw.writeAll(available);
775 br.toss(available.len);
776 amount += available.len;
777 remaining = remaining.subtract(available.len).?;
778 }
779 return .{ amount, .limit };
780}
781
782/// Reads from the stream until specified byte is found, discarding all data,
783/// including the delimiter.
784///
785/// If end of stream is found, this function succeeds.
786pub fn discardDelimiterInclusive(br: *BufferedReader, delimiter: u8) Reader.Error!void {
787 _ = br;
788 _ = delimiter;
789 @panic("TODO");
790}
791
792/// Reads from the stream until specified byte is found, discarding all data,
793/// excluding the delimiter.
794///
795/// Succeeds if stream ends before delimiter found.
796pub fn discardDelimiterExclusive(br: *BufferedReader, delimiter: u8) Reader.ShortError!void {
797 _ = br;
798 _ = delimiter;
799 @panic("TODO");
800}
801
802/// Fills the buffer such that it contains at least `n` bytes, without
803/// advancing the seek position.
804///
805/// Returns `error.EndOfStream` if and only if there are fewer than `n` bytes
806/// remaining.
807///
808/// Asserts buffer capacity is at least `n`.
809pub fn fill(br: *BufferedReader, n: usize) Reader.Error!void {
810 assert(n <= br.buffer.len);
811 if (br.seek + n <= br.end) {
812 @branchHint(.likely);
813 return;
814 }
815 rebaseCapacity(br, n);
816 while (br.end < br.seek + n) {
817 br.end += try br.unbuffered_reader.readVec(&.{br.buffer[br.end..]});
818 }
819}
820
821/// Without advancing the seek position, does exactly one underlying read, filling the buffer as
822/// much as possible. This may result in zero bytes added to the buffer, which is not an end of
823/// stream condition. End of stream is communicated via returning `error.EndOfStream`.
824///
825/// Asserts buffer capacity is at least 1.
826pub fn fillMore(br: *BufferedReader) Reader.Error!void {
827 rebaseCapacity(br, 1);
828 br.end += try br.unbuffered_reader.readVec(&.{br.buffer[br.end..]});
829}
830
831/// Returns the next byte from the stream or returns `error.EndOfStream`.
832///
833/// Does not advance the seek position.
834///
835/// Asserts the buffer capacity is nonzero.
836pub fn peekByte(br: *BufferedReader) Reader.Error!u8 {
837 const buffer = br.buffer[0..br.end];
838 const seek = br.seek;
839 if (seek >= buffer.len) {
840 @branchHint(.unlikely);
841 try fill(br, 1);
842 }
843 return buffer[seek];
844}
845
846/// Reads 1 byte from the stream or returns `error.EndOfStream`.
847///
848/// Asserts the buffer capacity is nonzero.
849pub fn takeByte(br: *BufferedReader) Reader.Error!u8 {
850 const result = try peekByte(br);
851 br.seek += 1;
852 return result;
853}
854
855/// Same as `takeByte` except the returned byte is signed.
856pub fn takeByteSigned(br: *BufferedReader) Reader.Error!i8 {
857 return @bitCast(try br.takeByte());
858}
859
860/// Asserts the buffer was initialized with a capacity at least `@bitSizeOf(T) / 8`.
861pub inline fn takeInt(br: *BufferedReader, comptime T: type, endian: std.builtin.Endian) Reader.Error!T {
862 const n = @divExact(@typeInfo(T).int.bits, 8);
863 return std.mem.readInt(T, try br.takeArray(n), endian);
864}
865
866/// Asserts the buffer was initialized with a capacity at least `n`.
867pub fn takeVarInt(br: *BufferedReader, comptime Int: type, endian: std.builtin.Endian, n: usize) Reader.Error!Int {
868 assert(n <= @sizeOf(Int));
869 return std.mem.readVarInt(Int, try br.take(n), endian);
870}
871
872/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
873///
874/// Advances the seek position.
875///
876/// See also:
877/// * `peekStruct`
878pub fn takeStruct(br: *BufferedReader, comptime T: type) Reader.Error!*align(1) T {
879 // Only extern and packed structs have defined in-memory layout.
880 comptime assert(@typeInfo(T).@"struct".layout != .auto);
881 return @ptrCast(try br.takeArray(@sizeOf(T)));
882}
883
884/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
885///
886/// Does not advance the seek position.
887///
888/// See also:
889/// * `takeStruct`
890pub fn peekStruct(br: *BufferedReader, comptime T: type) Reader.Error!*align(1) T {
891 // Only extern and packed structs have defined in-memory layout.
892 comptime assert(@typeInfo(T).@"struct".layout != .auto);
893 return @ptrCast(try br.peekArray(@sizeOf(T)));
894}
895
896/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
897///
898/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
899/// when `endian` is comptime-known and matches the host endianness.
900pub inline fn takeStructEndian(br: *BufferedReader, comptime T: type, endian: std.builtin.Endian) Reader.Error!T {
901 var res = (try br.takeStruct(T)).*;
902 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
903 return res;
904}
905
906/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
907///
908/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
909/// when `endian` is comptime-known and matches the host endianness.
910pub inline fn peekStructEndian(br: *BufferedReader, comptime T: type, endian: std.builtin.Endian) Reader.Error!T {
911 var res = (try br.peekStruct(T)).*;
912 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
913 return res;
914}
915
916pub const TakeEnumError = Reader.Error || error{InvalidEnumTag};
917
918/// Reads an integer with the same size as the given enum's tag type. If the
919/// integer matches an enum tag, casts the integer to the enum tag and returns
920/// it. Otherwise, returns `error.InvalidEnumTag`.
921///
922/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
923pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) TakeEnumError!Enum {
924 const Tag = @typeInfo(Enum).@"enum".tag_type;
925 const int = try br.takeInt(Tag, endian);
926 return std.meta.intToEnum(Enum, int);
927}
928
929/// Reads an integer with the same size as the given nonexhaustive enum's tag type.
930///
931/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
932pub fn takeEnumNonexhaustive(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) Reader.Error!Enum {
933 const info = @typeInfo(Enum).@"enum";
934 comptime assert(!info.is_exhaustive);
935 comptime assert(@bitSizeOf(info.tag_type) == @sizeOf(info.tag_type) * 8);
936 return takeEnum(br, Enum, endian) catch |err| switch (err) {
937 error.InvalidEnumTag => unreachable,
938 else => |e| return e,
939 };
940}
941
942pub const TakeLeb128Error = Reader.Error || error{Overflow};
943
944/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.
945pub fn takeLeb128(br: *BufferedReader, comptime Result: type) TakeLeb128Error!Result {
946 const result_info = @typeInfo(Result).int;
947 return std.math.cast(Result, try br.takeMultipleOf7Leb128(@Type(.{ .int = .{
948 .signedness = result_info.signedness,
949 .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),
950 } }))) orelse error.Overflow;
951}
952
953pub fn expandTotalCapacity(br: *BufferedReader, allocator: Allocator, n: usize) Allocator.Error!void {
954 if (n <= br.buffer.len) return;
955 if (br.seek > 0) rebase(br);
956 var list: ArrayList(u8) = .{
957 .items = br.buffer[0..br.end],
958 .capacity = br.buffer.len,
959 };
960 defer br.buffer = list.allocatedSlice();
961 try list.ensureTotalCapacity(allocator, n);
962}
963
964pub const FillAllocError = Reader.Error || Allocator.Error;
965
966pub fn fillAlloc(br: *BufferedReader, allocator: Allocator, n: usize) FillAllocError!void {
967 try expandTotalCapacity(br, allocator, n);
968 return fill(br, n);
969}
970
971/// Returns a slice into the unused capacity of `buffer` with at least
972/// `min_len` bytes, extending `buffer` by resizing it with `gpa` as necessary.
973///
974/// After calling this function, typically the caller will follow up with a
975/// call to `advanceBufferEnd` to report the actual number of bytes buffered.
976pub fn writableSliceGreedyAlloc(br: *BufferedReader, allocator: Allocator, min_len: usize) Allocator.Error![]u8 {
977 {
978 const unused = br.buffer[br.end..];
979 if (unused.len >= min_len) return unused;
980 }
981 if (br.seek > 0) rebase(br);
982 {
983 var list: ArrayList(u8) = .{
984 .items = br.buffer[0..br.end],
985 .capacity = br.buffer.len,
986 };
987 defer br.buffer = list.allocatedSlice();
988 try list.ensureUnusedCapacity(allocator, min_len);
989 }
990 const unused = br.buffer[br.end..];
991 assert(unused.len >= min_len);
992 return unused;
993}
994
995/// After writing directly into the unused capacity of `buffer`, this function
996/// updates `end` so that users of `BufferedReader` can receive the data.
997pub fn advanceBufferEnd(br: *BufferedReader, n: usize) void {
998 assert(n <= br.buffer.len - br.end);
999 br.end += n;
1000}
1001
1002fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) TakeLeb128Error!Result {
1003 const result_info = @typeInfo(Result).int;
1004 comptime assert(result_info.bits % 7 == 0);
1005 var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;
1006 const UnsignedResult = @Type(.{ .int = .{
1007 .signedness = .unsigned,
1008 .bits = result_info.bits,
1009 } });
1010 var result: UnsignedResult = 0;
1011 var fits = true;
1012 while (true) {
1013 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekGreedy(1));
1014 for (buffer, 1..) |byte, len| {
1015 if (remaining_bits > 0) {
1016 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) |
1017 if (result_info.bits > 7) @shrExact(result, 7) else 0;
1018 remaining_bits -= 7;
1019 } else if (fits) fits = switch (result_info.signedness) {
1020 .signed => @as(i7, @bitCast(byte.bits)) ==
1021 @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),
1022 .unsigned => byte.bits == 0,
1023 };
1024 if (byte.more) continue;
1025 br.toss(len);
1026 return if (fits) @as(Result, @bitCast(result)) >> remaining_bits else error.Overflow;
1027 }
1028 br.toss(buffer.len);
1029 }
1030}
1031
1032/// Left-aligns data such that `br.seek` becomes zero.
1033pub fn rebase(br: *BufferedReader) void {
1034 const data = br.buffer[br.seek..br.end];
1035 const dest = br.buffer[0..data.len];
1036 std.mem.copyForwards(u8, dest, data);
1037 br.seek = 0;
1038 br.end = data.len;
1039}
1040
1041/// Ensures `capacity` more data can be buffered without rebasing, by rebasing
1042/// if necessary.
1043///
1044/// Asserts `capacity` is within the buffer capacity.
1045pub fn rebaseCapacity(br: *BufferedReader, capacity: usize) void {
1046 if (br.end > br.buffer.len - capacity) rebase(br);
1047}
1048
1049/// Advances the stream and decreases the size of the storage buffer by `n`,
1050/// returning the range of bytes no longer accessible by `br`.
1051///
1052/// This action can be undone by `restitute`.
1053///
1054/// Asserts there are at least `n` buffered bytes already.
1055///
1056/// Asserts that `br.seek` is zero, i.e. the buffer is in a rebased state.
1057pub fn steal(br: *BufferedReader, n: usize) []u8 {
1058 assert(br.seek == 0);
1059 assert(n <= br.end);
1060 const stolen = br.buffer[0..n];
1061 br.buffer = br.buffer[n..];
1062 br.end -= n;
1063 return stolen;
1064}
1065
1066/// Expands the storage buffer, undoing the effects of `steal`
1067/// Assumes that `n` does not exceed the total number of stolen bytes.
1068pub fn restitute(br: *BufferedReader, n: usize) void {
1069 br.buffer = (br.buffer.ptr - n)[0 .. br.buffer.len + n];
1070 br.end += n;
1071 br.seek += n;
1072}
1073
1074test initFixed {
1075 var br: BufferedReader = undefined;
1076 br.initFixed("a\x02");
1077 try testing.expect((try br.takeByte()) == 'a');
1078 try testing.expect((try br.takeEnum(enum(u8) {
1079 a = 0,
1080 b = 99,
1081 c = 2,
1082 d = 3,
1083 }, builtin.cpu.arch.endian())) == .c);
1084 try testing.expectError(error.EndOfStream, br.takeByte());
1085}
1086
1087test peek {
1088 return error.Unimplemented;
1089}
1090
1091test peekGreedy {
1092 return error.Unimplemented;
1093}
1094
1095test toss {
1096 return error.Unimplemented;
1097}
1098
1099test take {
1100 return error.Unimplemented;
1101}
1102
1103test takeArray {
1104 return error.Unimplemented;
1105}
1106
1107test peekArray {
1108 return error.Unimplemented;
1109}
1110
1111test discardAll {
1112 var br: BufferedReader = undefined;
1113 br.initFixed("foobar");
1114 try br.discard(3);
1115 try testing.expectEqualStrings("bar", try br.take(3));
1116 try br.discard(0);
1117 try testing.expectError(error.EndOfStream, br.discard(1));
1118}
1119
1120test discardRemaining {
1121 return error.Unimplemented;
1122}
1123
1124test read {
1125 return error.Unimplemented;
1126}
1127
1128test takeSentinel {
1129 return error.Unimplemented;
1130}
1131
1132test peekSentinel {
1133 return error.Unimplemented;
1134}
1135
1136test takeDelimiterInclusive {
1137 return error.Unimplemented;
1138}
1139
1140test peekDelimiterInclusive {
1141 return error.Unimplemented;
1142}
1143
1144test takeDelimiterExclusive {
1145 return error.Unimplemented;
1146}
1147
1148test peekDelimiterExclusive {
1149 return error.Unimplemented;
1150}
1151
1152test readDelimiter {
1153 return error.Unimplemented;
1154}
1155
1156test readDelimiterEnding {
1157 return error.Unimplemented;
1158}
1159
1160test readDelimiterLimit {
1161 return error.Unimplemented;
1162}
1163
1164test discardDelimiterExclusive {
1165 return error.Unimplemented;
1166}
1167
1168test discardDelimiterInclusive {
1169 return error.Unimplemented;
1170}
1171
1172test fill {
1173 return error.Unimplemented;
1174}
1175
1176test takeByte {
1177 return error.Unimplemented;
1178}
1179
1180test takeByteSigned {
1181 return error.Unimplemented;
1182}
1183
1184test takeInt {
1185 return error.Unimplemented;
1186}
1187
1188test takeVarInt {
1189 return error.Unimplemented;
1190}
1191
1192test takeStruct {
1193 return error.Unimplemented;
1194}
1195
1196test peekStruct {
1197 return error.Unimplemented;
1198}
1199
1200test takeStructEndian {
1201 return error.Unimplemented;
1202}
1203
1204test peekStructEndian {
1205 return error.Unimplemented;
1206}
1207
1208test takeEnum {
1209 return error.Unimplemented;
1210}
1211
1212test takeLeb128 {
1213 return error.Unimplemented;
1214}
1215
1216test readSliceShort {
1217 return error.Unimplemented;
1218}
1219
1220test readVec {
1221 return error.Unimplemented;
1222}
1223
1224test "expected error.EndOfStream" {
1225 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1226 var br: std.io.BufferedReader = undefined;
1227 br.initFixed("");
1228 try std.testing.expectError(error.EndOfStream, br.readEnum(enum(u8) { a, b }, .little));
1229 try std.testing.expectError(error.EndOfStream, br.isBytes("foo"));
1230}
lib/std/io/Reader.zig+1206-110
......@@ -1,8 +1,12 @@
1const std = @import("../std.zig");
21const Reader = @This();
2
3const builtin = @import("builtin");
4const native_endian = builtin.target.cpu.arch.endian();
5
6const std = @import("../std.zig");
7const Writer = std.io.Writer;
38const assert = std.debug.assert;
4const BufferedWriter = std.io.BufferedWriter;
5const BufferedReader = std.io.BufferedReader;
9const testing = std.testing;
610const Allocator = std.mem.Allocator;
711const ArrayList = std.ArrayListUnmanaged;
812const Limit = std.io.Limit;
......@@ -11,9 +15,14 @@ pub const Limited = @import("Reader/Limited.zig");
1115
1216context: ?*anyopaque,
1317vtable: *const VTable,
18buffer: []u8,
19/// Number of bytes which have been consumed from `buffer`.
20seek: usize,
21/// In `buffer` before this are buffered bytes, after this is `undefined`.
22end: usize,
1423
1524pub const VTable = struct {
16 /// Writes bytes from the internally tracked stream position to `bw`.
25 /// Writes bytes from the internally tracked logical position to `bw`.
1726 ///
1827 /// Returns the number of bytes written, which will be at minimum `0` and
1928 /// at most `limit`. The number returned, including zero, does not indicate
......@@ -26,7 +35,7 @@ pub const VTable = struct {
2635 /// Implementations are encouraged to utilize mandatory minimum buffer
2736 /// sizes combined with short reads (returning a value less than `limit`)
2837 /// in order to minimize complexity.
29 read: *const fn (context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize,
38 stream: *const fn (r: *Reader, w: *Writer, limit: Limit) StreamError!usize,
3039
3140 /// Consumes bytes from the internally tracked stream position without
3241 /// providing access to them.
......@@ -42,11 +51,10 @@ pub const VTable = struct {
4251 /// sizes combined with short reads (returning a value less than `limit`)
4352 /// in order to minimize complexity.
4453 ///
45 /// If an implementation sets this to `null`, a default implementation is
46 /// provided which is based on calling `read`, borrowing
47 /// `BufferedReader.buffer` to construct a temporary `BufferedWriter` and
48 /// ignoring the written data.
49 discard: ?*const fn (context: ?*anyopaque, limit: Limit) Error!usize = null,
54 /// The default implementation is is based on calling `read`, borrowing
55 /// `buffer` to construct a temporary `Writer` and ignoring the written
56 /// data.
57 discard: *const fn (r: *Reader, limit: Limit) Error!usize = defaultDiscard,
5058};
5159
5260pub const StreamError = error{
......@@ -77,26 +85,97 @@ pub const ShortError = error{
7785 ReadFailed,
7886};
7987
80pub fn read(r: Reader, bw: *BufferedWriter, limit: Limit) StreamError!usize {
81 const before = bw.count;
82 const n = try r.vtable.read(r.context, bw, limit);
88pub const failing: Reader = .{
89 .context = undefined,
90 .vtable = &.{
91 .read = failingRead,
92 .discard = failingDiscard,
93 },
94 .buffer = &.{},
95 .seek = 0,
96 .end = 0,
97};
98
99pub const ending: Reader = .fixed(&.{});
100
101pub fn limited(r: *Reader, limit: Limit, buffer: []u8) Limited {
102 return Limited.init(r, limit, buffer);
103}
104
105/// Constructs a `Reader` such that it will read from `buffer` and then end.
106pub fn fixed(buffer: []const u8) Reader {
107 return .{
108 .context = undefined,
109 .vtable = &.{
110 .read = endingRead,
111 .discard = endingDiscard,
112 },
113 // This cast is safe because all potential writes to it will instead
114 // return `error.EndOfStream`.
115 .buffer = @constCast(buffer),
116 .end = buffer.len,
117 .seek = 0,
118 };
119}
120
121pub fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
122 const buffer = limit.slice(r.buffer[r.seek..r.end]);
123 if (buffer.len > 0) {
124 @branchHint(.likely);
125 const n = try w.write(buffer);
126 r.seek += n;
127 return n;
128 }
129 const before = w.count;
130 const n = try r.vtable.stream(r, w, limit);
83131 assert(n <= @intFromEnum(limit));
84 assert(bw.count == before + n);
132 assert(w.count == before + n);
85133 return n;
86134}
87135
88pub fn discard(r: Reader, limit: Limit) Error!usize {
89 const n = try r.vtable.discard(r.context, limit);
90 assert(n <= @intFromEnum(limit));
136pub fn discard(r: *Reader, limit: Limit) Error!usize {
137 const buffered_len = r.end - r.seek;
138 const remaining: Limit = if (limit.toInt()) |n| l: {
139 if (buffered_len >= n) {
140 r.seek += n;
141 return n;
142 }
143 break :l .limited(n - buffered_len);
144 } else .unlimited;
145 r.seek = 0;
146 r.end = 0;
147 const n = r.vtable.discard(r, remaining);
148 assert(n <= @intFromEnum(remaining));
149 return buffered_len + n;
150}
151
152pub fn defaultDiscard(r: *Reader, limit: Limit) Error!usize {
153 assert(r.seek == 0);
154 assert(r.end == 0);
155 var w: Writer = .discarding(r.buffer);
156 const n = r.stream(&w, limit) catch |err| switch (err) {
157 error.WriteFailed => unreachable,
158 error.ReadFailed => return error.ReadFailed,
159 error.EndOfStream => return error.EndOfStream,
160 };
161 if (n > @intFromEnum(limit)) {
162 const over_amt = n - @intFromEnum(limit);
163 assert(over_amt <= w.buffer.end); // limit may be exceeded only by an amount within buffer capacity.
164 r.seek = w.end - over_amt;
165 r.end = w.end;
166 return @intFromEnum(limit);
167 }
91168 return n;
92169}
93170
94/// Returns total number of bytes written to `bw`.
95pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize {
96 const readFn = r.vtable.read;
171/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
172/// a success case.
173///
174/// Returns total number of bytes written to `w`.
175pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize {
97176 var offset: usize = 0;
98177 while (true) {
99 offset += readFn(r.context, bw, .unlimited) catch |err| switch (err) {
178 offset += r.stream(w, .unlimited) catch |err| switch (err) {
100179 error.EndOfStream => return offset,
101180 else => |e| return e,
102181 };
......@@ -105,11 +184,12 @@ pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize
105184
106185/// Consumes the stream until the end, ignoring all the data, returning the
107186/// number of bytes discarded.
108pub fn discardRemaining(r: Reader) ShortError!usize {
109 const discardFn = r.vtable.discard;
110 var offset: usize = 0;
187pub fn discardRemaining(r: *Reader) ShortError!usize {
188 var offset: usize = r.end;
189 r.seek = 0;
190 r.end = 0;
111191 while (true) {
112 offset += discardFn(r.context, .unlimited) catch |err| switch (err) {
192 offset += r.vtable.discard(r, .unlimited) catch |err| switch (err) {
113193 error.EndOfStream => return offset,
114194 else => |e| return e,
115195 };
......@@ -121,112 +201,1133 @@ pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLo
121201/// Transfers all bytes from the current position to the end of the stream, up
122202/// to `limit`, returning them as a caller-owned allocated slice.
123203///
124/// If `limit` is exceeded, returns `error.StreamTooLong`. In such case, the
125/// stream is advanced one byte beyond the limit, and the consumed data is
126/// unrecoverable. Other functions listed below do not have this caveat.
204/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
205/// such case, the next byte that would be read will be the first one to exceed
206/// `limit`, and all preceeding bytes have been discarded.
207///
208/// Asserts `buffer` has nonzero capacity.
127209///
128210/// See also:
129/// * `readRemainingArrayList`
130/// * `BufferedReader.readRemainingArrayList`
131pub fn readRemainingAlloc(r: Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 {
211/// * `appendRemaining`
212pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 {
132213 var buffer: ArrayList(u8) = .empty;
133214 defer buffer.deinit(gpa);
134 try readRemainingArrayList(r, gpa, null, &buffer, limit, 1);
215 try appendRemaining(r, gpa, null, &buffer, limit, 1);
135216 return buffer.toOwnedSlice(gpa);
136217}
137218
138219/// Transfers all bytes from the current position to the end of the stream, up
139220/// to `limit`, appending them to `list`.
140221///
141/// If `limit` is exceeded:
142/// * The array list's length is increased by exactly one byte past `limit`.
143/// * The stream seek position is advanced by exactly one byte past `limit`.
144/// * `error.StreamTooLong` is returned.
222/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
223/// such case, the next byte that would be read will be the first one to exceed
224/// `limit`, and all preceeding bytes have been appended to `list`.
145225///
146/// The other function listed below has different semantics for an exceeded
147/// limit.
226/// Asserts `buffer` has nonzero capacity.
148227///
149228/// See also:
150/// * `BufferedReader.readRemainingArrayList`
151pub fn readRemainingArrayList(
152 r: Reader,
229/// * `allocRemaining`
230pub fn appendRemaining(
231 r: *Reader,
153232 gpa: Allocator,
154233 comptime alignment: ?std.mem.Alignment,
155234 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
156235 limit: Limit,
157 minimum_buffer_size: usize,
158236) LimitedAllocError!void {
159 var remaining = limit;
237 const buffer = r.buffer;
238 const buffered = buffer[r.seek..r.end];
239 const copy_len = limit.minInt(buffered.len);
240 try list.ensureUnusedCapacity(gpa, copy_len);
241 @memcpy(list.unusedCapacitySlice()[0..copy_len], buffer[0..copy_len]);
242 list.items.len += copy_len;
243 r.seek += copy_len;
244 if (copy_len == buffered.len) {
245 r.seek = 0;
246 r.end = 0;
247 }
248 var remaining = limit.subtract(copy_len).?;
160249 while (true) {
161 try list.ensureUnusedCapacity(gpa, minimum_buffer_size);
162 const buffer = remaining.slice1(list.unusedCapacitySlice());
163 const n = r.vtable.readVec(r.context, &.{buffer}) catch |err| switch (err) {
164 error.EndOfStream => return,
250 try list.ensureUnusedCapacity(gpa, 1);
251 const dest = remaining.slice(list.unusedCapacitySlice());
252 const additional_buffer = if (@intFromEnum(remaining) == dest.len) buffer else &.{};
253 const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) {
254 error.EndOfStream => break,
165255 error.ReadFailed => return error.ReadFailed,
166256 };
257 if (n >= dest.len) {
258 r.end = n - dest.len;
259 list.items.len += dest.len;
260 if (n == dest.len) return;
261 return error.StreamTooLong;
262 }
167263 list.items.len += n;
168 remaining = remaining.subtract(n) orelse return error.StreamTooLong;
264 remaining = remaining.subtract(n).?;
169265 }
170266}
171267
172pub const failing: Reader = .{
173 .context = undefined,
174 .vtable = &.{
175 .read = failingRead,
176 .discard = failingDiscard,
177 },
268/// Writes bytes from the internally tracked stream position to `data`.
269///
270/// Returns the number of bytes written, which will be at minimum `0` and
271/// at most the sum of each data slice length. The number of bytes read,
272/// including zero, does not indicate end of stream.
273///
274/// The reader's internal logical seek position moves forward in accordance
275/// with the number of bytes returned from this function.
276pub fn readVec(r: *Reader, data: []const []u8) Error!usize {
277 return readVecLimit(r, data, .unlimited);
278}
279
280/// Equivalent to `readVec` but reads at most `limit` bytes.
281///
282/// This ultimately will lower to a call to `stream`, but it must ensure
283/// that the buffer used has at least as much capacity, in case that function
284/// depends on a minimum buffer capacity. It also ensures that if the `stream`
285/// implementation calls `Writer.writableVector`, it will get this data slice
286/// along with the buffer at the end.
287pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
288 comptime assert(@intFromEnum(Limit.unlimited) == std.math.maxInt(usize));
289 var remaining = @intFromEnum(limit);
290 for (data, 0..) |buf, i| {
291 const buffered = r.buffer[r.seek..r.end];
292 const copy_len = @min(buffered.len, buf.len, remaining);
293 @memcpy(buf[0..copy_len], buffered[0..copy_len]);
294 r.seek += copy_len;
295 remaining -= copy_len;
296 if (remaining == 0) break;
297 if (buf.len - copy_len == 0) continue;
298
299 r.seek = 0;
300 r.end = 0;
301 var vecs: [8][]u8 = undefined; // Arbitrarily chosen value.
302 const available_remaining_buf = buf[copy_len..];
303 vecs[0] = available_remaining_buf[0..@min(available_remaining_buf.len, remaining)];
304 const vec_start_remaining = remaining;
305 remaining -= vecs[0].len;
306 var vecs_i: usize = 1;
307 var data_i: usize = i + 1;
308 while (true) {
309 if (vecs.len - vecs_i == 0) {
310 const n = try r.unbuffered_reader.readVec(&vecs);
311 return @intFromEnum(limit) - vec_start_remaining + n;
312 }
313 if (remaining == 0 or data.len - data_i == 0) {
314 vecs[vecs_i] = r.buffer;
315 vecs_i += 1;
316 const n = try r.unbuffered_reader.readVec(vecs[0..vecs_i]);
317 const cutoff = vec_start_remaining - remaining;
318 if (n > cutoff) {
319 r.end = n - cutoff;
320 return @intFromEnum(limit) - remaining;
321 } else {
322 return @intFromEnum(limit) - vec_start_remaining + n;
323 }
324 }
325 if (data[data_i].len == 0) {
326 data_i += 1;
327 continue;
328 }
329 const data_elem = data[data_i];
330 vecs[vecs_i] = data_elem[0..@min(data_elem.len, remaining)];
331 remaining -= vecs[vecs_i].len;
332 vecs_i += 1;
333 data_i += 1;
334 }
335 }
336 return @intFromEnum(limit) - remaining;
337}
338
339pub fn bufferContents(r: *Reader) []u8 {
340 return r.buffer[r.seek..r.end];
341}
342
343pub fn bufferedLen(r: *const Reader) usize {
344 return r.end - r.seek;
345}
346
347pub fn hashed(r: *Reader, hasher: anytype) Hashed(@TypeOf(hasher)) {
348 return .{ .in = r, .hasher = hasher };
349}
350
351pub fn readVecAll(r: *Reader, data: [][]u8) Error!void {
352 var index: usize = 0;
353 var truncate: usize = 0;
354 while (index < data.len) {
355 {
356 const untruncated = data[index];
357 data[index] = untruncated[truncate..];
358 defer data[index] = untruncated;
359 truncate += try r.readVec(data[index..]);
360 }
361 while (index < data.len and truncate >= data[index].len) {
362 truncate -= data[index].len;
363 index += 1;
364 }
365 }
366}
367
368/// "Pump" data from the reader to the writer.
369pub fn readAll(r: *Reader, bw: *Writer, limit: Limit) StreamError!void {
370 var remaining = limit;
371 while (remaining.nonzero()) {
372 const n = try r.read(bw, remaining);
373 remaining = remaining.subtract(n).?;
374 }
375}
376
377/// Returns the next `len` bytes from `unbuffered_reader`, filling the buffer as
378/// necessary.
379///
380/// Invalidates previously returned values from `peek`.
381///
382/// Asserts that the `Reader` was initialized with a buffer capacity at
383/// least as big as `len`.
384///
385/// If there are fewer than `len` bytes left in the stream, `error.EndOfStream`
386/// is returned instead.
387///
388/// See also:
389/// * `peek`
390/// * `toss`
391pub fn peek(r: *Reader, n: usize) Error![]u8 {
392 try r.fill(n);
393 return r.buffer[r.seek..][0..n];
394}
395
396/// Returns all the next buffered bytes from `unbuffered_reader`, after filling
397/// the buffer to ensure it contains at least `n` bytes.
398///
399/// Invalidates previously returned values from `peek` and `peekGreedy`.
400///
401/// Asserts that the `Reader` was initialized with a buffer capacity at
402/// least as big as `n`.
403///
404/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
405/// is returned instead.
406///
407/// See also:
408/// * `peek`
409/// * `toss`
410pub fn peekGreedy(r: *Reader, n: usize) Error![]u8 {
411 try r.fill(n);
412 return r.buffer[r.seek..r.end];
413}
414
415/// Skips the next `n` bytes from the stream, advancing the seek position. This
416/// is typically and safely used after `peek`.
417///
418/// Asserts that the number of bytes buffered is at least as many as `n`.
419///
420/// The "tossed" memory remains alive until a "peek" operation occurs.
421///
422/// See also:
423/// * `peek`.
424/// * `discard`.
425pub fn toss(r: *Reader, n: usize) void {
426 r.seek += n;
427 assert(r.seek <= r.end);
428}
429
430/// Equivalent to `toss(r.bufferedLen())`.
431pub fn tossAll(r: *Reader) void {
432 r.seek = 0;
433 r.end = 0;
434}
435
436/// Equivalent to `peek` followed by `toss`.
437///
438/// The data returned is invalidated by the next call to `take`, `peek`,
439/// `fill`, and functions with those prefixes.
440pub fn take(r: *Reader, n: usize) Error![]u8 {
441 const result = try r.peek(n);
442 r.toss(n);
443 return result;
444}
445
446/// Returns the next `n` bytes from `unbuffered_reader` as an array, filling
447/// the buffer as necessary and advancing the seek position `n` bytes.
448///
449/// Asserts that the `Reader` was initialized with a buffer capacity at
450/// least as big as `n`.
451///
452/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
453/// is returned instead.
454///
455/// See also:
456/// * `take`
457pub fn takeArray(r: *Reader, comptime n: usize) Error!*[n]u8 {
458 return (try r.take(n))[0..n];
459}
460
461/// Returns the next `n` bytes from `unbuffered_reader` as an array, filling
462/// the buffer as necessary, without advancing the seek position.
463///
464/// Asserts that the `Reader` was initialized with a buffer capacity at
465/// least as big as `n`.
466///
467/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
468/// is returned instead.
469///
470/// See also:
471/// * `peek`
472/// * `takeArray`
473pub fn peekArray(r: *Reader, comptime n: usize) Error!*[n]u8 {
474 return (try r.peek(n))[0..n];
475}
476
477/// Skips the next `n` bytes from the stream, advancing the seek position.
478///
479/// Unlike `toss` which is infallible, in this function `n` can be any amount.
480///
481/// Returns `error.EndOfStream` if fewer than `n` bytes could be discarded.
482///
483/// See also:
484/// * `toss`
485/// * `discardRemaining`
486/// * `discardShort`
487/// * `discard`
488pub fn discardAll(r: *Reader, n: usize) Error!void {
489 if ((try r.discardShort(n)) != n) return error.EndOfStream;
490}
491
492pub fn discardAll64(r: *Reader, n: u64) Error!void {
493 var remaining: u64 = n;
494 while (remaining > 0) {
495 const limited_remaining = std.math.cast(usize, remaining) orelse std.math.maxInt(usize);
496 try discardAll(r, limited_remaining);
497 remaining -= limited_remaining;
498 }
499}
500
501/// Skips the next `n` bytes from the stream, advancing the seek position.
502///
503/// Unlike `toss` which is infallible, in this function `n` can be any amount.
504///
505/// Returns the number of bytes discarded, which is less than `n` if and only
506/// if the stream reached the end.
507///
508/// See also:
509/// * `discardAll`
510/// * `discardRemaining`
511/// * `discard`
512pub fn discardShort(r: *Reader, n: usize) ShortError!usize {
513 const proposed_seek = r.seek + n;
514 if (proposed_seek <= r.end) {
515 @branchHint(.likely);
516 r.seek = proposed_seek;
517 return n;
518 }
519 var remaining = n - (r.end - r.seek);
520 r.end = 0;
521 r.seek = 0;
522 while (true) {
523 const discard_len = r.unbuffered_reader.discard(.limited(remaining)) catch |err| switch (err) {
524 error.EndOfStream => return n - remaining,
525 error.ReadFailed => return error.ReadFailed,
526 };
527 remaining -= discard_len;
528 if (remaining == 0) return n;
529 }
530}
531
532/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
533/// the seek position.
534///
535/// Invalidates previously returned values from `peek`.
536///
537/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
538/// returned instead.
539///
540/// See also:
541/// * `peek`
542/// * `readSliceShort`
543pub fn readSlice(r: *Reader, buffer: []u8) Error!void {
544 const n = try readSliceShort(r, buffer);
545 if (n != buffer.len) return error.EndOfStream;
546}
547
548/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
549/// the seek position.
550///
551/// Invalidates previously returned values from `peek`.
552///
553/// Returns the number of bytes read, which is less than `buffer.len` if and
554/// only if the stream reached the end.
555///
556/// See also:
557/// * `readSlice`
558pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {
559 const in_buffer = r.buffer[r.seek..r.end];
560 const copy_len = @min(buffer.len, in_buffer.len);
561 @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]);
562 if (buffer.len - copy_len == 0) {
563 r.seek += copy_len;
564 return buffer.len;
565 }
566 var i: usize = copy_len;
567 r.end = 0;
568 r.seek = 0;
569 while (true) {
570 const remaining = buffer[i..];
571 const n = r.unbuffered_reader.readVec(&.{ remaining, r.buffer }) catch |err| switch (err) {
572 error.EndOfStream => return i,
573 error.ReadFailed => return error.ReadFailed,
574 };
575 if (n < remaining.len) {
576 i += n;
577 continue;
578 }
579 r.end = n - remaining.len;
580 return buffer.len;
581 }
582}
583
584/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
585/// the seek position.
586///
587/// Invalidates previously returned values from `peek`.
588///
589/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
590/// returned instead.
591///
592/// The function is inline to avoid the dead code in case `endian` is
593/// comptime-known and matches host endianness.
594///
595/// See also:
596/// * `readSlice`
597/// * `readSliceEndianAlloc`
598pub inline fn readSliceEndian(
599 r: *Reader,
600 comptime Elem: type,
601 buffer: []Elem,
602 endian: std.builtin.Endian,
603) Error!void {
604 try readSlice(r, @ptrCast(buffer));
605 if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem);
606}
607
608pub const ReadAllocError = Error || Allocator.Error;
609
610/// The function is inline to avoid the dead code in case `endian` is
611/// comptime-known and matches host endianness.
612pub inline fn readSliceEndianAlloc(
613 r: *Reader,
614 allocator: Allocator,
615 comptime Elem: type,
616 len: usize,
617 endian: std.builtin.Endian,
618) ReadAllocError![]Elem {
619 const dest = try allocator.alloc(Elem, len);
620 errdefer allocator.free(dest);
621 try readSlice(r, @ptrCast(dest));
622 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
623 return dest;
624}
625
626pub fn readSliceAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
627 const dest = try allocator.alloc(u8, len);
628 errdefer allocator.free(dest);
629 try readSlice(r, dest);
630 return dest;
631}
632
633pub const DelimiterError = error{
634 /// See the `Reader` implementation for detailed diagnostics.
635 ReadFailed,
636 /// For "inclusive" functions, stream ended before the delimiter was found.
637 /// For "exclusive" functions, stream ended and there are no more bytes to
638 /// return.
639 EndOfStream,
640 /// The delimiter was not found within a number of bytes matching the
641 /// capacity of the `Reader`.
642 StreamTooLong,
178643};
179644
180pub const ending: Reader = .{
181 .context = undefined,
182 .vtable = &.{
183 .read = endingRead,
184 .discard = endingDiscard,
185 },
645/// Returns a slice of the next bytes of buffered data from the stream until
646/// `sentinel` is found, advancing the seek position.
647///
648/// Returned slice has a sentinel.
649///
650/// Invalidates previously returned values from `peek`.
651///
652/// See also:
653/// * `peekSentinel`
654/// * `takeDelimiterExclusive`
655/// * `takeDelimiterInclusive`
656pub fn takeSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
657 const result = try r.peekSentinel(sentinel);
658 r.toss(result.len + 1);
659 return result;
660}
661
662pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
663 const result = try r.peekDelimiterInclusive(sentinel);
664 return result[0 .. result.len - 1 :sentinel];
665}
666
667/// Returns a slice of the next bytes of buffered data from the stream until
668/// `delimiter` is found, advancing the seek position.
669///
670/// Returned slice includes the delimiter as the last byte.
671///
672/// Invalidates previously returned values from `peek`.
673///
674/// See also:
675/// * `takeSentinel`
676/// * `takeDelimiterExclusive`
677/// * `peekDelimiterInclusive`
678pub fn takeDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
679 const result = try r.peekDelimiterInclusive(delimiter);
680 r.toss(result.len);
681 return result;
682}
683
684/// Returns a slice of the next bytes of buffered data from the stream until
685/// `delimiter` is found, without advancing the seek position.
686///
687/// Returned slice includes the delimiter as the last byte.
688///
689/// Invalidates previously returned values from `peek`.
690///
691/// See also:
692/// * `peekSentinel`
693/// * `peekDelimiterExclusive`
694/// * `takeDelimiterInclusive`
695pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
696 const buffer = r.buffer[0..r.end];
697 const seek = r.seek;
698 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {
699 @branchHint(.likely);
700 return buffer[seek .. end + 1];
701 }
702 if (seek > 0) {
703 const remainder = buffer[seek..];
704 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
705 r.end = remainder.len;
706 r.seek = 0;
707 }
708 while (r.end < r.buffer.len) {
709 const n = try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
710 const prev_end = r.end;
711 r.end = prev_end + n;
712 if (std.mem.indexOfScalarPos(u8, r.buffer[0..r.end], prev_end, delimiter)) |end| {
713 return r.buffer[0 .. end + 1];
714 }
715 }
716 return error.StreamTooLong;
717}
718
719/// Returns a slice of the next bytes of buffered data from the stream until
720/// `delimiter` is found, advancing the seek position.
721///
722/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
723/// to a delimiter, unless it would result in a length 0 return value, in which
724/// case `error.EndOfStream` is returned instead.
725///
726/// If the delimiter is not found within a number of bytes matching the
727/// capacity of this `Reader`, `error.StreamTooLong` is returned. In
728/// such case, the stream state is unmodified as if this function was never
729/// called.
730///
731/// Invalidates previously returned values from `peek`.
732///
733/// See also:
734/// * `takeDelimiterInclusive`
735/// * `peekDelimiterExclusive`
736pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
737 const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
738 error.EndOfStream => {
739 if (r.end == 0) return error.EndOfStream;
740 r.toss(r.end);
741 return r.buffer[0..r.end];
742 },
743 else => |e| return e,
744 };
745 r.toss(result.len);
746 return result[0 .. result.len - 1];
747}
748
749/// Returns a slice of the next bytes of buffered data from the stream until
750/// `delimiter` is found, without advancing the seek position.
751///
752/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
753/// to a delimiter, unless it would result in a length 0 return value, in which
754/// case `error.EndOfStream` is returned instead.
755///
756/// If the delimiter is not found within a number of bytes matching the
757/// capacity of this `Reader`, `error.StreamTooLong` is returned. In
758/// such case, the stream state is unmodified as if this function was never
759/// called.
760///
761/// Invalidates previously returned values from `peek`.
762///
763/// See also:
764/// * `peekDelimiterInclusive`
765/// * `takeDelimiterExclusive`
766pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
767 const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
768 error.EndOfStream => {
769 if (r.end == 0) return error.EndOfStream;
770 return r.buffer[0..r.end];
771 },
772 else => |e| return e,
773 };
774 return result[0 .. result.len - 1];
775}
776
777/// Appends to `bw` contents by reading from the stream until `delimiter` is
778/// found. Does not write the delimiter itself.
779///
780/// Returns number of bytes streamed.
781pub fn readDelimiter(r: *Reader, bw: *Writer, delimiter: u8) StreamError!usize {
782 const amount, const to = try r.readAny(bw, delimiter, .unlimited);
783 return switch (to) {
784 .delimiter => amount,
785 .limit => unreachable,
786 .end => error.EndOfStream,
787 };
788}
789
790/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
791/// Does not write the delimiter itself.
792///
793/// Succeeds if stream ends before delimiter found.
794///
795/// Returns number of bytes streamed. The end is not signaled to the writer.
796pub fn readDelimiterEnding(
797 r: *Reader,
798 bw: *Writer,
799 delimiter: u8,
800) StreamRemainingError!usize {
801 const amount, const to = try r.readAny(bw, delimiter, .unlimited);
802 return switch (to) {
803 .delimiter, .end => amount,
804 .limit => unreachable,
805 };
806}
807
808pub const StreamDelimiterLimitedError = StreamRemainingError || error{
809 /// Stream ended before the delimiter was found.
810 EndOfStream,
811 /// The delimiter was not found within the limit.
812 StreamTooLong,
186813};
187814
188pub fn unbuffered(r: Reader) BufferedReader {
189 return buffered(r, &.{});
815/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
816/// Does not write the delimiter itself.
817///
818/// Returns number of bytes streamed.
819pub fn readDelimiterLimit(
820 r: *Reader,
821 bw: *Writer,
822 delimiter: u8,
823 limit: Limit,
824) StreamDelimiterLimitedError!usize {
825 const amount, const to = try r.readAny(bw, delimiter, limit);
826 return switch (to) {
827 .delimiter => amount,
828 .limit => error.StreamTooLong,
829 .end => error.EndOfStream,
830 };
190831}
191832
192pub fn buffered(r: Reader, buffer: []u8) BufferedReader {
193 return .{
194 .unbuffered_reader = r,
195 .seek = 0,
196 .buffer = buffer,
197 .end = 0,
833fn readAny(
834 r: *Reader,
835 bw: *Writer,
836 delimiter: ?u8,
837 limit: Limit,
838) StreamRemainingError!struct { usize, enum { delimiter, limit, end } } {
839 var amount: usize = 0;
840 var remaining = limit;
841 while (remaining.nonzero()) {
842 const available = remaining.slice(r.peekGreedy(1) catch |err| switch (err) {
843 error.ReadFailed => |e| return e,
844 error.EndOfStream => return .{ amount, .end },
845 });
846 if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| {
847 try bw.writeAll(available[0..delimiter_index]);
848 r.toss(delimiter_index + 1);
849 return .{ amount + delimiter_index, .delimiter };
850 };
851 try bw.writeAll(available);
852 r.toss(available.len);
853 amount += available.len;
854 remaining = remaining.subtract(available.len).?;
855 }
856 return .{ amount, .limit };
857}
858
859/// Reads from the stream until specified byte is found, discarding all data,
860/// including the delimiter.
861///
862/// If end of stream is found, this function succeeds.
863pub fn discardDelimiterInclusive(r: *Reader, delimiter: u8) Error!void {
864 _ = r;
865 _ = delimiter;
866 @panic("TODO");
867}
868
869/// Reads from the stream until specified byte is found, discarding all data,
870/// excluding the delimiter.
871///
872/// Succeeds if stream ends before delimiter found.
873pub fn discardDelimiterExclusive(r: *Reader, delimiter: u8) ShortError!void {
874 _ = r;
875 _ = delimiter;
876 @panic("TODO");
877}
878
879/// Fills the buffer such that it contains at least `n` bytes, without
880/// advancing the seek position.
881///
882/// Returns `error.EndOfStream` if and only if there are fewer than `n` bytes
883/// remaining.
884///
885/// Asserts buffer capacity is at least `n`.
886pub fn fill(r: *Reader, n: usize) Error!void {
887 assert(n <= r.buffer.len);
888 if (r.seek + n <= r.end) {
889 @branchHint(.likely);
890 return;
891 }
892 rebaseCapacity(r, n);
893 while (r.end < r.seek + n) {
894 r.end += try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
895 }
896}
897
898/// Without advancing the seek position, does exactly one underlying read, filling the buffer as
899/// much as possible. This may result in zero bytes added to the buffer, which is not an end of
900/// stream condition. End of stream is communicated via returning `error.EndOfStream`.
901///
902/// Asserts buffer capacity is at least 1.
903pub fn fillMore(r: *Reader) Error!void {
904 rebaseCapacity(r, 1);
905 r.end += try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
906}
907
908/// Returns the next byte from the stream or returns `error.EndOfStream`.
909///
910/// Does not advance the seek position.
911///
912/// Asserts the buffer capacity is nonzero.
913pub fn peekByte(r: *Reader) Error!u8 {
914 const buffer = r.buffer[0..r.end];
915 const seek = r.seek;
916 if (seek >= buffer.len) {
917 @branchHint(.unlikely);
918 try fill(r, 1);
919 }
920 return buffer[seek];
921}
922
923/// Reads 1 byte from the stream or returns `error.EndOfStream`.
924///
925/// Asserts the buffer capacity is nonzero.
926pub fn takeByte(r: *Reader) Error!u8 {
927 const result = try peekByte(r);
928 r.seek += 1;
929 return result;
930}
931
932/// Same as `takeByte` except the returned byte is signed.
933pub fn takeByteSigned(r: *Reader) Error!i8 {
934 return @bitCast(try r.takeByte());
935}
936
937/// Asserts the buffer was initialized with a capacity at least `@bitSizeOf(T) / 8`.
938pub inline fn takeInt(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
939 const n = @divExact(@typeInfo(T).int.bits, 8);
940 return std.mem.readInt(T, try r.takeArray(n), endian);
941}
942
943/// Asserts the buffer was initialized with a capacity at least `n`.
944pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n: usize) Error!Int {
945 assert(n <= @sizeOf(Int));
946 return std.mem.readVarInt(Int, try r.take(n), endian);
947}
948
949/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
950///
951/// Advances the seek position.
952///
953/// See also:
954/// * `peekStruct`
955pub fn takeStruct(r: *Reader, comptime T: type) Error!*align(1) T {
956 // Only extern and packed structs have defined in-memory layout.
957 comptime assert(@typeInfo(T).@"struct".layout != .auto);
958 return @ptrCast(try r.takeArray(@sizeOf(T)));
959}
960
961/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
962///
963/// Does not advance the seek position.
964///
965/// See also:
966/// * `takeStruct`
967pub fn peekStruct(r: *Reader, comptime T: type) Error!*align(1) T {
968 // Only extern and packed structs have defined in-memory layout.
969 comptime assert(@typeInfo(T).@"struct".layout != .auto);
970 return @ptrCast(try r.peekArray(@sizeOf(T)));
971}
972
973/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
974///
975/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
976/// when `endian` is comptime-known and matches the host endianness.
977pub inline fn takeStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
978 var res = (try r.takeStruct(T)).*;
979 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
980 return res;
981}
982
983/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
984///
985/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
986/// when `endian` is comptime-known and matches the host endianness.
987pub inline fn peekStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
988 var res = (try r.peekStruct(T)).*;
989 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
990 return res;
991}
992
993pub const TakeEnumError = Error || error{InvalidEnumTag};
994
995/// Reads an integer with the same size as the given enum's tag type. If the
996/// integer matches an enum tag, casts the integer to the enum tag and returns
997/// it. Otherwise, returns `error.InvalidEnumTag`.
998///
999/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
1000pub fn takeEnum(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) TakeEnumError!Enum {
1001 const Tag = @typeInfo(Enum).@"enum".tag_type;
1002 const int = try r.takeInt(Tag, endian);
1003 return std.meta.intToEnum(Enum, int);
1004}
1005
1006/// Reads an integer with the same size as the given nonexhaustive enum's tag type.
1007///
1008/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
1009pub fn takeEnumNonexhaustive(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) Error!Enum {
1010 const info = @typeInfo(Enum).@"enum";
1011 comptime assert(!info.is_exhaustive);
1012 comptime assert(@bitSizeOf(info.tag_type) == @sizeOf(info.tag_type) * 8);
1013 return takeEnum(r, Enum, endian) catch |err| switch (err) {
1014 error.InvalidEnumTag => unreachable,
1015 else => |e| return e,
1981016 };
1991017}
2001018
201pub fn limited(r: Reader, limit: Limit) Limited {
202 return .{
203 .unlimited_reader = r,
204 .remaining = limit,
1019pub const TakeLeb128Error = Error || error{Overflow};
1020
1021/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.
1022pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
1023 const result_info = @typeInfo(Result).int;
1024 return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Type(.{ .int = .{
1025 .signedness = result_info.signedness,
1026 .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),
1027 } }))) orelse error.Overflow;
1028}
1029
1030pub fn expandTotalCapacity(r: *Reader, allocator: Allocator, n: usize) Allocator.Error!void {
1031 if (n <= r.buffer.len) return;
1032 if (r.seek > 0) rebase(r);
1033 var list: ArrayList(u8) = .{
1034 .items = r.buffer[0..r.end],
1035 .capacity = r.buffer.len,
2051036 };
1037 defer r.buffer = list.allocatedSlice();
1038 try list.ensureTotalCapacity(allocator, n);
1039}
1040
1041pub const FillAllocError = Error || Allocator.Error;
1042
1043pub fn fillAlloc(r: *Reader, allocator: Allocator, n: usize) FillAllocError!void {
1044 try expandTotalCapacity(r, allocator, n);
1045 return fill(r, n);
1046}
1047
1048/// Returns a slice into the unused capacity of `buffer` with at least
1049/// `min_len` bytes, extending `buffer` by resizing it with `gpa` as necessary.
1050///
1051/// After calling this function, typically the caller will follow up with a
1052/// call to `advanceBufferEnd` to report the actual number of bytes buffered.
1053pub fn writableSliceGreedyAlloc(r: *Reader, allocator: Allocator, min_len: usize) Allocator.Error![]u8 {
1054 {
1055 const unused = r.buffer[r.end..];
1056 if (unused.len >= min_len) return unused;
1057 }
1058 if (r.seek > 0) rebase(r);
1059 {
1060 var list: ArrayList(u8) = .{
1061 .items = r.buffer[0..r.end],
1062 .capacity = r.buffer.len,
1063 };
1064 defer r.buffer = list.allocatedSlice();
1065 try list.ensureUnusedCapacity(allocator, min_len);
1066 }
1067 const unused = r.buffer[r.end..];
1068 assert(unused.len >= min_len);
1069 return unused;
1070}
1071
1072/// After writing directly into the unused capacity of `buffer`, this function
1073/// updates `end` so that users of `Reader` can receive the data.
1074pub fn advanceBufferEnd(r: *Reader, n: usize) void {
1075 assert(n <= r.buffer.len - r.end);
1076 r.end += n;
1077}
1078
1079fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
1080 const result_info = @typeInfo(Result).int;
1081 comptime assert(result_info.bits % 7 == 0);
1082 var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;
1083 const UnsignedResult = @Type(.{ .int = .{
1084 .signedness = .unsigned,
1085 .bits = result_info.bits,
1086 } });
1087 var result: UnsignedResult = 0;
1088 var fits = true;
1089 while (true) {
1090 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try r.peekGreedy(1));
1091 for (buffer, 1..) |byte, len| {
1092 if (remaining_bits > 0) {
1093 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) |
1094 if (result_info.bits > 7) @shrExact(result, 7) else 0;
1095 remaining_bits -= 7;
1096 } else if (fits) fits = switch (result_info.signedness) {
1097 .signed => @as(i7, @bitCast(byte.bits)) ==
1098 @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),
1099 .unsigned => byte.bits == 0,
1100 };
1101 if (byte.more) continue;
1102 r.toss(len);
1103 return if (fits) @as(Result, @bitCast(result)) >> remaining_bits else error.Overflow;
1104 }
1105 r.toss(buffer.len);
1106 }
1107}
1108
1109/// Left-aligns data such that `r.seek` becomes zero.
1110pub fn rebase(r: *Reader) void {
1111 const data = r.buffer[r.seek..r.end];
1112 const dest = r.buffer[0..data.len];
1113 std.mem.copyForwards(u8, dest, data);
1114 r.seek = 0;
1115 r.end = data.len;
2061116}
2071117
208fn endingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize {
209 _ = context;
210 _ = bw;
1118/// Ensures `capacity` more data can be buffered without rebasing, by rebasing
1119/// if necessary.
1120///
1121/// Asserts `capacity` is within the buffer capacity.
1122pub fn rebaseCapacity(r: *Reader, capacity: usize) void {
1123 if (r.end > r.buffer.len - capacity) rebase(r);
1124}
1125
1126/// Advances the stream and decreases the size of the storage buffer by `n`,
1127/// returning the range of bytes no longer accessible by `r`.
1128///
1129/// This action can be undone by `restitute`.
1130///
1131/// Asserts there are at least `n` buffered bytes already.
1132///
1133/// Asserts that `r.seek` is zero, i.e. the buffer is in a rebased state.
1134pub fn steal(r: *Reader, n: usize) []u8 {
1135 assert(r.seek == 0);
1136 assert(n <= r.end);
1137 const stolen = r.buffer[0..n];
1138 r.buffer = r.buffer[n..];
1139 r.end -= n;
1140 return stolen;
1141}
1142
1143/// Expands the storage buffer, undoing the effects of `steal`
1144/// Assumes that `n` does not exceed the total number of stolen bytes.
1145pub fn restitute(r: *Reader, n: usize) void {
1146 r.buffer = (r.buffer.ptr - n)[0 .. r.buffer.len + n];
1147 r.end += n;
1148 r.seek += n;
1149}
1150
1151test fixed {
1152 var r: Reader = undefined;
1153 r.initFixed("a\x02");
1154 try testing.expect((try r.takeByte()) == 'a');
1155 try testing.expect((try r.takeEnum(enum(u8) {
1156 a = 0,
1157 b = 99,
1158 c = 2,
1159 d = 3,
1160 }, builtin.cpu.arch.endian())) == .c);
1161 try testing.expectError(error.EndOfStream, r.takeByte());
1162}
1163
1164test peek {
1165 return error.Unimplemented;
1166}
1167
1168test peekGreedy {
1169 return error.Unimplemented;
1170}
1171
1172test toss {
1173 return error.Unimplemented;
1174}
1175
1176test take {
1177 return error.Unimplemented;
1178}
1179
1180test takeArray {
1181 return error.Unimplemented;
1182}
1183
1184test peekArray {
1185 return error.Unimplemented;
1186}
1187
1188test discardAll {
1189 var r: Reader = undefined;
1190 r.initFixed("foobar");
1191 try r.discard(3);
1192 try testing.expectEqualStrings("bar", try r.take(3));
1193 try r.discard(0);
1194 try testing.expectError(error.EndOfStream, r.discard(1));
1195}
1196
1197test discardRemaining {
1198 return error.Unimplemented;
1199}
1200
1201test stream {
1202 return error.Unimplemented;
1203}
1204
1205test takeSentinel {
1206 return error.Unimplemented;
1207}
1208
1209test peekSentinel {
1210 return error.Unimplemented;
1211}
1212
1213test takeDelimiterInclusive {
1214 return error.Unimplemented;
1215}
1216
1217test peekDelimiterInclusive {
1218 return error.Unimplemented;
1219}
1220
1221test takeDelimiterExclusive {
1222 return error.Unimplemented;
1223}
1224
1225test peekDelimiterExclusive {
1226 return error.Unimplemented;
1227}
1228
1229test readDelimiter {
1230 return error.Unimplemented;
1231}
1232
1233test readDelimiterEnding {
1234 return error.Unimplemented;
1235}
1236
1237test readDelimiterLimit {
1238 return error.Unimplemented;
1239}
1240
1241test discardDelimiterExclusive {
1242 return error.Unimplemented;
1243}
1244
1245test discardDelimiterInclusive {
1246 return error.Unimplemented;
1247}
1248
1249test fill {
1250 return error.Unimplemented;
1251}
1252
1253test takeByte {
1254 return error.Unimplemented;
1255}
1256
1257test takeByteSigned {
1258 return error.Unimplemented;
1259}
1260
1261test takeInt {
1262 return error.Unimplemented;
1263}
1264
1265test takeVarInt {
1266 return error.Unimplemented;
1267}
1268
1269test takeStruct {
1270 return error.Unimplemented;
1271}
1272
1273test peekStruct {
1274 return error.Unimplemented;
1275}
1276
1277test takeStructEndian {
1278 return error.Unimplemented;
1279}
1280
1281test peekStructEndian {
1282 return error.Unimplemented;
1283}
1284
1285test takeEnum {
1286 return error.Unimplemented;
1287}
1288
1289test takeLeb128 {
1290 return error.Unimplemented;
1291}
1292
1293test readSliceShort {
1294 return error.Unimplemented;
1295}
1296
1297test readVec {
1298 return error.Unimplemented;
1299}
1300
1301test "expected error.EndOfStream" {
1302 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1303 var r: std.io.Reader = undefined;
1304 r.initFixed("");
1305 try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));
1306 try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));
1307}
1308
1309fn endingRead(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1310 _ = r;
1311 _ = w;
2111312 _ = limit;
2121313 return error.EndOfStream;
2131314}
2141315
215fn endingDiscard(context: ?*anyopaque, limit: Limit) Error!usize {
216 _ = context;
1316fn endingDiscard(r: *Reader, limit: Limit) Error!usize {
1317 _ = r;
2171318 _ = limit;
2181319 return error.EndOfStream;
2191320}
2201321
221fn failingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize {
222 _ = context;
223 _ = bw;
1322fn failingRead(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1323 _ = r;
1324 _ = w;
2241325 _ = limit;
2251326 return error.ReadFailed;
2261327}
2271328
228fn failingDiscard(context: ?*anyopaque, limit: Limit) Error!usize {
229 _ = context;
1329fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
1330 _ = r;
2301331 _ = limit;
2311332 return error.ReadFailed;
2321333}
......@@ -270,46 +1371,31 @@ test "readAlloc when the backing reader provides one byte at a time" {
2701371/// implementation details.
2711372pub fn Hashed(comptime Hasher: type) type {
2721373 return struct {
273 in: *BufferedReader,
1374 in: *Reader,
2741375 hasher: Hasher,
1376 interface: Reader,
2751377
276 pub fn readable(this: *@This(), buffer: []u8) BufferedReader {
1378 pub fn init(in: *Reader, hasher: Hasher, buffer: []u8) @This() {
2771379 return .{
278 .unbuffered_reader = .{
279 .context = this,
1380 .in = in,
1381 .hasher = hasher,
1382 .interface = .{
2801383 .vtable = &.{
2811384 .read = @This().read,
2821385 .discard = @This().discard,
2831386 },
1387 .buffer = buffer,
1388 .end = 0,
1389 .seek = 0,
2841390 },
285 .buffer = buffer,
286 .end = 0,
287 .seek = 0,
288 };
289 }
290
291 fn read(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize {
292 const this: *@This() = @alignCast(@ptrCast(context));
293 const slice = limit.slice(try bw.writableSliceGreedy(1));
294 const n = try this.in.readVec(&.{slice});
295 this.hasher.update(slice[0..n]);
296 bw.advance(n);
297 return n;
298 }
299
300 fn discard(context: ?*anyopaque, limit: Limit) Error!usize {
301 const this: *@This() = @alignCast(@ptrCast(context));
302 var bw = this.hasher.writable(&.{});
303 const n = this.in.read(&bw, limit) catch |err| switch (err) {
304 error.WriteFailed => unreachable,
305 else => |e| return e,
3061391 };
307 return n;
3081392 }
3091393
310 fn readVec(context: ?*anyopaque, data: []const []u8) Error!usize {
311 const this: *@This() = @alignCast(@ptrCast(context));
1394 fn read(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1395 const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1396 const data = w.writableVector(limit);
3121397 const n = try this.in.readVec(data);
1398 w.advanceVector(n);
3131399 var remaining: usize = n;
3141400 for (data) |slice| {
3151401 if (remaining < slice.len) {
......@@ -323,5 +1409,15 @@ pub fn Hashed(comptime Hasher: type) type {
3231409 assert(remaining == 0);
3241410 return n;
3251411 }
1412
1413 fn discard(r: *Reader, limit: Limit) Error!usize {
1414 const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1415 var bw = this.hasher.writable(&.{});
1416 const n = this.in.read(&bw, limit) catch |err| switch (err) {
1417 error.WriteFailed => unreachable,
1418 else => |e| return e,
1419 };
1420 return n;
1421 }
3261422 };
3271423}
lib/std/io/Reader/Limited.zig+15-29
......@@ -5,21 +5,27 @@ const Reader = std.io.Reader;
55const BufferedWriter = std.io.BufferedWriter;
66const Limit = std.io.Limit;
77
8unlimited_reader: Reader,
8unlimited: *Reader,
99remaining: Limit,
10interface: Reader,
1011
11pub fn reader(l: *Limited) Reader {
12pub fn init(reader: *Reader, limit: Limit, buffer: []u8) Limited {
1213 return .{
13 .context = l,
14 .vtable = &.{
15 .read = passthruRead,
16 .readVec = passthruReadVec,
17 .discard = passthruDiscard,
14 .unlimited = reader,
15 .remaining = limit,
16 .interface = .{
17 .vtable = &.{
18 .stream = stream,
19 .discard = discard,
20 },
21 .buffer = buffer,
22 .seek = 0,
23 .end = 0,
1824 },
1925 };
2026}
2127
22fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {
28fn stream(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {
2329 const l: *Limited = @alignCast(@ptrCast(context));
2430 const combined_limit = limit.min(l.remaining);
2531 const n = try l.unlimited_reader.read(bw, combined_limit);
......@@ -27,30 +33,10 @@ fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.
2733 return n;
2834}
2935
30fn passthruDiscard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
36fn discard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
3137 const l: *Limited = @alignCast(@ptrCast(context));
3238 const combined_limit = limit.min(l.remaining);
3339 const n = try l.unlimited_reader.discard(combined_limit);
3440 l.remaining = l.remaining.subtract(n).?;
3541 return n;
3642}
37
38fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize {
39 const l: *Limited = @alignCast(@ptrCast(context));
40 if (data.len == 0) return 0;
41 if (data[0].len >= @intFromEnum(l.remaining)) {
42 const n = try l.unlimited_reader.readVec(&.{l.remaining.slice(data[0])});
43 l.remaining = l.remaining.subtract(n).?;
44 return n;
45 }
46 var total: usize = 0;
47 for (data, 0..) |buf, i| {
48 total += buf.len;
49 if (total > @intFromEnum(l.remaining)) {
50 const n = try l.unlimited_reader.readVec(data[0..i]);
51 l.remaining = l.remaining.subtract(n).?;
52 return n;
53 }
54 }
55 return 0;
56}
lib/std/leb128.zig+8-15
......@@ -114,32 +114,27 @@ test writeSignedFixed {
114114}
115115
116116fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
117 var br: std.io.BufferedReader = undefined;
118 br.initFixed(encoded);
117 var br: std.io.Reader = .fixed(encoded);
119118 return br.takeIleb128(T);
120119}
121120
122121fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {
123 var br: std.io.BufferedReader = undefined;
124 br.initFixed(encoded);
122 var br: std.io.Reader = .fixed(encoded);
125123 return br.takeUleb128(T);
126124}
127125
128126fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
129 var br: std.io.BufferedReader = undefined;
130 br.initFixed(encoded);
127 var br: std.io.Reader = .fixed(encoded);
131128 return br.readIleb128(T);
132129}
133130
134131fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
135 var br: std.io.BufferedReader = undefined;
136 br.initFixed(encoded);
132 var br: std.io.Reader = .fixed(encoded);
137133 return br.readUleb128(T);
138134}
139135
140136fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {
141 var br: std.io.BufferedReader = undefined;
142 br.initFixed(encoded);
137 var br: std.io.Reader = .fixed(encoded);
143138 var i: usize = 0;
144139 while (i < N) : (i += 1) {
145140 _ = try br.readIleb128(T);
......@@ -147,8 +142,7 @@ fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u
147142}
148143
149144fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {
150 var br: std.io.BufferedReader = undefined;
151 br.initFixed(encoded);
145 var br: std.io.Reader = .fixed(encoded);
152146 var i: usize = 0;
153147 while (i < N) : (i += 1) {
154148 _ = try br.readUleb128(T);
......@@ -248,7 +242,7 @@ fn test_write_leb128(value: anytype) !void {
248242 const t_signed = signedness == .signed;
249243
250244 const writeStream = if (t_signed) std.io.BufferedWriter.writeIleb128 else std.io.BufferedWriter.writeUleb128;
251 const readStream = if (t_signed) std.io.BufferedReader.readIleb128 else std.io.BufferedReader.readUleb128;
245 const readStream = if (t_signed) std.io.Reader.readIleb128 else std.io.Reader.readUleb128;
252246
253247 // decode to a larger bit size too, to ensure sign extension
254248 // is working as expected
......@@ -275,8 +269,7 @@ fn test_write_leb128(value: anytype) !void {
275269 try testing.expect(bw.buffer.items.len == bytes_needed);
276270
277271 // stream read
278 var br: std.io.BufferedReader = undefined;
279 br.initFixed(&buf);
272 var br: std.io.Reader = .fixed(&buf);
280273 const sr = try readStream(&br, T);
281274 try testing.expect(br.seek == bytes_needed);
282275 try testing.expect(sr == value);
lib/std/net.zig+2-2
......@@ -1378,7 +1378,7 @@ fn parseHosts(
13781378 name: []const u8,
13791379 family: posix.sa_family_t,
13801380 port: u16,
1381 br: *std.io.BufferedReader,
1381 br: *std.io.Reader,
13821382) error{ OutOfMemory, ReadFailed }!void {
13831383 while (true) {
13841384 const line = br.takeDelimiterExclusive('\n') catch |err| switch (err) {
......@@ -1592,7 +1592,7 @@ const ResolvConf = struct {
15921592 };
15931593 }
15941594
1595 fn parse(rc: *ResolvConf, br: *std.io.BufferedReader) !void {
1595 fn parse(rc: *ResolvConf, br: *std.io.Reader) !void {
15961596 const gpa = rc.gpa;
15971597 while (br.takeSentinel('\n')) |line_with_comment| {
15981598 const line = line: {
lib/std/process/Child.zig+5-5
......@@ -348,15 +348,15 @@ pub const RunResult = struct {
348348 stderr: []u8,
349349};
350350
351fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), br: *std.io.BufferedReader) !void {
352 assert(br.seek == 0);
351fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), r: *std.io.Reader) !void {
352 assert(r.seek == 0);
353353 if (list.capacity == 0) {
354354 list.* = .{
355 .items = br.bufferContents(),
356 .capacity = br.buffer.len,
355 .items = r.bufferContents(),
356 .capacity = r.buffer.len,
357357 };
358358 } else {
359 try list.appendSlice(allocator, br.bufferContents());
359 try list.appendSlice(allocator, r.bufferContents());
360360 }
361361}
362362
lib/std/tar.zig+15-15
......@@ -302,7 +302,7 @@ pub const FileKind = enum {
302302
303303/// Iterator over entries in the tar file represented by reader.
304304pub const Iterator = struct {
305 reader: *std.io.BufferedReader,
305 reader: *std.io.Reader,
306306 diagnostics: ?*Diagnostics = null,
307307
308308 // buffers for heeader and file attributes
......@@ -328,7 +328,7 @@ pub const Iterator = struct {
328328
329329 /// Iterates over files in tar archive.
330330 /// `next` returns each file in tar archive.
331 pub fn init(reader: *std.io.BufferedReader, options: Options) Iterator {
331 pub fn init(reader: *std.io.Reader, options: Options) Iterator {
332332 return .{
333333 .reader = reader,
334334 .diagnostics = options.diagnostics,
......@@ -345,7 +345,7 @@ pub const Iterator = struct {
345345 kind: FileKind = .file,
346346
347347 unread_bytes: *u64,
348 parent_reader: *std.io.BufferedReader,
348 parent_reader: *std.io.Reader,
349349
350350 pub fn reader(self: *File) std.io.Reader {
351351 return .{
......@@ -537,14 +537,14 @@ const pax_max_size_attr_len = 64;
537537
538538pub const PaxIterator = struct {
539539 size: usize, // cumulative size of all pax attributes
540 reader: *std.io.BufferedReader,
540 reader: *std.io.Reader,
541541
542542 const Self = @This();
543543
544544 const Attribute = struct {
545545 kind: PaxAttributeKind,
546546 len: usize, // length of the attribute value
547 reader: *std.io.BufferedReader, // reader positioned at value start
547 reader: *std.io.Reader, // reader positioned at value start
548548
549549 // Copies pax attribute value into destination buffer.
550550 // Must be called with destination buffer of size at least Attribute.len.
......@@ -611,13 +611,13 @@ pub const PaxIterator = struct {
611611 }
612612
613613 // Checks that each record ends with new line.
614 fn validateAttributeEnding(reader: *std.io.BufferedReader) !void {
614 fn validateAttributeEnding(reader: *std.io.Reader) !void {
615615 if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd;
616616 }
617617};
618618
619619/// Saves tar file content to the file systems.
620pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.BufferedReader, options: PipeOptions) !void {
620pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.Reader, options: PipeOptions) !void {
621621 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
622622 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
623623 var iter: Iterator = .init(reader, .{
......@@ -818,7 +818,7 @@ test PaxIterator {
818818 var buffer: [1024]u8 = undefined;
819819
820820 outer: for (cases) |case| {
821 var br: std.io.BufferedReader = undefined;
821 var br: std.io.Reader = undefined;
822822 br.initFixed(case.data);
823823 var iter: PaxIterator = .init(&br, case.data.len);
824824
......@@ -955,7 +955,7 @@ test Iterator {
955955 // example/empty/
956956
957957 const data = @embedFile("tar/testdata/example.tar");
958 var br: std.io.BufferedReader = undefined;
958 var br: std.io.Reader = undefined;
959959 br.initFixed(data);
960960
961961 // User provided buffers to the iterator
......@@ -1015,7 +1015,7 @@ test pipeToFileSystem {
10151015 // example/empty/
10161016
10171017 const data = @embedFile("tar/testdata/example.tar");
1018 var br: std.io.BufferedReader = undefined;
1018 var br: std.io.Reader = undefined;
10191019 br.initFixed(data);
10201020
10211021 var tmp = testing.tmpDir(.{ .no_follow = true });
......@@ -1047,7 +1047,7 @@ test pipeToFileSystem {
10471047
10481048test "pipeToFileSystem root_dir" {
10491049 const data = @embedFile("tar/testdata/example.tar");
1050 var br: std.io.BufferedReader = undefined;
1050 var br: std.io.Reader = undefined;
10511051 br.initFixed(data);
10521052
10531053 // with strip_components = 1
......@@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" {
10961096
10971097test "findRoot with single file archive" {
10981098 const data = @embedFile("tar/testdata/22752.tar");
1099 var br: std.io.BufferedReader = undefined;
1099 var br: std.io.Reader = undefined;
11001100 br.initFixed(data);
11011101
11021102 var tmp = testing.tmpDir(.{});
......@@ -1111,7 +1111,7 @@ test "findRoot with single file archive" {
11111111
11121112test "findRoot without explicit root dir" {
11131113 const data = @embedFile("tar/testdata/19820.tar");
1114 var br: std.io.BufferedReader = undefined;
1114 var br: std.io.Reader = undefined;
11151115 br.initFixed(data);
11161116
11171117 var tmp = testing.tmpDir(.{});
......@@ -1126,7 +1126,7 @@ test "findRoot without explicit root dir" {
11261126
11271127test "pipeToFileSystem strip_components" {
11281128 const data = @embedFile("tar/testdata/example.tar");
1129 var br: std.io.BufferedReader = undefined;
1129 var br: std.io.Reader = undefined;
11301130 br.initFixed(data);
11311131
11321132 var tmp = testing.tmpDir(.{ .no_follow = true });
......@@ -1188,7 +1188,7 @@ test "executable bit" {
11881188 const data = @embedFile("tar/testdata/example.tar");
11891189
11901190 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {
1191 var br: std.io.BufferedReader = undefined;
1191 var br: std.io.Reader = undefined;
11921192 br.initFixed(data);
11931193
11941194 var tmp = testing.tmpDir(.{ .no_follow = true });
lib/std/tar/Writer.zig+4-4
......@@ -67,7 +67,7 @@ pub fn writeFileStream(
6767 w: *Writer,
6868 sub_path: []const u8,
6969 size: usize,
70 reader: *std.io.BufferedReader,
70 reader: *std.io.Reader,
7171 options: Options,
7272) std.io.Reader.StreamError!void {
7373 try w.writeHeader(.regular, sub_path, "", @intCast(size), options);
......@@ -441,7 +441,7 @@ test "write files" {
441441 for (files) |file|
442442 try wrt.writeFileBytes(file.path, file.content, .{});
443443
444 var input: std.io.BufferedReader = undefined;
444 var input: std.io.Reader = undefined;
445445 input.initFixed(output.getWritten());
446446 var iter = std.tar.iterator(&input, .{
447447 .file_name_buffer = &file_name_buffer,
......@@ -476,12 +476,12 @@ test "write files" {
476476 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };
477477 defer output.deinit();
478478 for (files) |file| {
479 var content: std.io.BufferedReader = undefined;
479 var content: std.io.Reader = undefined;
480480 content.initFixed(file.content);
481481 try wrt.writeFileStream(file.path, file.content.len, &content, .{});
482482 }
483483
484 var input: std.io.BufferedReader = undefined;
484 var input: std.io.Reader = undefined;
485485 input.initFixed(output.getWritten());
486486 var iter = std.tar.iterator(&input, .{
487487 .file_name_buffer = &file_name_buffer,
lib/std/tar/test.zig+9-14
......@@ -346,8 +346,7 @@ test "run test cases" {
346346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
347347
348348 for (cases) |case| {
349 var br: std.io.BufferedReader = undefined;
350 br.initFixed(case.data);
349 var br: std.io.Reader = .fixed(case.data);
351350 var iter = tar.iterator(&br, .{
352351 .file_name_buffer = &file_name_buffer,
353352 .link_name_buffer = &link_name_buffer,
......@@ -391,8 +390,7 @@ test "pax/gnu long names with small buffer" {
391390 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };
392391
393392 for (long_name_cases) |case| {
394 var br: std.io.BufferedReader = undefined;
395 br.initFixed(case.data);
393 var br: std.io.Reader = .fixed(case.data);
396394 var iter = tar.iterator(&br, .{
397395 .file_name_buffer = &min_file_name_buffer,
398396 .link_name_buffer = &min_link_name_buffer,
......@@ -413,8 +411,7 @@ test "insufficient buffer in Header name filed" {
413411 var min_file_name_buffer: [9]u8 = undefined;
414412 var min_link_name_buffer: [100]u8 = undefined;
415413
416 var br: std.io.BufferedReader = undefined;
417 br.initFixed(cases[0].data);
414 var br: std.io.Reader = .fixed(cases[0].data);
418415 var iter = tar.iterator(&br, .{
419416 .file_name_buffer = &min_file_name_buffer,
420417 .link_name_buffer = &min_link_name_buffer,
......@@ -469,22 +466,21 @@ test "should not overwrite existing file" {
469466 // This ensures that file is not overwritten.
470467 //
471468 const data = @embedFile("testdata/overwrite_file.tar");
472 var br: std.io.BufferedReader = undefined;
473 br.initFixed(data);
469 var r: std.io.Reader = .fixed(data);
474470
475471 // Unpack with strip_components = 1 should fail
476472 var root = std.testing.tmpDir(.{});
477473 defer root.cleanup();
478474 try testing.expectError(
479475 error.PathAlreadyExists,
480 tar.pipeToFileSystem(root.dir, &br, .{ .mode_mode = .ignore, .strip_components = 1 }),
476 tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }),
481477 );
482478
483479 // Unpack with strip_components = 0 should pass
484 br.initFixed(data);
480 r = .fixed(data);
485481 var root2 = std.testing.tmpDir(.{});
486482 defer root2.cleanup();
487 try tar.pipeToFileSystem(root2.dir, &br, .{ .mode_mode = .ignore, .strip_components = 0 });
483 try tar.pipeToFileSystem(root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 });
488484}
489485
490486test "case sensitivity" {
......@@ -498,13 +494,12 @@ test "case sensitivity" {
498494 // 18089/alacritty/Darkermatrix.yml
499495 //
500496 const data = @embedFile("testdata/18089.tar");
501 var br: std.io.BufferedReader = undefined;
502 br.initFixed(data);
497 var r: std.io.Reader = .fixed(data);
503498
504499 var root = std.testing.tmpDir(.{});
505500 defer root.cleanup();
506501
507 tar.pipeToFileSystem(root.dir, &br, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
502 tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
508503 // on case insensitive fs we fail on overwrite existing file
509504 try testing.expectEqual(error.PathAlreadyExists, err);
510505 return;
lib/std/tz.zig+4-4
......@@ -54,7 +54,7 @@ pub const Tz = struct {
5454 },
5555 };
5656
57 pub fn parse(allocator: std.mem.Allocator, reader: *std.io.BufferedReader) !Tz {
57 pub fn parse(allocator: std.mem.Allocator, reader: *std.io.Reader) !Tz {
5858 var legacy_header = try reader.takeStruct(Header);
5959 if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader;
6060 if (legacy_header.version != 0 and legacy_header.version != '2' and legacy_header.version != '3') return error.BadVersion;
......@@ -215,7 +215,7 @@ pub const Tz = struct {
215215
216216test "slim" {
217217 const data = @embedFile("tz/asia_tokyo.tzif");
218 var in_stream: std.io.BufferedReader = undefined;
218 var in_stream: std.io.Reader = undefined;
219219 in_stream.initFixed(data);
220220
221221 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
......@@ -229,7 +229,7 @@ test "slim" {
229229
230230test "fat" {
231231 const data = @embedFile("tz/antarctica_davis.tzif");
232 var in_stream: std.io.BufferedReader = undefined;
232 var in_stream: std.io.Reader = undefined;
233233 in_stream.initFixed(data);
234234
235235 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
......@@ -243,7 +243,7 @@ test "fat" {
243243test "legacy" {
244244 // Taken from Slackware 8.0, from 2001
245245 const data = @embedFile("tz/europe_vatican.tzif");
246 var in_stream: std.io.BufferedReader = undefined;
246 var in_stream: std.io.Reader = undefined;
247247 in_stream.initFixed(data);
248248
249249 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
lib/std/zig/Server.zig+2-2
......@@ -1,4 +1,4 @@
1in: *std.io.BufferedReader,
1in: *std.io.Reader,
22out: *std.io.BufferedWriter,
33
44pub const Message = struct {
......@@ -93,7 +93,7 @@ pub const Message = struct {
9393};
9494
9595pub const Options = struct {
96 in: *std.io.BufferedReader,
96 in: *std.io.Reader,
9797 out: *std.io.BufferedWriter,
9898 zig_version: []const u8,
9999};
lib/std/zig/llvm/BitcodeReader.zig+7-7
......@@ -1,6 +1,6 @@
11allocator: std.mem.Allocator,
22record_arena: std.heap.ArenaAllocator.State,
3br: *std.io.BufferedReader,
3reader: *std.io.Reader,
44keep_names: bool,
55bit_buffer: u32,
66bit_offset: u5,
......@@ -93,14 +93,14 @@ pub const Record = struct {
9393};
9494
9595pub const InitOptions = struct {
96 br: *std.io.BufferedReader,
96 reader: *std.io.Reader,
9797 keep_names: bool = false,
9898};
9999pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
100100 return .{
101101 .allocator = allocator,
102102 .record_arena = .{},
103 .br = options.br,
103 .reader = options.reader,
104104 .keep_names = options.keep_names,
105105 .bit_buffer = 0,
106106 .bit_offset = 0,
......@@ -172,7 +172,7 @@ pub fn next(bc: *BitcodeReader) !?Item {
172172
173173pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {
174174 assert(bc.bit_offset == 0);
175 try bc.br.discard(4 * @as(u34, block.len));
175 try bc.reader.discard(4 * @as(u34, block.len));
176176 try bc.endBlock();
177177}
178178
......@@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void {
371371
372372fn read32Bits(bc: *BitcodeReader) !u32 {
373373 assert(bc.bit_offset == 0);
374 return bc.br.takeInt(u32, .little);
374 return bc.reader.takeInt(u32, .little);
375375}
376376
377377fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {
378378 assert(bc.bit_offset == 0);
379 try bc.br.read(bytes);
379 try bc.reader.read(bytes);
380380
381381 const trailing_bytes = bytes.len % 4;
382382 if (trailing_bytes > 0) {
383383 var bit_buffer: [4]u8 = @splat(0);
384 try bc.br.read(bit_buffer[trailing_bytes..]);
384 try bc.reader.read(bit_buffer[trailing_bytes..]);
385385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);
386386 bc.bit_offset = @intCast(8 * trailing_bytes);
387387 }
lib/std/zig/system/linux.zig+2-3
......@@ -342,9 +342,8 @@ fn testParser(
342342 expected_model: *const Target.Cpu.Model,
343343 input: []const u8,
344344) !void {
345 var br: std.io.BufferedReader = undefined;
346 br.initFixed(@constCast(input));
347 const result = try parser.parse(arch, &br);
345 var r: std.io.Reader = .fixed(input);
346 const result = try parser.parse(arch, &r);
348347 try testing.expectEqual(expected_model, result.?.model);
349348 try testing.expect(expected_model.features.eql(result.?.features));
350349}
lib/std/zip.zig+3-3
......@@ -161,14 +161,14 @@ pub const EndRecord = extern struct {
161161
162162pub const Decompress = union {
163163 inflate: std.compress.flate.Decompress,
164 store: *std.io.BufferedReader,
164 store: *std.io.Reader,
165165
166166 fn readable(
167167 d: *Decompress,
168 reader: *std.io.BufferedReader,
168 reader: *std.io.Reader,
169169 method: CompressionMethod,
170170 buffer: []u8,
171 ) std.io.BufferedReader {
171 ) std.io.Reader {
172172 switch (method) {
173173 .store => {
174174 d.* = .{ .store = reader };
lib/std/zip/test.zig+2-2
......@@ -51,7 +51,7 @@ const FileStore = struct {
5151 uncompressed_size: usize,
5252};
5353
54fn makeZip(file_writer: *std.fs.File.Writer, files: []const File, options: WriteZipOptions) !std.io.BufferedReader {
54fn makeZip(file_writer: *std.fs.File.Writer, files: []const File, options: WriteZipOptions) !std.io.Reader {
5555 const store = try std.testing.allocator.alloc(FileStore, files.len);
5656 defer std.testing.allocator.free(store);
5757 return makeZipWithStore(file_writer, files, options, store);
......@@ -198,7 +198,7 @@ const Zipper = struct {
198198 },
199199 .deflate => {
200200 const offset = writer.count;
201 var br: std.io.BufferedReader = undefined;
201 var br: std.io.Reader = undefined;
202202 br.initFixed(@constCast(opt.content));
203203 var compress: std.compress.flate.Compress = .init(&br, .{});
204204 var compress_br = compress.readable(&.{});
src/Compilation.zig+2-3
......@@ -1076,9 +1076,8 @@ pub const CObject = struct {
10761076 var buffer: [1024]u8 = undefined;
10771077 const file = try std.fs.cwd().openFile(path, .{});
10781078 defer file.close();
1079 var br: std.io.BufferedReader = undefined;
1080 br.init(file.reader(), &buffer);
1081 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .br = &br });
1079 var file_reader = file.reader(&buffer);
1080 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });
10821081 defer bc.deinit();
10831082
10841083 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;
src/Package/Fetch/git.zig+9-9
......@@ -79,7 +79,7 @@ pub const Oid = union(Format) {
7979 };
8080 }
8181
82 pub fn readBytes(oid_format: Format, reader: *std.io.BufferedReader) std.io.Reader.Error!Oid {
82 pub fn readBytes(oid_format: Format, reader: *std.io.Reader) std.io.Reader.Error!Oid {
8383 return switch (oid_format) {
8484 .sha1 => {
8585 var result: Oid = .{ .sha1 = undefined };
......@@ -593,7 +593,7 @@ const Packet = union(enum) {
593593 const max_data_length = 65516;
594594
595595 /// Reads a packet in pkt-line format.
596 fn read(reader: *std.io.BufferedReader, buf: *[max_data_length]u8) !Packet {
596 fn read(reader: *std.io.Reader, buf: *[max_data_length]u8) !Packet {
597597 const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket;
598598 switch (length) {
599599 0 => return .flush,
......@@ -1107,7 +1107,7 @@ const PackHeader = struct {
11071107 const signature = "PACK";
11081108 const supported_version = 2;
11091109
1110 fn read(reader: *std.io.BufferedReader) !PackHeader {
1110 fn read(reader: *std.io.Reader) !PackHeader {
11111111 const actual_signature = try reader.take(4);
11121112 if (!mem.eql(u8, actual_signature, signature)) return error.InvalidHeader;
11131113 const version = try reader.takeInt(u32, .big);
......@@ -1161,7 +1161,7 @@ const EntryHeader = union(Type) {
11611161 };
11621162 }
11631163
1164 fn read(format: Oid.Format, reader: *std.io.BufferedReader) !EntryHeader {
1164 fn read(format: Oid.Format, reader: *std.io.Reader) !EntryHeader {
11651165 const InitialByte = packed struct { len: u4, type: u3, has_next: bool };
11661166 const initial: InitialByte = @bitCast(try reader.takeByte());
11671167 const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0;
......@@ -1187,7 +1187,7 @@ const EntryHeader = union(Type) {
11871187 }
11881188};
11891189
1190fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {
1190fn readSizeVarInt(r: *std.io.Reader) !u64 {
11911191 const Byte = packed struct { value: u7, has_next: bool };
11921192 var b: Byte = @bitCast(try r.takeByte());
11931193 var value: u64 = b.value;
......@@ -1200,7 +1200,7 @@ fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {
12001200 return value;
12011201}
12021202
1203fn readOffsetVarInt(r: *std.io.BufferedReader) !u64 {
1203fn readOffsetVarInt(r: *std.io.Reader) !u64 {
12041204 const Byte = packed struct { value: u7, has_next: bool };
12051205 var b: Byte = @bitCast(try r.takeByte());
12061206 var value: u64 = b.value;
......@@ -1219,7 +1219,7 @@ const IndexHeader = struct {
12191219 const supported_version = 2;
12201220 const size = 4 + 4 + @sizeOf([256]u32);
12211221
1222 fn read(index_header: *IndexHeader, br: *std.io.BufferedReader) !void {
1222 fn read(index_header: *IndexHeader, br: *std.io.Reader) !void {
12231223 const sig = try br.take(4);
12241224 if (!mem.eql(u8, sig, signature)) return error.InvalidHeader;
12251225 const version = try br.takeInt(u32, .big);
......@@ -1493,7 +1493,7 @@ fn resolveDeltaChain(
14931493}
14941494
14951495/// Reads the complete contents of an object from `reader`.
1496fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u8 {
1496fn readObjectRaw(gpa: Allocator, reader: *std.io.Reader, size: u64) ![]u8 {
14971497 const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge;
14981498 var decompress: zlib.Decompressor = .init(reader);
14991499 var buffer: std.ArrayListUnmanaged(u8) = .empty;
......@@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u
15051505
15061506/// The format of the delta data is documented in
15071507/// [pack-format](https://git-scm.com/docs/pack-format).
1508fn expandDelta(base_object: []const u8, delta_reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
1508fn expandDelta(base_object: []const u8, delta_reader: *std.io.Reader, writer: *std.io.BufferedWriter) !void {
15091509 var base_offset: u32 = 0;
15101510 while (true) {
15111511 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.takeByte() catch |e| switch (e) {
src/Zcu.zig+2-2
......@@ -2828,7 +2828,7 @@ pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
28282828 };
28292829}
28302830
2831pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *std.io.BufferedReader) !Zir {
2831pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *std.io.Reader) !Zir {
28322832 var instructions: std.MultiArrayList(Zir.Inst) = .{};
28332833 errdefer instructions.deinit(gpa);
28342834
......@@ -2947,7 +2947,7 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir
29472947 };
29482948}
29492949
2950pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_br: *std.io.BufferedReader) !Zoir {
2950pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_br: *std.io.Reader) !Zoir {
29512951 var zoir: Zoir = .{
29522952 .nodes = .empty,
29532953 .extra = &.{},
src/arch/x86_64/Disassembler.zig+3-4
......@@ -372,7 +372,7 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi
372372}
373373
374374fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
375 var br: std.io.BufferedReader = undefined;
375 var br: std.io.Reader = undefined;
376376 br.initFixed(dis.code[dis.pos..]);
377377 defer dis.pos += br.seek;
378378 return switch (kind) {
......@@ -388,7 +388,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
388388}
389389
390390fn parseOffset(dis: *Disassembler) !u64 {
391 var br: std.io.BufferedReader = undefined;
391 var br: std.io.Reader = undefined;
392392 br.initFixed(dis.code[dis.pos..]);
393393 defer dis.pos += br.seek;
394394 return br.takeInt(u64, .little);
......@@ -464,8 +464,7 @@ fn parseSibByte(dis: *Disassembler) !Sib {
464464}
465465
466466fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 {
467 var br: std.io.BufferedReader = undefined;
468 br.initFixed(dis.code[dis.pos..]);
467 var br: std.io.Reader = .fixed(dis.code[dis.pos..]);
469468 defer dis.pos += br.seek;
470469 if (sib) |info| {
471470 if (info.base == 0b101 and modrm.mod == 0) {
src/libs/glibc.zig+1-2
......@@ -793,8 +793,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
793793 // twice, which causes a "duplicate symbol" assembler error.
794794 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);
795795
796 var inc_br: std.io.BufferedReader = undefined;
797 inc_br.initFixed(metadata.inclusions);
796 var inc_br: std.io.Reader = .fixed(metadata.inclusions);
798797
799798 const fn_inclusions_len = try inc_br.takeInt(u16, .little);
800799
src/link/Dwarf.zig+2-3
......@@ -142,8 +142,7 @@ const DebugInfo = struct {
142142 &abbrev_code_buf,
143143 debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,
144144 ) != abbrev_code_buf.len) return error.InputOutput;
145 var abbrev_code_br: std.io.BufferedReader = undefined;
146 abbrev_code_br.initFixed(&abbrev_code_buf);
145 var abbrev_code_br: std.io.Reader = .fixed(&abbrev_code_buf);
147146 return @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
148147 }
149148
......@@ -2757,7 +2756,7 @@ fn finishWipNavFuncInner(
27572756 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
27582757 } else {
27592758 const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes];
2760 var abbrev_code_br: std.io.BufferedReader = undefined;
2759 var abbrev_code_br: std.io.Reader = undefined;
27612760 abbrev_code_br.initFixed(abbrev_code_buf);
27622761 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
27632762 std.leb.writeUnsignedFixed(
src/link/Elf/Object.zig+5-6
......@@ -1192,18 +1192,17 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
11921192 const atom_ptr = self.atom(atom_index).?;
11931193 const shdr = atom_ptr.inputShdr(elf_file);
11941194 const handle = elf_file.fileHandle(self.file_handle);
1195 var br: std.io.BufferedReader = undefined;
1196 br.initFixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index));
1197 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(br.storageBuffer());
1195 var r: std.io.Reader = .fixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index));
1196 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(r.storageBuffer());
11981197
11991198 if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
1200 const chdr = (try br.takeStruct(elf.Elf64_Chdr)).*;
1199 const chdr = (try r.takeStruct(elf.Elf64_Chdr)).*;
12011200 switch (chdr.ch_type) {
12021201 .ZLIB => {
12031202 var bw: std.io.BufferedWriter = undefined;
12041203 bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));
12051204 errdefer gpa.free(bw.buffer);
1206 try std.compress.zlib.decompress(&br, &bw);
1205 try std.compress.zlib.decompress(&r, &bw);
12071206 if (bw.end != bw.buffer.len) return error.InputOutput;
12081207 return bw.buffer;
12091208 },
......@@ -1211,7 +1210,7 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
12111210 }
12121211 }
12131212
1214 return br.storageBuffer();
1213 return r.storageBuffer();
12151214}
12161215
12171216fn locals(self: *Object) []Symbol {
src/link/Elf/eh_frame.zig+6-6
......@@ -187,7 +187,7 @@ pub const Cie = struct {
187187};
188188
189189pub const Iterator = struct {
190 br: std.io.BufferedReader,
190 reader: std.io.Reader,
191191
192192 pub const Record = struct {
193193 tag: enum { fde, cie },
......@@ -196,18 +196,18 @@ pub const Iterator = struct {
196196 };
197197
198198 pub fn next(it: *Iterator) !?Record {
199 if (it.br.seek >= it.br.storageBuffer().len) return null;
199 if (it.reader.seek >= it.reader.storageBuffer().len) return null;
200200
201 const size = try it.br.takeInt(u32, .little);
201 const size = try it.reader.takeInt(u32, .little);
202202 if (size == 0xFFFFFFFF) @panic("DWARF CFI is 32bit on macOS");
203203
204 const id = try it.br.takeInt(u32, .little);
204 const id = try it.reader.takeInt(u32, .little);
205205 const record: Record = .{
206206 .tag = if (id == 0) .cie else .fde,
207 .offset = it.br.seek,
207 .offset = it.reader.seek,
208208 .size = size,
209209 };
210 try it.br.discard(size);
210 try it.reader.discard(size);
211211
212212 return record;
213213 }
src/link/MachO/Dwarf.zig+6-8
......@@ -273,10 +273,9 @@ pub const InfoReader = struct {
273273 }
274274
275275 pub fn readLeb128(p: *InfoReader, comptime Type: type) !Type {
276 var br: std.io.BufferedReader = undefined;
277 br.initFixed(p.bytes()[p.pos..]);
278 defer p.pos += br.seek;
279 return br.takeLeb128(Type);
276 var r: std.io.Reader = .fixed(p.bytes()[p.pos..]);
277 defer p.pos += r.seek;
278 return r.takeLeb128(Type);
280279 }
281280
282281 pub fn seekTo(p: *InfoReader, off: u64) !void {
......@@ -331,10 +330,9 @@ pub const AbbrevReader = struct {
331330 }
332331
333332 pub fn readLeb128(p: *AbbrevReader, comptime Type: type) !Type {
334 var br: std.io.BufferedReader = undefined;
335 br.initFixed(p.bytes()[p.pos..]);
336 defer p.pos += br.seek;
337 return br.takeLeb128(Type);
333 var r: std.io.Reader = .fixed(p.bytes()[p.pos..]);
334 defer p.pos += r.seek;
335 return r.takeLeb128(Type);
338336 }
339337
340338 pub fn seekTo(p: *AbbrevReader, off: u64) !void {
src/link/MachO/Dylib.zig+3-4
......@@ -167,7 +167,7 @@ pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Ex
167167
168168fn parseTrieNode(
169169 self: *Dylib,
170 br: *std.io.BufferedReader,
170 br: *std.io.Reader,
171171 allocator: Allocator,
172172 arena: Allocator,
173173 prefix: []const u8,
......@@ -216,9 +216,8 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {
216216 var arena = std.heap.ArenaAllocator.init(gpa);
217217 defer arena.deinit();
218218
219 var br: std.io.BufferedReader = undefined;
220 br.initFixed(data);
221 try self.parseTrieNode(&br, gpa, arena.allocator(), "");
219 var r: std.io.Reader = .fixed(data);
220 try self.parseTrieNode(&r, gpa, arena.allocator(), "");
222221}
223222
224223fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
src/link/MachO/eh_frame.zig+13-14
......@@ -12,34 +12,33 @@ pub const Cie = struct {
1212 const tracy = trace(@src());
1313 defer tracy.end();
1414
15 var br: std.io.BufferedReader = undefined;
16 br.initFixed(cie.getData(macho_file));
15 var r: std.io.Reader = .fixed(cie.getData(macho_file));
1716
18 try br.discard(9);
19 const aug = try br.takeSentinel(0);
17 try r.discard(9);
18 const aug = try r.takeSentinel(0);
2019 if (aug[0] != 'z') return; // TODO should we error out?
2120
22 _ = try br.takeLeb128(u64); // code alignment factor
23 _ = try br.takeLeb128(u64); // data alignment factor
24 _ = try br.takeLeb128(u64); // return address register
25 _ = try br.takeLeb128(u64); // augmentation data length
21 _ = try r.takeLeb128(u64); // code alignment factor
22 _ = try r.takeLeb128(u64); // data alignment factor
23 _ = try r.takeLeb128(u64); // return address register
24 _ = try r.takeLeb128(u64); // augmentation data length
2625
2726 for (aug[1..]) |ch| switch (ch) {
2827 'R' => {
29 const enc = try br.takeByte();
28 const enc = try r.takeByte();
3029 if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) {
3130 @panic("unexpected pointer encoding"); // TODO error
3231 }
3332 },
3433 'P' => {
35 const enc = try br.takeByte();
34 const enc = try r.takeByte();
3635 if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) {
3736 @panic("unexpected personality pointer encoding"); // TODO error
3837 }
39 _ = try br.takeInt(u32, .little); // personality pointer
38 _ = try r.takeInt(u32, .little); // personality pointer
4039 },
4140 'L' => {
42 const enc = try br.takeByte();
41 const enc = try r.takeByte();
4342 switch (enc & DW_EH_PE.type_mask) {
4443 DW_EH_PE.sdata4 => cie.lsda_size = .p32,
4544 DW_EH_PE.absptr => cie.lsda_size = .p64,
......@@ -143,7 +142,7 @@ pub const Fde = struct {
143142 const object = fde.getObject(macho_file);
144143 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];
145144
146 var br: std.io.BufferedReader = undefined;
145 var br: std.io.Reader = undefined;
147146 br.initFixed(fde.getData(macho_file));
148147
149148 try br.discard(4);
......@@ -267,7 +266,7 @@ pub const Fde = struct {
267266};
268267
269268pub const Iterator = struct {
270 br: std.io.BufferedReader,
269 br: std.io.Reader,
271270
272271 pub const Record = struct {
273272 tag: enum { fde, cie },
src/link/Wasm.zig+4-5
......@@ -2087,10 +2087,9 @@ pub const Expr = enum(u32) {
20872087 pub const end = @intFromEnum(std.wasm.Opcode.end);
20882088
20892089 pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {
2090 var br: std.io.BufferedReader = undefined;
2091 br.initFixed(wasm.string_bytes.items[@intFromEnum(index)..]);
2092 Object.skipInit(&br) catch unreachable;
2093 return br.storageBuffer()[0 .. br.seek - 1 :end];
2090 var r: std.io.Reader = .fixed(wasm.string_bytes.items[@intFromEnum(index)..]);
2091 Object.skipInit(&r) catch unreachable;
2092 return r.storageBuffer()[0 .. r.seek - 1 :end];
20942093 }
20952094};
20962095
......@@ -3038,7 +3037,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
30383037 const stat = try obj.file.stat();
30393038 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;
30403039
3041 var br: std.io.BufferedReader = undefined;
3040 var br: std.io.Reader = undefined;
30423041 br.initFixed(try gpa.alloc(u8, size));
30433042 defer gpa.free(br.storageBuffer());
30443043
src/link/Wasm/Archive.zig+2-4
......@@ -167,10 +167,8 @@ pub fn parseObject(
167167 };
168168
169169 const object_file_size = try header.parsedSize();
170 var br: std.io.BufferedReader = undefined;
171 br.initFixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]);
172
173 return Object.parse(wasm, &br, path, object_name, host_name, scratch_space, must_link, gc_sections);
170 var r: std.io.Reader = .fixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]);
171 return Object.parse(wasm, &r, path, object_name, host_name, scratch_space, must_link, gc_sections);
174172}
175173
176174const Archive = @This();
src/link/Wasm/Object.zig+5-5
......@@ -252,7 +252,7 @@ pub const ScratchSpace = struct {
252252
253253pub fn parse(
254254 wasm: *Wasm,
255 br: *std.io.BufferedReader,
255 br: *std.io.Reader,
256256 path: Path,
257257 archive_member_name: ?[]const u8,
258258 host_name: Wasm.OptionalString,
......@@ -1402,7 +1402,7 @@ pub fn parse(
14021402/// Based on the "features" custom section, parses it into a list of
14031403/// features that tell the linker what features were enabled and may be mandatory
14041404/// to be able to link.
1405fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) error{ OutOfMemory, LinkFailure }!Wasm.Feature.Set {
1405fn parseFeatures(wasm: *Wasm, br: *std.io.Reader, path: Path) error{ OutOfMemory, LinkFailure }!Wasm.Feature.Set {
14061406 const gpa = wasm.base.comp.gpa;
14071407 const diags = &wasm.base.comp.link_diags;
14081408 const features_len = try br.takeLeb128(u32);
......@@ -1430,7 +1430,7 @@ fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) error{ Out
14301430 return .fromString(try wasm.internString(@ptrCast(feature_buffer)));
14311431}
14321432
1433fn readLimits(br: *std.io.BufferedReader) std.io.Reader.Error!std.wasm.Limits {
1433fn readLimits(br: *std.io.Reader) std.io.Reader.Error!std.wasm.Limits {
14341434 const flags: std.wasm.Limits.Flags = @bitCast(try br.takeByte());
14351435 const min = try br.takeLeb128(u32);
14361436 const max = if (flags.has_max) try br.takeLeb128(u32) else 0;
......@@ -1441,13 +1441,13 @@ fn readLimits(br: *std.io.BufferedReader) std.io.Reader.Error!std.wasm.Limits {
14411441 };
14421442}
14431443
1444fn readInit(wasm: *Wasm, br: *std.io.BufferedReader) std.io.Reader.Error!Wasm.Expr {
1444fn readInit(wasm: *Wasm, br: *std.io.Reader) std.io.Reader.Error!Wasm.Expr {
14451445 const start = br.seek;
14461446 try skipInit(br); // one after the end opcode
14471447 return wasm.addExpr(br.storageBuffer()[start..br.seek]);
14481448}
14491449
1450pub fn skipInit(br: *std.io.BufferedReader) std.io.Reader.Error!void {
1450pub fn skipInit(br: *std.io.Reader) std.io.Reader.Error!void {
14511451 switch (try br.takeEnum(std.wasm.Opcode, .little)) {
14521452 .i32_const => _ = try br.takeLeb128(i32),
14531453 .i64_const => _ = try br.takeLeb128(i64),
src/link/riscv.zig+2-3
......@@ -13,9 +13,8 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.
1313 switch (op) {
1414 .set => try overwriteUleb(@intCast(addend), bw),
1515 .sub => {
16 var br: std.io.BufferedReader = undefined;
17 br.initFixed(try bw.writableArray(1));
18 const old_value = try br.takeLeb128(u64);
16 var r: std.io.Reader = .fixed(try bw.writableArray(1));
17 const old_value = try r.takeLeb128(u64);
1918 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);
2019 },
2120 }