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 {...@@ -1082,11 +1082,9 @@ const CorrespondingLines = struct {
1082 at_eof: bool = false,1082 at_eof: bool = false,
1083 span: SourceMappings.CorrespondingSpan,1083 span: SourceMappings.CorrespondingSpan,
1084 file: std.fs.File,1084 file: std.fs.File,
1085 buffered_reader: BufferedReaderType,1085 buffered_reader: *std.io.Reader,
1086 code_page: SupportedCodePage,1086 code_page: SupportedCodePage,
10871087
1088 const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.Reader);
1089
1090 pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines {1088 pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines {
1091 // We don't do line comparison for this error, so don't print the note if the line1089 // We don't do line comparison for this error, so don't print the note if the line
1092 // number is different1090 // number is different
...@@ -1105,7 +1103,7 @@ const CorrespondingLines = struct {...@@ -1105,7 +1103,7 @@ const CorrespondingLines = struct {
1105 .buffered_reader = undefined,1103 .buffered_reader = undefined,
1106 .code_page = err_details.code_page,1104 .code_page = err_details.code_page,
1107 };1105 };
1108 corresponding_lines.buffered_reader = BufferedReaderType{1106 corresponding_lines.buffered_reader = .{
1109 .unbuffered_reader = corresponding_lines.file.reader(),1107 .unbuffered_reader = corresponding_lines.file.reader(),
1110 };1108 };
1111 errdefer corresponding_lines.deinit();1109 errdefer corresponding_lines.deinit();
lib/compiler/std-docs.zig+1-1
...@@ -390,7 +390,7 @@ fn receiveWasmMessage(...@@ -390,7 +390,7 @@ fn receiveWasmMessage(
390 gpa: Allocator,390 gpa: Allocator,
391 arena: Allocator,391 arena: Allocator,
392 context: *Context,392 context: *Context,
393 br: *std.io.BufferedReader,393 br: *std.io.Reader,
394 result: *?Cache.Path,394 result: *?Cache.Path,
395 result_error_bundle: *std.zig.ErrorBundle,395 result_error_bundle: *std.zig.ErrorBundle,
396) !void {396) !void {
lib/docs/wasm/main.zig+1-2
...@@ -778,8 +778,7 @@ export fn decl_type_html(decl_index: Decl.Index) String {...@@ -778,8 +778,7 @@ export fn decl_type_html(decl_index: Decl.Index) String {
778const Oom = error{OutOfMemory};778const Oom = error{OutOfMemory};
779779
780fn unpackInner(tar_bytes: []u8) !void {780fn unpackInner(tar_bytes: []u8) !void {
781 var br: std.io.BufferedReader = undefined;781 var br: std.io.Reader = .fixed(tar_bytes);
782 br.initFixed(tar_bytes);
783 var file_name_buffer: [1024]u8 = undefined;782 var file_name_buffer: [1024]u8 = undefined;
784 var link_name_buffer: [1024]u8 = undefined;783 var link_name_buffer: [1024]u8 = undefined;
785 var it = std.tar.Iterator.init(&br, .{784 var it = std.tar.Iterator.init(&br, .{
lib/std/Build/Step/CheckObject.zig+19-20
...@@ -1238,8 +1238,7 @@ const MachODumper = struct {...@@ -1238,8 +1238,7 @@ const MachODumper = struct {
1238 }1238 }
12391239
1240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {1240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1241 var br: std.io.BufferedReader = undefined;1241 var br: std.io.Reader = .fixed(data);
1242 br.initFixed(@constCast(data));
12431242
1244 var seg_id: ?u8 = null;1243 var seg_id: ?u8 = null;
1245 var offset: u64 = 0;1244 var offset: u64 = 0;
...@@ -1349,7 +1348,7 @@ const MachODumper = struct {...@@ -1349,7 +1348,7 @@ const MachODumper = struct {
1349 }1348 }
13501349
1351 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {1350 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;
1353 br.initFixed(@constCast(data));1352 br.initFixed(@constCast(data));
13541353
1355 var seg_id: ?u8 = null;1354 var seg_id: ?u8 = null;
...@@ -1447,7 +1446,7 @@ const MachODumper = struct {...@@ -1447,7 +1446,7 @@ const MachODumper = struct {
1447 defer arena.deinit();1446 defer arena.deinit();
14481447
1449 var exports: std.ArrayList(Export) = .init(arena.allocator());1448 var exports: std.ArrayList(Export) = .init(arena.allocator());
1450 var br: std.io.BufferedReader = undefined;1449 var br: std.io.Reader = undefined;
1451 br.initFixed(@constCast(data));1450 br.initFixed(@constCast(data));
1452 try parseTrieNode(arena.allocator(), &br, "", &exports);1451 try parseTrieNode(arena.allocator(), &br, "", &exports);
14531452
...@@ -1517,7 +1516,7 @@ const MachODumper = struct {...@@ -1517,7 +1516,7 @@ const MachODumper = struct {
15171516
1518 fn parseTrieNode(1517 fn parseTrieNode(
1519 arena: Allocator,1518 arena: Allocator,
1520 br: *std.io.BufferedReader,1519 br: *std.io.Reader,
1521 prefix: []const u8,1520 prefix: []const u8,
1522 exports: *std.ArrayList(Export),1521 exports: *std.ArrayList(Export),
1523 ) !void {1522 ) !void {
...@@ -1705,7 +1704,7 @@ const ElfDumper = struct {...@@ -1705,7 +1704,7 @@ const ElfDumper = struct {
17051704
1706 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1705 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1707 const gpa = step.owner.allocator;1706 const gpa = step.owner.allocator;
1708 var br: std.io.BufferedReader = undefined;1707 var br: std.io.Reader = undefined;
1709 br.initFixed(@constCast(bytes));1708 br.initFixed(@constCast(bytes));
17101709
1711 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;1710 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
...@@ -1780,7 +1779,7 @@ const ElfDumper = struct {...@@ -1780,7 +1779,7 @@ const ElfDumper = struct {
1780 }1779 }
17811780
1782 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {1781 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;
1784 br.initFixed(@constCast(data));1783 br.initFixed(@constCast(data));
1785 const num = switch (ptr_width) {1784 const num = switch (ptr_width) {
1786 .p32 => try br.takeInt(u32, .big),1785 .p32 => try br.takeInt(u32, .big),
...@@ -1851,7 +1850,7 @@ const ElfDumper = struct {...@@ -1851,7 +1850,7 @@ const ElfDumper = struct {
18511850
1852 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1851 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1853 const gpa = step.owner.allocator;1852 const gpa = step.owner.allocator;
1854 var br: std.io.BufferedReader = undefined;1853 var br: std.io.Reader = undefined;
1855 br.initFixed(@constCast(bytes));1854 br.initFixed(@constCast(bytes));
18561855
1857 const hdr = try br.takeStruct(elf.Elf64_Ehdr);1856 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
...@@ -2354,7 +2353,7 @@ const WasmDumper = struct {...@@ -2354,7 +2353,7 @@ const WasmDumper = struct {
23542353
2355 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {2354 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
2356 const gpa = step.owner.allocator;2355 const gpa = step.owner.allocator;
2357 var br: std.io.BufferedReader = undefined;2356 var br: std.io.Reader = undefined;
2358 br.initFixed(@constCast(bytes));2357 br.initFixed(@constCast(bytes));
23592358
2360 const buf = try br.takeArray(8);2359 const buf = try br.takeArray(8);
...@@ -2376,10 +2375,10 @@ const WasmDumper = struct {...@@ -2376,10 +2375,10 @@ const WasmDumper = struct {
2376 fn parseAndDumpInner(2375 fn parseAndDumpInner(
2377 step: *Step,2376 step: *Step,
2378 check: Check,2377 check: Check,
2379 br: *std.io.BufferedReader,2378 br: *std.io.Reader,
2380 bw: *std.io.BufferedWriter,2379 bw: *std.io.BufferedWriter,
2381 ) !void {2380 ) !void {
2382 var section_br: std.io.BufferedReader = undefined;2381 var section_br: std.io.Reader = undefined;
2383 switch (check.kind) {2382 switch (check.kind) {
2384 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {2383 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2385 section_br.initFixed(try br.take(try br.takeLeb128(u32)));2384 section_br.initFixed(try br.take(try br.takeLeb128(u32)));
...@@ -2396,7 +2395,7 @@ const WasmDumper = struct {...@@ -2396,7 +2395,7 @@ const WasmDumper = struct {
2396 fn parseAndDumpSection(2395 fn parseAndDumpSection(
2397 step: *Step,2396 step: *Step,
2398 section: std.wasm.Section,2397 section: std.wasm.Section,
2399 br: *std.io.BufferedReader,2398 br: *std.io.Reader,
2400 bw: *std.io.BufferedWriter,2399 bw: *std.io.BufferedWriter,
2401 ) !void {2400 ) !void {
2402 try bw.print(2401 try bw.print(
...@@ -2445,7 +2444,7 @@ const WasmDumper = struct {...@@ -2445,7 +2444,7 @@ const WasmDumper = struct {
2445 }2444 }
2446 }2445 }
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 {
2449 switch (section) {2448 switch (section) {
2450 .type => {2449 .type => {
2451 var i: u32 = 0;2450 var i: u32 = 0;
...@@ -2576,7 +2575,7 @@ const WasmDumper = struct {...@@ -2576,7 +2575,7 @@ const WasmDumper = struct {
2576 }2575 }
2577 }2576 }
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 {
2580 const tag = br.takeEnum(E, .little) catch |err| switch (err) {2579 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2581 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),2580 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2582 else => |e| return e,2581 else => |e| return e,
...@@ -2585,7 +2584,7 @@ const WasmDumper = struct {...@@ -2585,7 +2584,7 @@ const WasmDumper = struct {
2585 return tag;2584 return tag;
2586 }2585 }
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 {
2589 const flags = try br.takeLeb128(u8);2588 const flags = try br.takeLeb128(u8);
2590 const min = try br.takeLeb128(u32);2589 const min = try br.takeLeb128(u32);
25912590
...@@ -2593,7 +2592,7 @@ const WasmDumper = struct {...@@ -2593,7 +2592,7 @@ const WasmDumper = struct {
2593 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});2592 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
2594 }2593 }
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 {
2597 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {2596 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2598 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),2597 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2599 else => |e| return e,2598 else => |e| return e,
...@@ -2613,8 +2612,8 @@ const WasmDumper = struct {...@@ -2613,8 +2612,8 @@ const WasmDumper = struct {
2613 }2612 }
26142613
2615 /// https://webassembly.github.io/spec/core/appendix/custom.html2614 /// https://webassembly.github.io/spec/core/appendix/custom.html
2616 fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {2615 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {
2617 var subsection_br: std.io.BufferedReader = undefined;2616 var subsection_br: std.io.Reader = undefined;
2618 while (br.seek < br.buffer.len) {2617 while (br.seek < br.buffer.len) {
2619 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {2618 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
2620 // The module name subsection ... consists of a single name2619 // The module name subsection ... consists of a single name
...@@ -2662,7 +2661,7 @@ const WasmDumper = struct {...@@ -2662,7 +2661,7 @@ const WasmDumper = struct {
2662 }2661 }
2663 }2662 }
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 {
2666 const field_count = try br.takeLeb128(u32);2665 const field_count = try br.takeLeb128(u32);
2667 try bw.print(2666 try bw.print(
2668 \\fields {d}2667 \\fields {d}
...@@ -2690,7 +2689,7 @@ const WasmDumper = struct {...@@ -2690,7 +2689,7 @@ const WasmDumper = struct {
2690 }2689 }
2691 }2690 }
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 {
2694 const feature_count = try br.takeLeb128(u32);2693 const feature_count = try br.takeLeb128(u32);
2695 try bw.print(2694 try bw.print(
2696 \\features {d}2695 \\features {d}
lib/std/coff.zig+6-8
...@@ -1087,10 +1087,9 @@ pub const Coff = struct {...@@ -1087,10 +1087,9 @@ pub const Coff = struct {
1087 const pe_pointer_offset = 0x3C;1087 const pe_pointer_offset = 0x3C;
1088 const pe_magic = "PE\x00\x00";1088 const pe_magic = "PE\x00\x00";
10891089
1090 var reader: std.io.BufferedReader = undefined;1090 var reader: std.io.Reader = .fixed(data[pe_pointer_offset..]);
1091 reader.initFixed(data[pe_pointer_offset..]);
1092 const coff_header_offset = try reader.readInt(u32, .little);1091 const coff_header_offset = try reader.readInt(u32, .little);
1093 reader.initFixed(data[coff_header_offset..]);1092 reader = .fixed(data[coff_header_offset..]);
1094 const magic = try reader.peek(4);1093 const magic = try reader.peek(4);
1095 const is_image = mem.eql(u8, pe_magic, magic);1094 const is_image = mem.eql(u8, pe_magic, magic);
10961095
...@@ -1121,16 +1120,15 @@ pub const Coff = struct {...@@ -1121,16 +1120,15 @@ pub const Coff = struct {
1121 if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null;1120 if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null;
11221121
1123 const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];1122 const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];
1124 var reader: std.io.BufferedReader = undefined;1123 var reader: std.io.Reader = .fixed(self.data);
1125 reader.initFixed(self.data);
11261124
1127 if (self.is_loaded) {1125 if (self.is_loaded) {
1128 reader.initFixed(self.data[debug_dir.virtual_address..]);1126 reader = .fixed(self.data[debug_dir.virtual_address..]);
1129 } else {1127 } else {
1130 // Find what section the debug_dir is in, in order to convert the RVA to a file offset1128 // Find what section the debug_dir is in, in order to convert the RVA to a file offset
1131 for (self.getSectionHeaders()) |*sect| {1129 for (self.getSectionHeaders()) |*sect| {
1132 if (debug_dir.virtual_address >= sect.virtual_address and debug_dir.virtual_address < sect.virtual_address + sect.virtual_size) {1130 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) ..]);
1134 break;1132 break;
1135 }1133 }
1136 } else return error.InvalidDebugDirectory;1134 } else return error.InvalidDebugDirectory;
...@@ -1144,7 +1142,7 @@ pub const Coff = struct {...@@ -1144,7 +1142,7 @@ pub const Coff = struct {
1144 const debug_dir_entry = try reader.takeStruct(DebugDirectoryEntry);1142 const debug_dir_entry = try reader.takeStruct(DebugDirectoryEntry);
1145 if (debug_dir_entry.type == .CODEVIEW) {1143 if (debug_dir_entry.type == .CODEVIEW) {
1146 const dir_offset = if (self.is_loaded) debug_dir_entry.address_of_raw_data else debug_dir_entry.pointer_to_raw_data;1144 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..]);
1148 break;1146 break;
1149 }1147 }
1150 } else return null;1148 } else return null;
lib/std/compress/flate.zig+22-44
...@@ -229,8 +229,7 @@ test "compress/decompress" {...@@ -229,8 +229,7 @@ test "compress/decompress" {
229229
230 // compress original stream to compressed stream230 // compress original stream to compressed stream
231 {231 {
232 var original: std.io.BufferedReader = undefined;232 var original: std.io.Reader = .fixed(data);
233 original.initFixed(@constCast(data));
234 var compressed: std.io.BufferedWriter = undefined;233 var compressed: std.io.BufferedWriter = undefined;
235 compressed.initFixed(&cmp_buf);234 compressed.initFixed(&cmp_buf);
236 var compress: Compress = .init(&original, .raw);235 var compress: Compress = .init(&original, .raw);
...@@ -246,8 +245,7 @@ test "compress/decompress" {...@@ -246,8 +245,7 @@ test "compress/decompress" {
246 }245 }
247 // decompress compressed stream to decompressed stream246 // decompress compressed stream to decompressed stream
248 {247 {
249 var compressed: std.io.BufferedReader = undefined;248 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
250 compressed.initFixed(cmp_buf[0..compressed_size]);
251 var decompressed: std.io.BufferedWriter = undefined;249 var decompressed: std.io.BufferedWriter = undefined;
252 decompressed.initFixed(&dcm_buf);250 decompressed.initFixed(&dcm_buf);
253 try Decompress.pump(container, &compressed, &decompressed);251 try Decompress.pump(container, &compressed, &decompressed);
...@@ -267,8 +265,7 @@ test "compress/decompress" {...@@ -267,8 +265,7 @@ test "compress/decompress" {
267 }265 }
268 // decompressor reader interface266 // decompressor reader interface
269 {267 {
270 var compressed: std.io.BufferedReader = undefined;268 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
271 compressed.initFixed(cmp_buf[0..compressed_size]);
272 var dcm = Decompress.pump(container, &compressed);269 var dcm = Decompress.pump(container, &compressed);
273 var dcm_rdr = dcm.reader();270 var dcm_rdr = dcm.reader();
274 const n = try dcm_rdr.readAll(&dcm_buf);271 const n = try dcm_rdr.readAll(&dcm_buf);
...@@ -287,8 +284,7 @@ test "compress/decompress" {...@@ -287,8 +284,7 @@ test "compress/decompress" {
287284
288 // compress original stream to compressed stream285 // compress original stream to compressed stream
289 {286 {
290 var original: std.io.BufferedReader = undefined;287 var original: std.io.Reader = .fixed(data);
291 original.initFixed(data);
292 var compressed: std.io.BufferedWriter = undefined;288 var compressed: std.io.BufferedWriter = undefined;
293 compressed.initFixed(&cmp_buf);289 compressed.initFixed(&cmp_buf);
294 var cmp = try Compress.Huffman.init(container, &compressed);290 var cmp = try Compress.Huffman.init(container, &compressed);
...@@ -303,8 +299,7 @@ test "compress/decompress" {...@@ -303,8 +299,7 @@ test "compress/decompress" {
303 }299 }
304 // decompress compressed stream to decompressed stream300 // decompress compressed stream to decompressed stream
305 {301 {
306 var compressed: std.io.BufferedReader = undefined;302 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
307 compressed.initFixed(cmp_buf[0..compressed_size]);
308 var decompressed: std.io.BufferedWriter = undefined;303 var decompressed: std.io.BufferedWriter = undefined;
309 decompressed.initFixed(&dcm_buf);304 decompressed.initFixed(&dcm_buf);
310 try Decompress.pump(container, &compressed, &decompressed);305 try Decompress.pump(container, &compressed, &decompressed);
...@@ -323,8 +318,7 @@ test "compress/decompress" {...@@ -323,8 +318,7 @@ test "compress/decompress" {
323318
324 // compress original stream to compressed stream319 // compress original stream to compressed stream
325 {320 {
326 var original: std.io.BufferedReader = undefined;321 var original: std.io.Reader = .fixed(data);
327 original.initFixed(data);
328 var compressed: std.io.BufferedWriter = undefined;322 var compressed: std.io.BufferedWriter = undefined;
329 compressed.initFixed(&cmp_buf);323 compressed.initFixed(&cmp_buf);
330 var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed);324 var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed);
...@@ -340,8 +334,7 @@ test "compress/decompress" {...@@ -340,8 +334,7 @@ test "compress/decompress" {
340 }334 }
341 // decompress compressed stream to decompressed stream335 // decompress compressed stream to decompressed stream
342 {336 {
343 var compressed: std.io.BufferedReader = undefined;337 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
344 compressed.initFixed(cmp_buf[0..compressed_size]);
345 var decompressed: std.io.BufferedWriter = undefined;338 var decompressed: std.io.BufferedWriter = undefined;
346 decompressed.initFixed(&dcm_buf);339 decompressed.initFixed(&dcm_buf);
347 try Decompress.pump(container, &compressed, &decompressed);340 try Decompress.pump(container, &compressed, &decompressed);
...@@ -353,8 +346,7 @@ test "compress/decompress" {...@@ -353,8 +346,7 @@ test "compress/decompress" {
353}346}
354347
355fn testDecompress(comptime container: Container, compressed: []const u8, expected_plain: []const u8) !void {348fn testDecompress(comptime container: Container, compressed: []const u8, expected_plain: []const u8) !void {
356 var in: std.io.BufferedReader = undefined;349 var in: std.io.Reader = .fixed(compressed);
357 in.initFixed(compressed);
358 var out: std.io.AllocatingWriter = undefined;350 var out: std.io.AllocatingWriter = undefined;
359 out.init(testing.allocator);351 out.init(testing.allocator);
360 defer out.deinit();352 defer out.deinit();
...@@ -502,8 +494,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -502,8 +494,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
502 var plain: std.io.BufferedWriter = undefined;494 var plain: std.io.BufferedWriter = undefined;
503 plain.initFixed(&buffer2);495 plain.initFixed(&buffer2);
504496
505 var in: std.io.BufferedReader = undefined;497 var in: std.io.Reader = .fixed(gzip_data);
506 in.initFixed(gzip_data);
507 try pkg.decompress(&in, &plain);498 try pkg.decompress(&in, &plain);
508 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());499 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
509 }500 }
...@@ -515,12 +506,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -515,12 +506,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
515 var compressed: std.io.BufferedWriter = undefined;506 var compressed: std.io.BufferedWriter = undefined;
516 compressed.initFixed(&buffer1);507 compressed.initFixed(&buffer1);
517508
518 var in: std.io.BufferedReader = undefined;509 var in: std.io.Reader = .fixed(plain_data);
519 in.initFixed(plain_data);
520 try pkg.compress(&in, &compressed, .{});510 try pkg.compress(&in, &compressed, .{});
521511
522 var compressed_br: std.io.BufferedReader = undefined;512 var compressed_br: std.io.Reader = .fixed(&buffer1);
523 compressed_br.initFixed(&buffer1);
524 try pkg.decompress(&compressed_br, &plain);513 try pkg.decompress(&compressed_br, &plain);
525 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());514 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
526 }515 }
...@@ -532,14 +521,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -532,14 +521,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
532 var compressed: std.io.BufferedWriter = undefined;521 var compressed: std.io.BufferedWriter = undefined;
533 compressed.initFixed(&buffer1);522 compressed.initFixed(&buffer1);
534523
535 var in: std.io.BufferedReader = undefined;524 var in: std.io.Reader = .fixed(plain_data);
536 in.initFixed(plain_data);
537 var cmp = try pkg.compressor(&compressed, .{});525 var cmp = try pkg.compressor(&compressed, .{});
538 try cmp.compress(&in);526 try cmp.compress(&in);
539 try cmp.finish();527 try cmp.finish();
540528
541 var compressed_br: std.io.BufferedReader = undefined;529 var compressed_br: std.io.Reader = .fixed(&buffer1);
542 compressed_br.initFixed(&buffer1);
543 var dcp = pkg.decompressor(&compressed_br);530 var dcp = pkg.decompressor(&compressed_br);
544 try dcp.decompress(&plain);531 try dcp.decompress(&plain);
545 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());532 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
...@@ -554,12 +541,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -554,12 +541,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
554 var compressed: std.io.BufferedWriter = undefined;541 var compressed: std.io.BufferedWriter = undefined;
555 compressed.initFixed(&buffer1);542 compressed.initFixed(&buffer1);
556543
557 var in: std.io.BufferedReader = undefined;544 var in: std.io.Reader = .fixed(plain_data);
558 in.initFixed(plain_data);
559 try pkg.huffman.compress(&in, &compressed);545 try pkg.huffman.compress(&in, &compressed);
560546
561 var compressed_br: std.io.BufferedReader = undefined;547 var compressed_br: std.io.Reader = .fixed(&buffer1);
562 compressed_br.initFixed(&buffer1);
563 try pkg.decompress(&compressed_br, &plain);548 try pkg.decompress(&compressed_br, &plain);
564 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());549 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
565 }550 }
...@@ -571,14 +556,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -571,14 +556,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
571 var compressed: std.io.BufferedWriter = undefined;556 var compressed: std.io.BufferedWriter = undefined;
572 compressed.initFixed(&buffer1);557 compressed.initFixed(&buffer1);
573558
574 var in: std.io.BufferedReader = undefined;559 var in: std.io.Reader = .fixed(plain_data);
575 in.initFixed(plain_data);
576 var cmp = try pkg.huffman.compressor(&compressed);560 var cmp = try pkg.huffman.compressor(&compressed);
577 try cmp.compress(&in);561 try cmp.compress(&in);
578 try cmp.finish();562 try cmp.finish();
579563
580 var compressed_br: std.io.BufferedReader = undefined;564 var compressed_br: std.io.Reader = .fixed(&buffer1);
581 compressed_br.initFixed(&buffer1);
582 try pkg.decompress(&compressed_br, &plain);565 try pkg.decompress(&compressed_br, &plain);
583 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());566 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
584 }567 }
...@@ -593,12 +576,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -593,12 +576,10 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
593 var compressed: std.io.BufferedWriter = undefined;576 var compressed: std.io.BufferedWriter = undefined;
594 compressed.initFixed(&buffer1);577 compressed.initFixed(&buffer1);
595578
596 var in: std.io.BufferedReader = undefined;579 var in: std.io.Reader = .fixed(plain_data);
597 in.initFixed(plain_data);
598 try pkg.store.compress(&in, &compressed);580 try pkg.store.compress(&in, &compressed);
599581
600 var compressed_br: std.io.BufferedReader = undefined;582 var compressed_br: std.io.Reader = .fixed(&buffer1);
601 compressed_br.initFixed(&buffer1);
602 try pkg.decompress(&compressed_br, &plain);583 try pkg.decompress(&compressed_br, &plain);
603 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());584 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
604 }585 }
...@@ -610,14 +591,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -610,14 +591,12 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
610 var compressed: std.io.BufferedWriter = undefined;591 var compressed: std.io.BufferedWriter = undefined;
611 compressed.initFixed(&buffer1);592 compressed.initFixed(&buffer1);
612593
613 var in: std.io.BufferedReader = undefined;594 var in: std.io.Reader = .fixed(plain_data);
614 in.initFixed(plain_data);
615 var cmp = try pkg.store.compressor(&compressed);595 var cmp = try pkg.store.compressor(&compressed);
616 try cmp.compress(&in);596 try cmp.compress(&in);
617 try cmp.finish();597 try cmp.finish();
618598
619 var compressed_br: std.io.BufferedReader = undefined;599 var compressed_br: std.io.Reader = .fixed(&buffer1);
620 compressed_br.initFixed(&buffer1);
621 try pkg.decompress(&compressed_br, &plain);600 try pkg.decompress(&compressed_br, &plain);
622 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());601 try testing.expectEqualSlices(u8, plain_data, plain.getWritten());
623 }602 }
...@@ -650,8 +629,7 @@ test "zlib should not overshoot" {...@@ -650,8 +629,7 @@ test "zlib should not overshoot" {
650 0x03, 0x00, 0x8b, 0x61, 0x0f, 0xa4, 0x52, 0x5a, 0x94, 0x12,629 0x03, 0x00, 0x8b, 0x61, 0x0f, 0xa4, 0x52, 0x5a, 0x94, 0x12,
651 };630 };
652631
653 var stream: std.io.BufferedReader = undefined;632 var stream: std.io.Reader = .fixed(&data);
654 stream.initFixed(&data);
655 const reader = stream.reader();633 const reader = stream.reader();
656634
657 var dcp = Decompress.init(reader);635 var dcp = Decompress.init(reader);
lib/std/compress/flate/Compress.zig+5-5
...@@ -59,7 +59,7 @@ const huffman = flate.huffman;...@@ -59,7 +59,7 @@ const huffman = flate.huffman;
59lookup: Lookup = .{},59lookup: Lookup = .{},
60tokens: Tokens = .{},60tokens: Tokens = .{},
61/// Asserted to have a buffer capacity of at least `flate.max_window_len`.61/// Asserted to have a buffer capacity of at least `flate.max_window_len`.
62input: *std.io.BufferedReader,62input: *std.io.Reader,
63block_writer: BlockWriter,63block_writer: BlockWriter,
64level: LevelArgs,64level: LevelArgs,
65hasher: Container.Hasher,65hasher: Container.Hasher,
...@@ -69,7 +69,7 @@ hasher: Container.Hasher,...@@ -69,7 +69,7 @@ hasher: Container.Hasher,
69prev_match: ?Token = null,69prev_match: ?Token = null,
70prev_literal: ?u8 = null,70prev_literal: ?u8 = null,
7171
72pub fn readable(c: *Compress, buffer: []u8) std.io.BufferedReader {72pub fn readable(c: *Compress, buffer: []u8) std.io.Reader {
73 return .{73 return .{
74 .unbuffered_reader = .{74 .unbuffered_reader = .{
75 .context = c,75 .context = c,
...@@ -126,7 +126,7 @@ const LevelArgs = struct {...@@ -126,7 +126,7 @@ const LevelArgs = struct {
126 }126 }
127};127};
128128
129pub fn init(input: *std.io.BufferedReader, options: Options) Compress {129pub fn init(input: *std.io.Reader, options: Options) Compress {
130 return .{130 return .{
131 .input = input,131 .input = input,
132 .block_writer = undefined,132 .block_writer = undefined,
...@@ -1147,7 +1147,7 @@ test "file tokenization" {...@@ -1147,7 +1147,7 @@ test "file tokenization" {
1147 const data = case.data;1147 const data = case.data;
11481148
1149 for (levels, 0..) |level, i| { // for each compression level1149 for (levels, 0..) |level, i| { // for each compression level
1150 var original: std.io.BufferedReader = undefined;1150 var original: std.io.Reader = undefined;
1151 original.initFixed(data);1151 original.initFixed(data);
11521152
1153 // buffer for decompressed data1153 // buffer for decompressed data
...@@ -1222,7 +1222,7 @@ test "store simple compressor" {...@@ -1222,7 +1222,7 @@ test "store simple compressor" {
1222 //0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,1222 //0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
1223 };1223 };
12241224
1225 var fbs: std.io.BufferedReader = undefined;1225 var fbs: std.io.Reader = undefined;
1226 fbs.initFixed(data);1226 fbs.initFixed(data);
1227 var al = std.ArrayList(u8).init(testing.allocator);1227 var al = std.ArrayList(u8).init(testing.allocator);
1228 defer al.deinit();1228 defer al.deinit();
lib/std/compress/flate/Decompress.zig+9-9
...@@ -24,7 +24,7 @@ const Token = @import("Token.zig");...@@ -24,7 +24,7 @@ const Token = @import("Token.zig");
24const testing = std.testing;24const testing = std.testing;
25const Decompress = @This();25const Decompress = @This();
2626
27input: *std.io.BufferedReader,27input: *std.io.Reader,
28// Hashes, produces checksum, of uncompressed data for gzip/zlib footer.28// Hashes, produces checksum, of uncompressed data for gzip/zlib footer.
29hasher: Container.Hasher,29hasher: Container.Hasher,
3030
...@@ -67,7 +67,7 @@ pub const Error = Container.Error || error{...@@ -67,7 +67,7 @@ pub const Error = Container.Error || error{
67 MissingEndOfBlockCode,67 MissingEndOfBlockCode,
68};68};
6969
70pub fn init(input: *std.io.BufferedReader, container: Container) Decompress {70pub fn init(input: *std.io.Reader, container: Container) Decompress {
71 return .{71 return .{
72 .input = input,72 .input = input,
73 .hasher = .init(container),73 .hasher = .init(container),
...@@ -361,7 +361,7 @@ pub fn reader(self: *Decompress) std.io.Reader {...@@ -361,7 +361,7 @@ pub fn reader(self: *Decompress) std.io.Reader {
361 };361 };
362}362}
363363
364pub fn readable(self: *Decompress, buffer: []u8) std.io.BufferedReader {364pub fn readable(self: *Decompress, buffer: []u8) std.io.Reader {
365 return reader(self).buffered(buffer);365 return reader(self).buffered(buffer);
366}366}
367367
...@@ -727,7 +727,7 @@ test "decompress" {...@@ -727,7 +727,7 @@ test "decompress" {
727 },727 },
728 };728 };
729 for (cases) |c| {729 for (cases) |c| {
730 var fb: std.io.BufferedReader = undefined;730 var fb: std.io.Reader = undefined;
731 fb.initFixed(@constCast(c.in));731 fb.initFixed(@constCast(c.in));
732 var aw: std.io.AllocatingWriter = undefined;732 var aw: std.io.AllocatingWriter = undefined;
733 aw.init(testing.allocator);733 aw.init(testing.allocator);
...@@ -788,7 +788,7 @@ test "gzip decompress" {...@@ -788,7 +788,7 @@ test "gzip decompress" {
788 },788 },
789 };789 };
790 for (cases) |c| {790 for (cases) |c| {
791 var fb: std.io.BufferedReader = undefined;791 var fb: std.io.Reader = undefined;
792 fb.initFixed(@constCast(c.in));792 fb.initFixed(@constCast(c.in));
793 var aw: std.io.AllocatingWriter = undefined;793 var aw: std.io.AllocatingWriter = undefined;
794 aw.init(testing.allocator);794 aw.init(testing.allocator);
...@@ -818,7 +818,7 @@ test "zlib decompress" {...@@ -818,7 +818,7 @@ test "zlib decompress" {
818 },818 },
819 };819 };
820 for (cases) |c| {820 for (cases) |c| {
821 var fb: std.io.BufferedReader = undefined;821 var fb: std.io.Reader = undefined;
822 fb.initFixed(@constCast(c.in));822 fb.initFixed(@constCast(c.in));
823 var aw: std.io.AllocatingWriter = undefined;823 var aw: std.io.AllocatingWriter = undefined;
824 aw.init(testing.allocator);824 aw.init(testing.allocator);
...@@ -880,7 +880,7 @@ test "fuzzing tests" {...@@ -880,7 +880,7 @@ test "fuzzing tests" {
880 };880 };
881881
882 inline for (cases, 0..) |c, case_no| {882 inline for (cases, 0..) |c, case_no| {
883 var in: std.io.BufferedReader = undefined;883 var in: std.io.Reader = undefined;
884 in.initFixed(@constCast(@embedFile("testdata/fuzz/" ++ c.input ++ ".input")));884 in.initFixed(@constCast(@embedFile("testdata/fuzz/" ++ c.input ++ ".input")));
885 var aw: std.io.AllocatingWriter = undefined;885 var aw: std.io.AllocatingWriter = undefined;
886 aw.init(testing.allocator);886 aw.init(testing.allocator);
...@@ -903,7 +903,7 @@ test "bug 18966" {...@@ -903,7 +903,7 @@ test "bug 18966" {
903 const input = @embedFile("testdata/fuzz/bug_18966.input");903 const input = @embedFile("testdata/fuzz/bug_18966.input");
904 const expect = @embedFile("testdata/fuzz/bug_18966.expect");904 const expect = @embedFile("testdata/fuzz/bug_18966.expect");
905905
906 var in: std.io.BufferedReader = undefined;906 var in: std.io.Reader = undefined;
907 in.initFixed(@constCast(input));907 in.initFixed(@constCast(input));
908 var aw: std.io.AllocatingWriter = undefined;908 var aw: std.io.AllocatingWriter = undefined;
909 aw.init(testing.allocator);909 aw.init(testing.allocator);
...@@ -921,7 +921,7 @@ test "reading into empty buffer" {...@@ -921,7 +921,7 @@ test "reading into empty buffer" {
921 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen921 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen
922 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0a, // non compressed data922 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0a, // non compressed data
923 };923 };
924 var in: std.io.BufferedReader = undefined;924 var in: std.io.Reader = undefined;
925 in.initFixed(@constCast(input));925 in.initFixed(@constCast(input));
926 var decomp: Decompress = .init(&in, .raw);926 var decomp: Decompress = .init(&in, .raw);
927 var decompress_br = decomp.readable(&.{});927 var decompress_br = decomp.readable(&.{});
lib/std/compress/lzma.zig+21-21
...@@ -11,7 +11,7 @@ pub const RangeDecoder = struct {...@@ -11,7 +11,7 @@ pub const RangeDecoder = struct {
11 range: u32,11 range: u32,
12 code: u32,12 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 {
15 const reserved = try br.takeByte();15 const reserved = try br.takeByte();
16 if (reserved != 0) return error.CorruptInput;16 if (reserved != 0) return error.CorruptInput;
17 rd.* = .{17 rd.* = .{
...@@ -25,14 +25,14 @@ pub const RangeDecoder = struct {...@@ -25,14 +25,14 @@ pub const RangeDecoder = struct {
25 return self.code == 0;25 return self.code == 0;
26 }26 }
2727
28 inline fn normalize(self: *RangeDecoder, br: *std.io.BufferedReader) !void {28 inline fn normalize(self: *RangeDecoder, br: *std.io.Reader) !void {
29 if (self.range < 0x0100_0000) {29 if (self.range < 0x0100_0000) {
30 self.range <<= 8;30 self.range <<= 8;
31 self.code = (self.code << 8) ^ @as(u32, try br.takeByte());31 self.code = (self.code << 8) ^ @as(u32, try br.takeByte());
32 }32 }
33 }33 }
3434
35 inline fn getBit(self: *RangeDecoder, br: *std.io.BufferedReader) !bool {35 inline fn getBit(self: *RangeDecoder, br: *std.io.Reader) !bool {
36 self.range >>= 1;36 self.range >>= 1;
3737
38 const bit = self.code >= self.range;38 const bit = self.code >= self.range;
...@@ -43,7 +43,7 @@ pub const RangeDecoder = struct {...@@ -43,7 +43,7 @@ pub const RangeDecoder = struct {
43 return bit;43 return bit;
44 }44 }
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 {
47 var result: u32 = 0;47 var result: u32 = 0;
48 var i: usize = 0;48 var i: usize = 0;
49 while (i < count) : (i += 1)49 while (i < count) : (i += 1)
...@@ -51,7 +51,7 @@ pub const RangeDecoder = struct {...@@ -51,7 +51,7 @@ pub const RangeDecoder = struct {
51 return result;51 return result;
52 }52 }
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 {
55 const bound = (self.range >> 11) * prob.*;55 const bound = (self.range >> 11) * prob.*;
5656
57 if (self.code < bound) {57 if (self.code < bound) {
...@@ -74,7 +74,7 @@ pub const RangeDecoder = struct {...@@ -74,7 +74,7 @@ pub const RangeDecoder = struct {
7474
75 fn parseBitTree(75 fn parseBitTree(
76 self: *RangeDecoder,76 self: *RangeDecoder,
77 br: *std.io.BufferedReader,77 br: *std.io.Reader,
78 num_bits: u5,78 num_bits: u5,
79 probs: []u16,79 probs: []u16,
80 update: bool,80 update: bool,
...@@ -90,7 +90,7 @@ pub const RangeDecoder = struct {...@@ -90,7 +90,7 @@ pub const RangeDecoder = struct {
9090
91 pub fn parseReverseBitTree(91 pub fn parseReverseBitTree(
92 self: *RangeDecoder,92 self: *RangeDecoder,
93 br: *std.io.BufferedReader,93 br: *std.io.Reader,
94 num_bits: u5,94 num_bits: u5,
95 probs: []u16,95 probs: []u16,
96 offset: usize,96 offset: usize,
...@@ -117,7 +117,7 @@ pub const LenDecoder = struct {...@@ -117,7 +117,7 @@ pub const LenDecoder = struct {
117117
118 pub fn decode(118 pub fn decode(
119 self: *LenDecoder,119 self: *LenDecoder,
120 br: *std.io.BufferedReader,120 br: *std.io.Reader,
121 decoder: *RangeDecoder,121 decoder: *RangeDecoder,
122 pos_state: usize,122 pos_state: usize,
123 update: bool,123 update: bool,
...@@ -148,7 +148,7 @@ pub fn BitTree(comptime num_bits: usize) type {...@@ -148,7 +148,7 @@ pub fn BitTree(comptime num_bits: usize) type {
148148
149 pub fn parse(149 pub fn parse(
150 self: *Self,150 self: *Self,
151 br: *std.io.BufferedReader,151 br: *std.io.Reader,
152 decoder: *RangeDecoder,152 decoder: *RangeDecoder,
153 update: bool,153 update: bool,
154 ) !u32 {154 ) !u32 {
...@@ -157,7 +157,7 @@ pub fn BitTree(comptime num_bits: usize) type {...@@ -157,7 +157,7 @@ pub fn BitTree(comptime num_bits: usize) type {
157157
158 pub fn parseReverse(158 pub fn parseReverse(
159 self: *Self,159 self: *Self,
160 br: *std.io.BufferedReader,160 br: *std.io.Reader,
161 decoder: *RangeDecoder,161 decoder: *RangeDecoder,
162 update: bool,162 update: bool,
163 ) !u32 {163 ) !u32 {
...@@ -222,7 +222,7 @@ pub const Decode = struct {...@@ -222,7 +222,7 @@ pub const Decode = struct {
222 dict_size: u32,222 dict_size: u32,
223 unpacked_size: ?u64,223 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 {
226 var props = try br.readByte();226 var props = try br.readByte();
227 if (props >= 225) {227 if (props >= 225) {
228 return error.CorruptInput;228 return error.CorruptInput;
...@@ -319,7 +319,7 @@ pub const Decode = struct {...@@ -319,7 +319,7 @@ pub const Decode = struct {
319 fn processNextInner(319 fn processNextInner(
320 self: *Decode,320 self: *Decode,
321 allocator: Allocator,321 allocator: Allocator,
322 br: *std.io.BufferedReader,322 br: *std.io.Reader,
323 bw: *std.io.BufferedWriter,323 bw: *std.io.BufferedWriter,
324 buffer: anytype,324 buffer: anytype,
325 decoder: *RangeDecoder,325 decoder: *RangeDecoder,
...@@ -416,7 +416,7 @@ pub const Decode = struct {...@@ -416,7 +416,7 @@ pub const Decode = struct {
416 fn processNext(416 fn processNext(
417 self: *Decode,417 self: *Decode,
418 allocator: Allocator,418 allocator: Allocator,
419 br: *std.io.BufferedReader,419 br: *std.io.Reader,
420 bw: *std.io.BufferedWriter,420 bw: *std.io.BufferedWriter,
421 buffer: anytype,421 buffer: anytype,
422 decoder: *RangeDecoder,422 decoder: *RangeDecoder,
...@@ -428,7 +428,7 @@ pub const Decode = struct {...@@ -428,7 +428,7 @@ pub const Decode = struct {
428 pub fn process(428 pub fn process(
429 self: *Decode,429 self: *Decode,
430 allocator: Allocator,430 allocator: Allocator,
431 br: *std.io.BufferedReader,431 br: *std.io.Reader,
432 bw: *std.io.BufferedWriter,432 bw: *std.io.BufferedWriter,
433 buffer: anytype,433 buffer: anytype,
434 decoder: *RangeDecoder,434 decoder: *RangeDecoder,
...@@ -460,7 +460,7 @@ pub const Decode = struct {...@@ -460,7 +460,7 @@ pub const Decode = struct {
460460
461 fn decodeLiteral(461 fn decodeLiteral(
462 self: *Decode,462 self: *Decode,
463 br: *std.io.BufferedReader,463 br: *std.io.Reader,
464 buffer: anytype,464 buffer: anytype,
465 decoder: *RangeDecoder,465 decoder: *RangeDecoder,
466 update: bool,466 update: bool,
...@@ -502,7 +502,7 @@ pub const Decode = struct {...@@ -502,7 +502,7 @@ pub const Decode = struct {
502502
503 fn decodeDistance(503 fn decodeDistance(
504 self: *Decode,504 self: *Decode,
505 br: *std.io.BufferedReader,505 br: *std.io.Reader,
506 decoder: *RangeDecoder,506 decoder: *RangeDecoder,
507 length: usize,507 length: usize,
508 update: bool,508 update: bool,
...@@ -542,19 +542,19 @@ pub const Decompress = struct {...@@ -542,19 +542,19 @@ pub const Decompress = struct {
542 error{ CorruptInput, EndOfStream, Overflow };542 error{ CorruptInput, EndOfStream, Overflow };
543543
544 allocator: Allocator,544 allocator: Allocator,
545 in_reader: *std.io.BufferedReader,545 in_reader: *std.io.Reader,
546 to_read: std.ArrayListUnmanaged(u8),546 to_read: std.ArrayListUnmanaged(u8),
547547
548 buffer: LzCircularBuffer,548 buffer: LzCircularBuffer,
549 decoder: RangeDecoder,549 decoder: RangeDecoder,
550 state: Decode,550 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 {
553 const params = try Decode.Params.readHeader(br, options);553 const params = try Decode.Params.readHeader(br, options);
554 return init(allocator, br, params, options.memlimit);554 return init(allocator, br, params, options.memlimit);
555 }555 }
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 {
558 return .{558 return .{
559 .allocator = allocator,559 .allocator = allocator,
560 .in_reader = source,560 .in_reader = source,
...@@ -839,7 +839,7 @@ test "Vec2D get addition overflow" {...@@ -839,7 +839,7 @@ test "Vec2D get addition overflow" {
839839
840fn testDecompress(compressed: []const u8) ![]u8 {840fn testDecompress(compressed: []const u8) ![]u8 {
841 const allocator = std.testing.allocator;841 const allocator = std.testing.allocator;
842 var br: std.io.BufferedReader = undefined;842 var br: std.io.Reader = undefined;
843 br.initFixed(compressed);843 br.initFixed(compressed);
844 var decompressor = try Decompress.initOptions(allocator, &br, .{});844 var decompressor = try Decompress.initOptions(allocator, &br, .{});
845 defer decompressor.deinit();845 defer decompressor.deinit();
...@@ -927,7 +927,7 @@ test "too small uncompressed size in header" {...@@ -927,7 +927,7 @@ test "too small uncompressed size in header" {
927927
928test "reading one byte" {928test "reading one byte" {
929 const compressed = @embedFile("testdata/good-known_size-with_eopm.lzma");929 const compressed = @embedFile("testdata/good-known_size-with_eopm.lzma");
930 var br: std.io.BufferedReader = undefined;930 var br: std.io.Reader = undefined;
931 br.initFixed(compressed);931 br.initFixed(compressed);
932 var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{});932 var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{});
933 defer decompressor.deinit();933 defer decompressor.deinit();
lib/std/compress/lzma2.zig+5-5
...@@ -2,7 +2,7 @@ const std = @import("../std.zig");...@@ -2,7 +2,7 @@ const std = @import("../std.zig");
2const Allocator = std.mem.Allocator;2const Allocator = std.mem.Allocator;
3const lzma = std.compress.lzma;3const 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 {
6 var decoder = try Decode.init(gpa);6 var decoder = try Decode.init(gpa);
7 defer decoder.deinit(gpa);7 defer decoder.deinit(gpa);
8 return decoder.decompress(gpa, reader, writer);8 return decoder.decompress(gpa, reader, writer);
...@@ -33,7 +33,7 @@ pub const Decode = struct {...@@ -33,7 +33,7 @@ pub const Decode = struct {
33 pub fn decompress(33 pub fn decompress(
34 self: *Decode,34 self: *Decode,
35 allocator: Allocator,35 allocator: Allocator,
36 reader: *std.io.BufferedReader,36 reader: *std.io.Reader,
37 writer: *std.io.BufferedWriter,37 writer: *std.io.BufferedWriter,
38 ) !void {38 ) !void {
39 var accum = LzAccumBuffer.init(std.math.maxInt(usize));39 var accum = LzAccumBuffer.init(std.math.maxInt(usize));
...@@ -56,7 +56,7 @@ pub const Decode = struct {...@@ -56,7 +56,7 @@ pub const Decode = struct {
56 fn parseLzma(56 fn parseLzma(
57 self: *Decode,57 self: *Decode,
58 allocator: Allocator,58 allocator: Allocator,
59 br: *std.io.BufferedReader,59 br: *std.io.Reader,
60 writer: *std.io.BufferedWriter,60 writer: *std.io.BufferedWriter,
61 accum: *LzAccumBuffer,61 accum: *LzAccumBuffer,
62 status: u8,62 status: u8,
...@@ -149,7 +149,7 @@ pub const Decode = struct {...@@ -149,7 +149,7 @@ pub const Decode = struct {
149149
150 fn parseUncompressed(150 fn parseUncompressed(
151 allocator: Allocator,151 allocator: Allocator,
152 reader: *std.io.BufferedReader,152 reader: *std.io.Reader,
153 writer: *std.io.BufferedWriter,153 writer: *std.io.BufferedWriter,
154 accum: *LzAccumBuffer,154 accum: *LzAccumBuffer,
155 reset_dict: bool,155 reset_dict: bool,
...@@ -276,7 +276,7 @@ test decompress {...@@ -276,7 +276,7 @@ test decompress {
276 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02,276 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02,
277 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00,277 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00,
278 };278 };
279 var stream: std.io.BufferedReader = undefined;279 var stream: std.io.Reader = undefined;
280 stream.initFixed(&compressed);280 stream.initFixed(&compressed);
281 var decomp: std.io.AllocatingWriter = undefined;281 var decomp: std.io.AllocatingWriter = undefined;
282 const decomp_bw = decomp.init(std.testing.allocator);282 const decomp_bw = decomp.init(std.testing.allocator);
lib/std/compress/xz/test.zig+2-3
...@@ -3,10 +3,9 @@ const testing = std.testing;...@@ -3,10 +3,9 @@ const testing = std.testing;
3const xz = std.compress.xz;3const xz = std.compress.xz;
44
5fn decompress(data: []const u8) ![]u8 {5fn decompress(data: []const u8) ![]u8 {
6 var in_stream: std.io.BufferedReader = undefined;6 var r: std.io.Reader = .fixed(data);
7 in_stream.initFixed(data);
87
9 var xz_stream = try xz.decompress(testing.allocator, &in_stream);8 var xz_stream = try xz.decompress(testing.allocator, &r);
10 defer xz_stream.deinit();9 defer xz_stream.deinit();
1110
12 return xz_stream.reader().readAllAlloc(testing.allocator, std.math.maxInt(usize));11 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 {...@@ -82,8 +82,7 @@ fn testDecompress(gpa: std.mem.Allocator, compressed: []const u8) ![]u8 {
82 var out: std.ArrayListUnmanaged(u8) = .empty;82 var out: std.ArrayListUnmanaged(u8) = .empty;
83 defer out.deinit(gpa);83 defer out.deinit(gpa);
8484
85 var in: std.io.BufferedReader = undefined;85 var in: std.io.Reader = .fixed(compressed);
86 in.initFixed(@constCast(compressed));
87 var zstd_stream: Decompress = .init(&in, .{});86 var zstd_stream: Decompress = .init(&in, .{});
88 try zstd_stream.reader().readRemainingArrayList(gpa, null, &out, .unlimited, default_window_len);87 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 {...@@ -103,8 +102,7 @@ fn testExpectDecompressError(err: anyerror, compressed: []const u8) !void {
103 var out: std.ArrayListUnmanaged(u8) = .empty;102 var out: std.ArrayListUnmanaged(u8) = .empty;
104 defer out.deinit(gpa);103 defer out.deinit(gpa);
105104
106 var in: std.io.BufferedReader = undefined;105 var in: std.io.Reader = .fixed(compressed);
107 in.initFixed(@constCast(compressed));
108 var zstd_stream: Decompress = .init(&in, .{});106 var zstd_stream: Decompress = .init(&in, .{});
109 try std.testing.expectError(107 try std.testing.expectError(
110 error.ReadFailed,108 error.ReadFailed,
lib/std/compress/zstd/Decompress.zig+11-12
...@@ -4,10 +4,9 @@ const assert = std.debug.assert;...@@ -4,10 +4,9 @@ const assert = std.debug.assert;
4const Reader = std.io.Reader;4const Reader = std.io.Reader;
5const Limit = std.io.Limit;5const Limit = std.io.Limit;
6const BufferedWriter = std.io.BufferedWriter;6const BufferedWriter = std.io.BufferedWriter;
7const BufferedReader = std.io.BufferedReader;
8const zstd = @import("../zstd.zig");7const zstd = @import("../zstd.zig");
98
10input: *BufferedReader,9input: *Reader,
11state: State,10state: State,
12verify_checksum: bool,11verify_checksum: bool,
13err: ?Error = null,12err: ?Error = null,
...@@ -63,7 +62,7 @@ pub const Error = error{...@@ -63,7 +62,7 @@ pub const Error = error{
63 WindowSizeUnknown,62 WindowSizeUnknown,
64};63};
6564
66pub fn init(input: *BufferedReader, options: Options) Decompress {65pub fn init(input: *Reader, options: Options) Decompress {
67 return .{66 return .{
68 .input = input,67 .input = input,
69 .state = .new_frame,68 .state = .new_frame,
...@@ -305,7 +304,7 @@ pub const Frame = struct {...@@ -305,7 +304,7 @@ pub const Frame = struct {
305304
306 pub const DecodeError = Reader.Error || error{ReservedBitSet};305 pub const DecodeError = Reader.Error || error{ReservedBitSet};
307306
308 pub fn decode(in: *BufferedReader) DecodeError!Header {307 pub fn decode(in: *Reader) DecodeError!Header {
309 const descriptor: Descriptor = @bitCast(try in.takeByte());308 const descriptor: Descriptor = @bitCast(try in.takeByte());
310309
311 if (descriptor.reserved) return error.ReservedBitSet;310 if (descriptor.reserved) return error.ReservedBitSet;
...@@ -446,7 +445,7 @@ pub const Frame = struct {...@@ -446,7 +445,7 @@ pub const Frame = struct {
446 /// FSE tables from `in`.445 /// FSE tables from `in`.
447 pub fn prepare(446 pub fn prepare(
448 self: *Decode,447 self: *Decode,
449 in: *BufferedReader,448 in: *Reader,
450 remaining: *Limit,449 remaining: *Limit,
451 literals: LiteralsSection,450 literals: LiteralsSection,
452 sequences_header: SequencesSection.Header,451 sequences_header: SequencesSection.Header,
...@@ -536,7 +535,7 @@ pub const Frame = struct {...@@ -536,7 +535,7 @@ pub const Frame = struct {
536 /// TODO: don't use `@field`535 /// TODO: don't use `@field`
537 fn updateFseTable(536 fn updateFseTable(
538 self: *Decode,537 self: *Decode,
539 in: *BufferedReader,538 in: *Reader,
540 remaining: *Limit,539 remaining: *Limit,
541 comptime choice: DataType,540 comptime choice: DataType,
542 mode: SequencesSection.Header.Mode,541 mode: SequencesSection.Header.Mode,
...@@ -858,7 +857,7 @@ pub const LiteralsSection = struct {...@@ -858,7 +857,7 @@ pub const LiteralsSection = struct {
858 compressed_size: ?u18,857 compressed_size: ?u18,
859858
860 /// Decode a literals section header.859 /// Decode a literals section header.
861 pub fn decode(in: *BufferedReader, remaining: *Limit) !Header {860 pub fn decode(in: *Reader, remaining: *Limit) !Header {
862 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;861 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
863 const byte0 = try in.takeByte();862 const byte0 = try in.takeByte();
864 const block_type: BlockType = @enumFromInt(byte0 & 0b11);863 const block_type: BlockType = @enumFromInt(byte0 & 0b11);
...@@ -965,7 +964,7 @@ pub const LiteralsSection = struct {...@@ -965,7 +964,7 @@ pub const LiteralsSection = struct {
965 MissingStartBit,964 MissingStartBit,
966 };965 };
967966
968 pub fn decode(in: *BufferedReader, remaining: *Limit) HuffmanTree.DecodeError!HuffmanTree {967 pub fn decode(in: *Reader, remaining: *Limit) HuffmanTree.DecodeError!HuffmanTree {
969 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;968 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
970 const header = try in.takeByte();969 const header = try in.takeByte();
971 if (header < 128) {970 if (header < 128) {
...@@ -976,7 +975,7 @@ pub const LiteralsSection = struct {...@@ -976,7 +975,7 @@ pub const LiteralsSection = struct {
976 }975 }
977976
978 fn decodeDirect(977 fn decodeDirect(
979 in: *BufferedReader,978 in: *Reader,
980 remaining: *Limit,979 remaining: *Limit,
981 encoded_symbol_count: usize,980 encoded_symbol_count: usize,
982 ) HuffmanTree.DecodeError!HuffmanTree {981 ) HuffmanTree.DecodeError!HuffmanTree {
...@@ -993,7 +992,7 @@ pub const LiteralsSection = struct {...@@ -993,7 +992,7 @@ pub const LiteralsSection = struct {
993 }992 }
994993
995 fn decodeFse(994 fn decodeFse(
996 in: *BufferedReader,995 in: *Reader,
997 remaining: *Limit,996 remaining: *Limit,
998 compressed_size: usize,997 compressed_size: usize,
999 ) HuffmanTree.DecodeError!HuffmanTree {998 ) HuffmanTree.DecodeError!HuffmanTree {
...@@ -1162,7 +1161,7 @@ pub const LiteralsSection = struct {...@@ -1162,7 +1161,7 @@ pub const LiteralsSection = struct {
1162 MissingStartBit,1161 MissingStartBit,
1163 };1162 };
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 {
1166 const header = try Header.decode(in, remaining);1165 const header = try Header.decode(in, remaining);
1167 switch (header.block_type) {1166 switch (header.block_type) {
1168 .raw => {1167 .raw => {
...@@ -1233,7 +1232,7 @@ pub const SequencesSection = struct {...@@ -1233,7 +1232,7 @@ pub const SequencesSection = struct {
1233 ReadFailed,1232 ReadFailed,
1234 };1233 };
12351234
1236 pub fn decode(in: *BufferedReader, remaining: *Limit) DecodeError!Header {1235 pub fn decode(in: *Reader, remaining: *Limit) DecodeError!Header {
1237 var sequence_count: u24 = undefined;1236 var sequence_count: u24 = undefined;
12381237
1239 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;1238 remaining.* = remaining.subtract(1) orelse return error.EndOfStream;
lib/std/crypto/codecs/asn1.zig+2-4
...@@ -154,8 +154,7 @@ pub const Tag = struct {...@@ -154,8 +154,7 @@ pub const Tag = struct {
154154
155test Tag {155test Tag {
156 const buf = [_]u8{0xa3};156 const buf = [_]u8{0xa3};
157 var stream: std.io.BufferedReader = undefined;157 var stream: std.io.Reader = .fixed(&buf);
158 stream.initFixed(&buf);
159 const t = Tag.decode(stream.reader());158 const t = Tag.decode(stream.reader());
160 try std.testing.expectEqual(Tag.init(@enumFromInt(3), true, .context_specific), t);159 try std.testing.expectEqual(Tag.init(@enumFromInt(3), true, .context_specific), t);
161}160}
...@@ -185,8 +184,7 @@ pub const Element = struct {...@@ -185,8 +184,7 @@ pub const Element = struct {
185 /// - Ensures length is within `bytes`184 /// - Ensures length is within `bytes`
186 /// - Ensures length is less than `std.math.maxInt(Index)`185 /// - Ensures length is less than `std.math.maxInt(Index)`
187 pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {186 pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {
188 var reader: std.io.BufferedReader = undefined;187 var reader: std.io.Reader = .fixed(bytes[index..]);
189 reader.initFixed(bytes[index..]);
190188
191 const tag = try Tag.decode(reader);189 const tag = try Tag.decode(reader);
192 const size_or_len_size = try reader.readByte();190 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 {...@@ -155,20 +155,20 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
155 }155 }
156156
157 // Read a DER-encoded integer.157 // Read a DER-encoded integer.
158 // Asserts `br` has storage capacity >= 2.158 // Asserts `r` has storage capacity >= 2.
159 fn readDerInt(out: []u8, br: *std.io.BufferedReader) EncodingError!void {159 fn readDerInt(out: []u8, r: *std.io.Reader) EncodingError!void {
160 const buf = br.take(2) catch return error.InvalidEncoding;160 const buf = r.take(2) catch return error.InvalidEncoding;
161 if (buf[0] != 0x02) return error.InvalidEncoding;161 if (buf[0] != 0x02) return error.InvalidEncoding;
162 var expected_len: usize = buf[1];162 var expected_len: usize = buf[1];
163 if (expected_len == 0 or expected_len > 1 + out.len) return error.InvalidEncoding;163 if (expected_len == 0 or expected_len > 1 + out.len) return error.InvalidEncoding;
164 var has_top_bit = false;164 var has_top_bit = false;
165 if (expected_len == 1 + out.len) {165 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;
167 expected_len -= 1;167 expected_len -= 1;
168 has_top_bit = true;168 has_top_bit = true;
169 }169 }
170 const out_slice = out[out.len - expected_len ..];170 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;
172 if (@intFromBool(has_top_bit) != out[0] >> 7) return error.InvalidEncoding;172 if (@intFromBool(has_top_bit) != out[0] >> 7) return error.InvalidEncoding;
173 }173 }
174174
...@@ -176,14 +176,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {...@@ -176,14 +176,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
176 /// Returns InvalidEncoding if the DER encoding is invalid.176 /// Returns InvalidEncoding if the DER encoding is invalid.
177 pub fn fromDer(der: []const u8) EncodingError!Signature {177 pub fn fromDer(der: []const u8) EncodingError!Signature {
178 if (der.len < 2) return error.InvalidEncoding;178 if (der.len < 2) return error.InvalidEncoding;
179 var br: std.io.BufferedReader = undefined;179 var r: std.io.Reader = .fixed(der);
180 br.initFixed(@constCast(der));180 const buf = r.take(2) catch return error.InvalidEncoding;
181 const buf = br.take(2) catch return error.InvalidEncoding;
182 if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) return error.InvalidEncoding;181 if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) return error.InvalidEncoding;
183 var sig: Signature = mem.zeroInit(Signature, .{});182 var sig: Signature = mem.zeroInit(Signature, .{});
184 try readDerInt(&sig.r, &br);183 try readDerInt(&sig.r, &r);
185 try readDerInt(&sig.s, &br);184 try readDerInt(&sig.s, &r);
186 if (br.seek != der.len) return error.InvalidEncoding;185 if (r.seek != der.len) return error.InvalidEncoding;
187 return sig;186 return sig;
188 }187 }
189 };188 };
lib/std/crypto/tls.zig+2-2
...@@ -655,7 +655,7 @@ pub const Decoder = struct {...@@ -655,7 +655,7 @@ pub const Decoder = struct {
655 }655 }
656656
657 /// Use this function to increase `their_end`.657 /// 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 {
659 assert(!d.disable_reads);659 assert(!d.disable_reads);
660 const existing_amt = d.cap - d.idx;660 const existing_amt = d.cap - d.idx;
661 d.their_end = d.idx + their_amt;661 d.their_end = d.idx + their_amt;
...@@ -672,7 +672,7 @@ pub const Decoder = struct {...@@ -672,7 +672,7 @@ pub const Decoder = struct {
672672
673 /// Same as `readAtLeast` but also increases `our_end` by exactly `our_amt`.673 /// Same as `readAtLeast` but also increases `our_end` by exactly `our_amt`.
674 /// Use when `our_amt` is calculated by us, not by them.674 /// 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 {
676 assert(!d.disable_reads);676 assert(!d.disable_reads);
677 try readAtLeast(d, stream, our_amt);677 try readAtLeast(d, stream, our_amt);
678 d.our_end = d.idx + our_amt;678 d.our_end = d.idx + our_amt;
lib/std/crypto/tls/Client.zig+3-3
...@@ -21,7 +21,7 @@ const array = tls.array;...@@ -21,7 +21,7 @@ const array = tls.array;
21/// here via `reader`.21/// here via `reader`.
22///22///
23/// The buffer is asserted to have capacity at least `min_buffer_len`.23/// The buffer is asserted to have capacity at least `min_buffer_len`.
24input: *std.io.BufferedReader,24input: *std.io.Reader,
2525
26/// The encrypted stream from the client to the server. Bytes are pushed here26/// The encrypted stream from the client to the server. Bytes are pushed here
27/// via `writer`.27/// via `writer`.
...@@ -85,7 +85,7 @@ pub const SslKeyLog = struct {...@@ -85,7 +85,7 @@ pub const SslKeyLog = struct {
85 }85 }
86};86};
8787
88/// The `std.io.BufferedReader` supplied to `init` requires a buffer capacity88/// The `std.io.Reader` supplied to `init` requires a buffer capacity
89/// at least this amount.89/// at least this amount.
90pub const min_buffer_len = tls.max_ciphertext_record_len;90pub const min_buffer_len = tls.max_ciphertext_record_len;
9191
...@@ -175,7 +175,7 @@ const InitError = error{...@@ -175,7 +175,7 @@ const InitError = error{
175/// `input` is asserted to have buffer capacity at least `min_buffer_len`.175/// `input` is asserted to have buffer capacity at least `min_buffer_len`.
176pub fn init(176pub fn init(
177 client: *Client,177 client: *Client,
178 input: *std.io.BufferedReader,178 input: *std.io.Reader,
179 output: *std.io.BufferedWriter,179 output: *std.io.BufferedWriter,
180 options: Options,180 options: Options,
181) InitError!void {181) InitError!void {
lib/std/debug/Dwarf.zig+1-2
...@@ -2235,8 +2235,7 @@ pub const ElfModule = struct {...@@ -2235,8 +2235,7 @@ pub const ElfModule = struct {
22352235
2236 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);2236 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
2237 sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: {2237 sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: {
2238 var section_reader: std.io.BufferedReader = undefined;2238 var section_reader: std.io.Reader = .fixed(section_bytes);
2239 section_reader.initFixed(@constCast(section_bytes));
2240 const chdr = section_reader.takeStruct(elf.Chdr) catch continue;2239 const chdr = section_reader.takeStruct(elf.Chdr) catch continue;
2241 if (chdr.ch_type != .ZLIB) continue;2240 if (chdr.ch_type != .ZLIB) continue;
2242 const ch_size = chdr.ch_size;2241 const ch_size = chdr.ch_size;
lib/std/debug/Dwarf/call_frame.zig+1-1
...@@ -136,7 +136,7 @@ pub const Instruction = union(Opcode) {...@@ -136,7 +136,7 @@ pub const Instruction = union(Opcode) {
136 },136 },
137137
138 pub fn read(138 pub fn read(
139 reader: *std.io.BufferedReader,139 reader: *std.io.Reader,
140 addr_size_bytes: u8,140 addr_size_bytes: u8,
141 endian: std.builtin.Endian,141 endian: std.builtin.Endian,
142 ) !Instruction {142 ) !Instruction {
lib/std/debug/Dwarf/expression.zig+1-2
...@@ -774,8 +774,7 @@ pub fn StackMachine(comptime options: Options) type {...@@ -774,8 +774,7 @@ pub fn StackMachine(comptime options: Options) type {
774 }774 }
775775
776 fn nextLeb128(expression: []const u8, i: *usize, comptime I: type) !I {776 fn nextLeb128(expression: []const u8, i: *usize, comptime I: type) !I {
777 var br: std.io.BufferedReader = undefined;777 var br: std.io.Reader = .fixed(expression);
778 br.initFixed(@constCast(expression));
779 br.seek = i.*;778 br.seek = i.*;
780 assert(br.seek <= br.end);779 assert(br.seek <= br.end);
781 const result = br.takeLeb128(I) catch |err| switch (err) {780 const result = br.takeLeb128(I) catch |err| switch (err) {
lib/std/debug/FixedBufferReader.zig+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1//! Optimized for performance in debug builds.1//! Optimized for performance in debug builds.
22
3// TODO I'm pretty sure this can be deleted thanks to the new std.io.BufferedReader semantics3// TODO I'm pretty sure this can be deleted thanks to the new std.io.Reader semantics
44
5const std = @import("../std.zig");5const std = @import("../std.zig");
6const MemoryAccessor = std.debug.MemoryAccessor;6const MemoryAccessor = std.debug.MemoryAccessor;
...@@ -52,7 +52,7 @@ pub fn readIntChecked(...@@ -52,7 +52,7 @@ pub fn readIntChecked(
52}52}
5353
54pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T {54pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
55 var br: std.io.BufferedReader = undefined;55 var br: std.io.Reader = undefined;
56 br.initFixed(@constCast(fbr.buf));56 br.initFixed(@constCast(fbr.buf));
57 br.seek = fbr.pos;57 br.seek = fbr.pos;
58 const result = br.takeLeb128(T);58 const result = br.takeLeb128(T);
lib/std/debug/SelfInfo.zig+4-3
...@@ -2025,9 +2025,10 @@ pub const VirtualMachine = struct {...@@ -2025,9 +2025,10 @@ pub const VirtualMachine = struct {
2025 assert(self.cie_row == null);2025 assert(self.cie_row == null);
2026 if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return error.AddressOutOfRange;2026 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;2028 var readers: [2]std.io.Reader = .{
2029 readers[0].initFixed(@constCast(cie.initial_instructions));2029 .fixed(cie.initial_instructions),
2030 readers[1].initFixed(@constCast(fde.instructions));2030 .fixed(fde.instructions),
2031 };
20312032
2032 var prev_row: Row = self.current_row;2033 var prev_row: Row = self.current_row;
2033 for (&readers, [2]bool{ true, false }) |*reader, is_initial| {2034 for (&readers, [2]bool{ true, false }) |*reader, is_initial| {
lib/std/elf.zig+3-3
...@@ -510,10 +510,10 @@ pub const Header = struct {...@@ -510,10 +510,10 @@ pub const Header = struct {
510510
511 pub const ReadError = std.io.Reader.Error || ParseError;511 pub const ReadError = std.io.Reader.Error || ParseError;
512512
513 pub fn read(br: *std.io.BufferedReader) ReadError!Header {513 pub fn read(r: *std.io.Reader) ReadError!Header {
514 const buf = try br.peek(@sizeOf(Elf64_Ehdr));514 const buf = try r.peek(@sizeOf(Elf64_Ehdr));
515 const result = try parse(@ptrCast(buf));515 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));
517 return result;517 return result;
518 }518 }
519519
lib/std/fs/File.zig+18-11
...@@ -904,6 +904,7 @@ pub const Reader = struct {...@@ -904,6 +904,7 @@ pub const Reader = struct {
904 size: ?u64 = null,904 size: ?u64 = null,
905 size_err: ?GetEndPosError = null,905 size_err: ?GetEndPosError = null,
906 seek_err: ?Reader.SeekError = null,906 seek_err: ?Reader.SeekError = null,
907 interface: std.io.Reader,
907908
908 pub const SeekError = File.SeekError || error{909 pub const SeekError = File.SeekError || error{
909 /// Seeking fell back to reading, and reached the end before the requested seek position.910 /// Seeking fell back to reading, and reached the end before the requested seek position.
...@@ -940,18 +941,24 @@ pub const Reader = struct {...@@ -940,18 +941,24 @@ pub const Reader = struct {
940 }941 }
941 };942 };
942943
943 pub fn interface(r: *Reader) std.io.Reader {944 pub fn initInterface(buffer: []u8) std.io.Reader {
944 return .{945 return .{
945 .context = r,946 .context = undefined,
946 .vtable = &.{947 .vtable = &.{
947 .read = Reader.stream,948 .stream = Reader.stream,
948 .discard = Reader.discard,949 .discard = Reader.discard,
949 },950 },
951 .buffer = buffer,
952 .seek = 0,
953 .end = 0,
950 };954 };
951 }955 }
952956
953 pub fn readable(r: *Reader, buffer: []u8) std.io.BufferedReader {957 pub fn init(file: File, buffer: []u8) Reader {
954 return interface(r).buffered(buffer);958 return .{
959 .file = file,
960 .interface = initInterface(buffer),
961 };
955 }962 }
956963
957 pub fn getSize(r: *Reader) GetEndPosError!u64 {964 pub fn getSize(r: *Reader) GetEndPosError!u64 {
...@@ -1021,11 +1028,11 @@ pub const Reader = struct {...@@ -1021,11 +1028,11 @@ pub const Reader = struct {
1021 const max_buffers_len = 16;1028 const max_buffers_len = 16;
10221029
1023 fn stream(1030 fn stream(
1024 context: ?*anyopaque,1031 io_reader: *std.io.Reader,
1025 bw: *BufferedWriter,1032 bw: *BufferedWriter,
1026 limit: std.io.Limit,1033 limit: std.io.Limit,
1027 ) std.io.Reader.StreamError!usize {1034 ) std.io.Reader.StreamError!usize {
1028 const r: *Reader = @ptrCast(@alignCast(context));1035 const r: *Reader = @fieldParentPtr("interface", io_reader);
1029 switch (r.mode) {1036 switch (r.mode) {
1030 .positional, .streaming => return bw.writeFile(r, limit, &.{}, 0) catch |write_err| switch (write_err) {1037 .positional, .streaming => return bw.writeFile(r, limit, &.{}, 0) catch |write_err| switch (write_err) {
1031 error.ReadFailed => return error.ReadFailed,1038 error.ReadFailed => return error.ReadFailed,
...@@ -1051,8 +1058,8 @@ pub const Reader = struct {...@@ -1051,8 +1058,8 @@ pub const Reader = struct {
1051 }1058 }
1052 }1059 }
10531060
1054 fn discard(context: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize {1061 fn discard(io_reader: *std.io.Reader, limit: std.io.Limit) std.io.Reader.Error!usize {
1055 const r: *Reader = @ptrCast(@alignCast(context));1062 const r: *Reader = @fieldParentPtr("interface", io_reader);
1056 const file = r.file;1063 const file = r.file;
1057 const pos = r.pos;1064 const pos = r.pos;
1058 switch (r.mode) {1065 switch (r.mode) {
...@@ -1357,8 +1364,8 @@ pub const Writer = struct {...@@ -1357,8 +1364,8 @@ pub const Writer = struct {
1357///1364///
1358/// Positional is more threadsafe, since the global seek position is not1365/// Positional is more threadsafe, since the global seek position is not
1359/// affected.1366/// affected.
1360pub fn reader(file: File) Reader {1367pub fn reader(file: File, buffer: []u8) Reader {
1361 return .{ .file = file };1368 return .init(file, buffer);
1362}1369}
13631370
1364/// Positional is more threadsafe, since the global seek position is not1371/// 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 {...@@ -325,7 +325,7 @@ pub const Header = struct {
325};325};
326326
327pub const Reader = struct {327pub const Reader = struct {
328 in: *std.io.BufferedReader,328 in: *std.io.Reader,
329 /// Keeps track of whether the stream is ready to accept a new request,329 /// Keeps track of whether the stream is ready to accept a new request,
330 /// making invalid API usage cause assertion failures rather than HTTP330 /// making invalid API usage cause assertion failures rather than HTTP
331 /// protocol violations.331 /// protocol violations.
...@@ -703,7 +703,7 @@ pub const Reader = struct {...@@ -703,7 +703,7 @@ pub const Reader = struct {
703703
704pub const Decompressor = struct {704pub const Decompressor = struct {
705 compression: Compression,705 compression: Compression,
706 buffered_reader: std.io.BufferedReader,706 buffered_reader: std.io.Reader,
707707
708 pub const Compression = union(enum) {708 pub const Compression = union(enum) {
709 deflate: std.compress.flate.Decompressor,709 deflate: std.compress.flate.Decompressor,
lib/std/http/Client.zig+2-2
...@@ -232,7 +232,7 @@ pub const Connection = struct {...@@ -232,7 +232,7 @@ pub const Connection = struct {
232 writer: std.io.BufferedWriter,232 writer: std.io.BufferedWriter,
233 /// HTTP protocol from server to client.233 /// HTTP protocol from server to client.
234 /// This either comes directly from `stream_reader`, or from a TLS client.234 /// This either comes directly from `stream_reader`, or from a TLS client.
235 reader: std.io.BufferedReader,235 reader: std.io.Reader,
236 /// Entry in `ConnectionPool.used` or `ConnectionPool.free`.236 /// Entry in `ConnectionPool.used` or `ConnectionPool.free`.
237 pool_node: std.DoublyLinkedList.Node,237 pool_node: std.DoublyLinkedList.Node,
238 port: u16,238 port: u16,
...@@ -299,7 +299,7 @@ pub const Connection = struct {...@@ -299,7 +299,7 @@ pub const Connection = struct {
299 /// Data from `client` to `Connection.stream`.299 /// Data from `client` to `Connection.stream`.
300 writer: std.io.BufferedWriter,300 writer: std.io.BufferedWriter,
301 /// Data from `Connection.stream` to `client`.301 /// Data from `Connection.stream` to `client`.
302 reader: std.io.BufferedReader,302 reader: std.io.Reader,
303 client: std.crypto.tls.Client,303 client: std.crypto.tls.Client,
304 connection: Connection,304 connection: Connection,
305305
lib/std/http/Server.zig+2-2
...@@ -20,7 +20,7 @@ reader: http.Reader,...@@ -20,7 +20,7 @@ reader: http.Reader,
20/// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`.20/// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`.
21///21///
22/// The returned `Server` is ready for `receiveHead` to be called.22/// 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 {
24 return .{24 return .{
25 .reader = .{25 .reader = .{
26 .in = in,26 .in = in,
...@@ -610,7 +610,7 @@ pub const Request = struct {...@@ -610,7 +610,7 @@ pub const Request = struct {
610/// See https://tools.ietf.org/html/rfc6455610/// See https://tools.ietf.org/html/rfc6455
611pub const WebSocket = struct {611pub const WebSocket = struct {
612 key: []const u8,612 key: []const u8,
613 input: *std.io.BufferedReader,613 input: *std.io.Reader,
614 output: *std.io.BufferedWriter,614 output: *std.io.BufferedWriter,
615615
616 pub const Header0 = packed struct(u8) {616 pub const Header0 = packed struct(u8) {
lib/std/io.zig+11-15
...@@ -72,8 +72,6 @@ pub const Limit = enum(usize) {...@@ -72,8 +72,6 @@ pub const Limit = enum(usize) {
72pub const Reader = @import("io/Reader.zig");72pub const Reader = @import("io/Reader.zig");
73pub const Writer = @import("io/Writer.zig");73pub const Writer = @import("io/Writer.zig");
7474
75pub const BufferedReader = @import("io/BufferedReader.zig");
76pub const BufferedWriter = @import("io/BufferedWriter.zig");
77pub const AllocatingWriter = @import("io/AllocatingWriter.zig");75pub const AllocatingWriter = @import("io/AllocatingWriter.zig");
7876
79pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;77pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;
...@@ -131,7 +129,7 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -131,7 +129,7 @@ pub fn Poller(comptime StreamEnum: type) type {
131 const PollFd = if (is_windows) void else posix.pollfd;129 const PollFd = if (is_windows) void else posix.pollfd;
132130
133 gpa: Allocator,131 gpa: Allocator,
134 readers: [enum_fields.len]BufferedReader,132 readers: [enum_fields.len]Reader,
135 poll_fds: [enum_fields.len]PollFd,133 poll_fds: [enum_fields.len]PollFd,
136 windows: if (is_windows) struct {134 windows: if (is_windows) struct {
137 first_read_done: bool,135 first_read_done: bool,
...@@ -163,7 +161,7 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -163,7 +161,7 @@ pub fn Poller(comptime StreamEnum: type) type {
163 _ = windows.kernel32.CancelIo(h);161 _ = windows.kernel32.CancelIo(h);
164 }162 }
165 }163 }
166 inline for (&self.readers) |*br| gpa.free(br.buffer);164 inline for (&self.readers) |*r| gpa.free(r.buffer);
167 self.* = undefined;165 self.* = undefined;
168 }166 }
169167
...@@ -183,7 +181,7 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -183,7 +181,7 @@ pub fn Poller(comptime StreamEnum: type) type {
183 }181 }
184 }182 }
185183
186 pub inline fn reader(self: *Self, comptime which: StreamEnum) *BufferedReader {184 pub inline fn reader(self: *Self, comptime which: StreamEnum) *Reader {
187 return &self.readers[@intFromEnum(which)];185 return &self.readers[@intFromEnum(which)];
188 }186 }
189187
...@@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type {
295 }293 }
296294
297 var keep_polling = false;295 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| {
299 // Try reading whatever is available before checking the error297 // Try reading whatever is available before checking the error
300 // conditions.298 // conditions.
301 // It's still possible to read after a POLL.HUP is received,299 // It's still possible to read after a POLL.HUP is received,
302 // always check if there's some data waiting to be read first.300 // always check if there's some data waiting to be read first.
303 if (poll_fd.revents & posix.POLL.IN != 0) {301 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);
305 const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) {303 const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) {
306 error.BrokenPipe => 0, // Handle the same as EOF.304 error.BrokenPipe => 0, // Handle the same as EOF.
307 else => |e| return e,305 else => |e| return e,
308 };306 };
309 br.advanceBufferEnd(amt);307 r.advanceBufferEnd(amt);
310 if (amt == 0) {308 if (amt == 0) {
311 // Remove the fd when the EOF condition is met.309 // Remove the fd when the EOF condition is met.
312 poll_fd.fd = -1;310 poll_fd.fd = -1;
...@@ -337,14 +335,14 @@ var win_dummy_bytes_read: u32 = undefined;...@@ -337,14 +335,14 @@ var win_dummy_bytes_read: u32 = undefined;
337fn windowsAsyncReadToFifoAndQueueSmallRead(335fn windowsAsyncReadToFifoAndQueueSmallRead(
338 handle: windows.HANDLE,336 handle: windows.HANDLE,
339 overlapped: *windows.OVERLAPPED,337 overlapped: *windows.OVERLAPPED,
340 br: *BufferedReader,338 r: *Reader,
341 small_buf: *[128]u8,339 small_buf: *[128]u8,
342 bump_amt: usize,340 bump_amt: usize,
343) !enum { empty, populated, closed_populated, closed } {341) !enum { empty, populated, closed_populated, closed } {
344 var read_any_data = false;342 var read_any_data = false;
345 while (true) {343 while (true) {
346 const fifo_read_pending = while (true) {344 const fifo_read_pending = while (true) {
347 const buf = try br.writableWithSize(bump_amt);345 const buf = try r.writableWithSize(bump_amt);
348 const buf_len = math.cast(u32, buf.len) orelse math.maxInt(u32);346 const buf_len = math.cast(u32, buf.len) orelse math.maxInt(u32);
349347
350 if (0 == windows.kernel32.ReadFile(348 if (0 == windows.kernel32.ReadFile(
...@@ -366,7 +364,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(...@@ -366,7 +364,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
366 };364 };
367365
368 read_any_data = true;366 read_any_data = true;
369 br.update(num_bytes_read);367 r.update(num_bytes_read);
370368
371 if (num_bytes_read == buf_len) {369 if (num_bytes_read == buf_len) {
372 // We filled the buffer, so there's probably more data available.370 // We filled the buffer, so there's probably more data available.
...@@ -396,7 +394,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(...@@ -396,7 +394,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
396 .aborted => break :cancel_read,394 .aborted => break :cancel_read,
397 };395 };
398 read_any_data = true;396 read_any_data = true;
399 br.update(num_bytes_read);397 r.update(num_bytes_read);
400 }398 }
401399
402 // Try to queue the 1-byte read.400 // Try to queue the 1-byte read.
...@@ -421,7 +419,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(...@@ -421,7 +419,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead(
421 .closed => return if (read_any_data) .closed_populated else .closed,419 .closed => return if (read_any_data) .closed_populated else .closed,
422 .aborted => unreachable,420 .aborted => unreachable,
423 };421 };
424 try br.write(small_buf[0..num_bytes_read]);422 try r.write(small_buf[0..num_bytes_read]);
425 read_any_data = true;423 read_any_data = true;
426 }424 }
427}425}
...@@ -488,8 +486,6 @@ pub fn PollFiles(comptime StreamEnum: type) type {...@@ -488,8 +486,6 @@ pub fn PollFiles(comptime StreamEnum: type) type {
488486
489test {487test {
490 _ = AllocatingWriter;488 _ = AllocatingWriter;
491 _ = BufferedReader;
492 _ = BufferedWriter;
493 _ = Reader;489 _ = Reader;
494 _ = Writer;490 _ = Writer;
495 _ = @import("io/test.zig");491 _ = @import("io/test.zig");
lib/std/io/AllocatingWriter.zig+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6//! `std.io.BufferedWriter` state such that it writes to the unused capacity of6//! `std.io.BufferedWriter` state such that it writes to the unused capacity of
7//! an array list, filling it up completely before making a call through the7//! an array list, filling it up completely before making a call through the
8//! vtable, causing a resize. Consequently, the same, optimized, non-generic8//! 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,
10//! takes the hot paths when using this API.10//! takes the hot paths when using this API.
1111
12const std = @import("../std.zig");12const 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 @@...@@ -1,8 +1,12 @@
1const std = @import("../std.zig");
2const Reader = @This();1const 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;
3const assert = std.debug.assert;8const assert = std.debug.assert;
4const BufferedWriter = std.io.BufferedWriter;9const testing = std.testing;
5const BufferedReader = std.io.BufferedReader;
6const Allocator = std.mem.Allocator;10const Allocator = std.mem.Allocator;
7const ArrayList = std.ArrayListUnmanaged;11const ArrayList = std.ArrayListUnmanaged;
8const Limit = std.io.Limit;12const Limit = std.io.Limit;
...@@ -11,9 +15,14 @@ pub const Limited = @import("Reader/Limited.zig");...@@ -11,9 +15,14 @@ pub const Limited = @import("Reader/Limited.zig");
1115
12context: ?*anyopaque,16context: ?*anyopaque,
13vtable: *const VTable,17vtable: *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
15pub const VTable = struct {24pub 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`.
17 ///26 ///
18 /// Returns the number of bytes written, which will be at minimum `0` and27 /// Returns the number of bytes written, which will be at minimum `0` and
19 /// at most `limit`. The number returned, including zero, does not indicate28 /// at most `limit`. The number returned, including zero, does not indicate
...@@ -26,7 +35,7 @@ pub const VTable = struct {...@@ -26,7 +35,7 @@ pub const VTable = struct {
26 /// Implementations are encouraged to utilize mandatory minimum buffer35 /// Implementations are encouraged to utilize mandatory minimum buffer
27 /// sizes combined with short reads (returning a value less than `limit`)36 /// sizes combined with short reads (returning a value less than `limit`)
28 /// in order to minimize complexity.37 /// 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
31 /// Consumes bytes from the internally tracked stream position without40 /// Consumes bytes from the internally tracked stream position without
32 /// providing access to them.41 /// providing access to them.
...@@ -42,11 +51,10 @@ pub const VTable = struct {...@@ -42,11 +51,10 @@ pub const VTable = struct {
42 /// sizes combined with short reads (returning a value less than `limit`)51 /// sizes combined with short reads (returning a value less than `limit`)
43 /// in order to minimize complexity.52 /// in order to minimize complexity.
44 ///53 ///
45 /// If an implementation sets this to `null`, a default implementation is54 /// The default implementation is is based on calling `read`, borrowing
46 /// provided which is based on calling `read`, borrowing55 /// `buffer` to construct a temporary `Writer` and ignoring the written
47 /// `BufferedReader.buffer` to construct a temporary `BufferedWriter` and56 /// data.
48 /// ignoring the written data.57 discard: *const fn (r: *Reader, limit: Limit) Error!usize = defaultDiscard,
49 discard: ?*const fn (context: ?*anyopaque, limit: Limit) Error!usize = null,
50};58};
5159
52pub const StreamError = error{60pub const StreamError = error{
...@@ -77,26 +85,97 @@ pub const ShortError = error{...@@ -77,26 +85,97 @@ pub const ShortError = error{
77 ReadFailed,85 ReadFailed,
78};86};
7987
80pub fn read(r: Reader, bw: *BufferedWriter, limit: Limit) StreamError!usize {88pub const failing: Reader = .{
81 const before = bw.count;89 .context = undefined,
82 const n = try r.vtable.read(r.context, bw, limit);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);
83 assert(n <= @intFromEnum(limit));131 assert(n <= @intFromEnum(limit));
84 assert(bw.count == before + n);132 assert(w.count == before + n);
85 return n;133 return n;
86}134}
87135
88pub fn discard(r: Reader, limit: Limit) Error!usize {136pub fn discard(r: *Reader, limit: Limit) Error!usize {
89 const n = try r.vtable.discard(r.context, limit);137 const buffered_len = r.end - r.seek;
90 assert(n <= @intFromEnum(limit));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 }
91 return n;168 return n;
92}169}
93170
94/// Returns total number of bytes written to `bw`.171/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
95pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize {172/// a success case.
96 const readFn = r.vtable.read;173///
174/// Returns total number of bytes written to `w`.
175pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize {
97 var offset: usize = 0;176 var offset: usize = 0;
98 while (true) {177 while (true) {
99 offset += readFn(r.context, bw, .unlimited) catch |err| switch (err) {178 offset += r.stream(w, .unlimited) catch |err| switch (err) {
100 error.EndOfStream => return offset,179 error.EndOfStream => return offset,
101 else => |e| return e,180 else => |e| return e,
102 };181 };
...@@ -105,11 +184,12 @@ pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize...@@ -105,11 +184,12 @@ pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize
105184
106/// Consumes the stream until the end, ignoring all the data, returning the185/// Consumes the stream until the end, ignoring all the data, returning the
107/// number of bytes discarded.186/// number of bytes discarded.
108pub fn discardRemaining(r: Reader) ShortError!usize {187pub fn discardRemaining(r: *Reader) ShortError!usize {
109 const discardFn = r.vtable.discard;188 var offset: usize = r.end;
110 var offset: usize = 0;189 r.seek = 0;
190 r.end = 0;
111 while (true) {191 while (true) {
112 offset += discardFn(r.context, .unlimited) catch |err| switch (err) {192 offset += r.vtable.discard(r, .unlimited) catch |err| switch (err) {
113 error.EndOfStream => return offset,193 error.EndOfStream => return offset,
114 else => |e| return e,194 else => |e| return e,
115 };195 };
...@@ -121,112 +201,1133 @@ pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLo...@@ -121,112 +201,1133 @@ pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLo
121/// Transfers all bytes from the current position to the end of the stream, up201/// Transfers all bytes from the current position to the end of the stream, up
122/// to `limit`, returning them as a caller-owned allocated slice.202/// to `limit`, returning them as a caller-owned allocated slice.
123///203///
124/// If `limit` is exceeded, returns `error.StreamTooLong`. In such case, the204/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
125/// stream is advanced one byte beyond the limit, and the consumed data is205/// such case, the next byte that would be read will be the first one to exceed
126/// unrecoverable. Other functions listed below do not have this caveat.206/// `limit`, and all preceeding bytes have been discarded.
207///
208/// Asserts `buffer` has nonzero capacity.
127///209///
128/// See also:210/// See also:
129/// * `readRemainingArrayList`211/// * `appendRemaining`
130/// * `BufferedReader.readRemainingArrayList`212pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 {
131pub fn readRemainingAlloc(r: Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 {
132 var buffer: ArrayList(u8) = .empty;213 var buffer: ArrayList(u8) = .empty;
133 defer buffer.deinit(gpa);214 defer buffer.deinit(gpa);
134 try readRemainingArrayList(r, gpa, null, &buffer, limit, 1);215 try appendRemaining(r, gpa, null, &buffer, limit, 1);
135 return buffer.toOwnedSlice(gpa);216 return buffer.toOwnedSlice(gpa);
136}217}
137218
138/// Transfers all bytes from the current position to the end of the stream, up219/// Transfers all bytes from the current position to the end of the stream, up
139/// to `limit`, appending them to `list`.220/// to `limit`, appending them to `list`.
140///221///
141/// If `limit` is exceeded:222/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
142/// * The array list's length is increased by exactly one byte past `limit`.223/// such case, the next byte that would be read will be the first one to exceed
143/// * The stream seek position is advanced by exactly one byte past `limit`.224/// `limit`, and all preceeding bytes have been appended to `list`.
144/// * `error.StreamTooLong` is returned.
145///225///
146/// The other function listed below has different semantics for an exceeded226/// Asserts `buffer` has nonzero capacity.
147/// limit.
148///227///
149/// See also:228/// See also:
150/// * `BufferedReader.readRemainingArrayList`229/// * `allocRemaining`
151pub fn readRemainingArrayList(230pub fn appendRemaining(
152 r: Reader,231 r: *Reader,
153 gpa: Allocator,232 gpa: Allocator,
154 comptime alignment: ?std.mem.Alignment,233 comptime alignment: ?std.mem.Alignment,
155 list: *std.ArrayListAlignedUnmanaged(u8, alignment),234 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
156 limit: Limit,235 limit: Limit,
157 minimum_buffer_size: usize,
158) LimitedAllocError!void {236) 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).?;
160 while (true) {249 while (true) {
161 try list.ensureUnusedCapacity(gpa, minimum_buffer_size);250 try list.ensureUnusedCapacity(gpa, 1);
162 const buffer = remaining.slice1(list.unusedCapacitySlice());251 const dest = remaining.slice(list.unusedCapacitySlice());
163 const n = r.vtable.readVec(r.context, &.{buffer}) catch |err| switch (err) {252 const additional_buffer = if (@intFromEnum(remaining) == dest.len) buffer else &.{};
164 error.EndOfStream => return,253 const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) {
254 error.EndOfStream => break,
165 error.ReadFailed => return error.ReadFailed,255 error.ReadFailed => return error.ReadFailed,
166 };256 };
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 }
167 list.items.len += n;263 list.items.len += n;
168 remaining = remaining.subtract(n) orelse return error.StreamTooLong;264 remaining = remaining.subtract(n).?;
169 }265 }
170}266}
171267
172pub const failing: Reader = .{268/// Writes bytes from the internally tracked stream position to `data`.
173 .context = undefined,269///
174 .vtable = &.{270/// Returns the number of bytes written, which will be at minimum `0` and
175 .read = failingRead,271/// at most the sum of each data slice length. The number of bytes read,
176 .discard = failingDiscard,272/// including zero, does not indicate end of stream.
177 },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,
178};643};
179644
180pub const ending: Reader = .{645/// Returns a slice of the next bytes of buffered data from the stream until
181 .context = undefined,646/// `sentinel` is found, advancing the seek position.
182 .vtable = &.{647///
183 .read = endingRead,648/// Returned slice has a sentinel.
184 .discard = endingDiscard,649///
185 },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,
186};813};
187814
188pub fn unbuffered(r: Reader) BufferedReader {815/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
189 return buffered(r, &.{});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 };
190}831}
191832
192pub fn buffered(r: Reader, buffer: []u8) BufferedReader {833fn readAny(
193 return .{834 r: *Reader,
194 .unbuffered_reader = r,835 bw: *Writer,
195 .seek = 0,836 delimiter: ?u8,
196 .buffer = buffer,837 limit: Limit,
197 .end = 0,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,
198 };1016 };
199}1017}
2001018
201pub fn limited(r: Reader, limit: Limit) Limited {1019pub const TakeLeb128Error = Error || error{Overflow};
202 return .{1020
203 .unlimited_reader = r,1021/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.
204 .remaining = limit,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,
205 };1036 };
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;
206}1116}
2071117
208fn endingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize {1118/// Ensures `capacity` more data can be buffered without rebasing, by rebasing
209 _ = context;1119/// if necessary.
210 _ = bw;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;
211 _ = limit;1312 _ = limit;
212 return error.EndOfStream;1313 return error.EndOfStream;
213}1314}
2141315
215fn endingDiscard(context: ?*anyopaque, limit: Limit) Error!usize {1316fn endingDiscard(r: *Reader, limit: Limit) Error!usize {
216 _ = context;1317 _ = r;
217 _ = limit;1318 _ = limit;
218 return error.EndOfStream;1319 return error.EndOfStream;
219}1320}
2201321
221fn failingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize {1322fn failingRead(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
222 _ = context;1323 _ = r;
223 _ = bw;1324 _ = w;
224 _ = limit;1325 _ = limit;
225 return error.ReadFailed;1326 return error.ReadFailed;
226}1327}
2271328
228fn failingDiscard(context: ?*anyopaque, limit: Limit) Error!usize {1329fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
229 _ = context;1330 _ = r;
230 _ = limit;1331 _ = limit;
231 return error.ReadFailed;1332 return error.ReadFailed;
232}1333}
...@@ -270,46 +1371,31 @@ test "readAlloc when the backing reader provides one byte at a time" {...@@ -270,46 +1371,31 @@ test "readAlloc when the backing reader provides one byte at a time" {
270/// implementation details.1371/// implementation details.
271pub fn Hashed(comptime Hasher: type) type {1372pub fn Hashed(comptime Hasher: type) type {
272 return struct {1373 return struct {
273 in: *BufferedReader,1374 in: *Reader,
274 hasher: Hasher,1375 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() {
277 return .{1379 return .{
278 .unbuffered_reader = .{1380 .in = in,
279 .context = this,1381 .hasher = hasher,
1382 .interface = .{
280 .vtable = &.{1383 .vtable = &.{
281 .read = @This().read,1384 .read = @This().read,
282 .discard = @This().discard,1385 .discard = @This().discard,
283 },1386 },
1387 .buffer = buffer,
1388 .end = 0,
1389 .seek = 0,
284 },1390 },
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,
306 };1391 };
307 return n;
308 }1392 }
3091393
310 fn readVec(context: ?*anyopaque, data: []const []u8) Error!usize {1394 fn read(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
311 const this: *@This() = @alignCast(@ptrCast(context));1395 const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1396 const data = w.writableVector(limit);
312 const n = try this.in.readVec(data);1397 const n = try this.in.readVec(data);
1398 w.advanceVector(n);
313 var remaining: usize = n;1399 var remaining: usize = n;
314 for (data) |slice| {1400 for (data) |slice| {
315 if (remaining < slice.len) {1401 if (remaining < slice.len) {
...@@ -323,5 +1409,15 @@ pub fn Hashed(comptime Hasher: type) type {...@@ -323,5 +1409,15 @@ pub fn Hashed(comptime Hasher: type) type {
323 assert(remaining == 0);1409 assert(remaining == 0);
324 return n;1410 return n;
325 }1411 }
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 }
326 };1422 };
327}1423}
lib/std/io/Reader/Limited.zig+15-29
...@@ -5,21 +5,27 @@ const Reader = std.io.Reader;...@@ -5,21 +5,27 @@ const Reader = std.io.Reader;
5const BufferedWriter = std.io.BufferedWriter;5const BufferedWriter = std.io.BufferedWriter;
6const Limit = std.io.Limit;6const Limit = std.io.Limit;
77
8unlimited_reader: Reader,8unlimited: *Reader,
9remaining: Limit,9remaining: Limit,
10interface: Reader,
1011
11pub fn reader(l: *Limited) Reader {12pub fn init(reader: *Reader, limit: Limit, buffer: []u8) Limited {
12 return .{13 return .{
13 .context = l,14 .unlimited = reader,
14 .vtable = &.{15 .remaining = limit,
15 .read = passthruRead,16 .interface = .{
16 .readVec = passthruReadVec,17 .vtable = &.{
17 .discard = passthruDiscard,18 .stream = stream,
19 .discard = discard,
20 },
21 .buffer = buffer,
22 .seek = 0,
23 .end = 0,
18 },24 },
19 };25 };
20}26}
2127
22fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {28fn stream(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {
23 const l: *Limited = @alignCast(@ptrCast(context));29 const l: *Limited = @alignCast(@ptrCast(context));
24 const combined_limit = limit.min(l.remaining);30 const combined_limit = limit.min(l.remaining);
25 const n = try l.unlimited_reader.read(bw, combined_limit);31 const n = try l.unlimited_reader.read(bw, combined_limit);
...@@ -27,30 +33,10 @@ fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader....@@ -27,30 +33,10 @@ fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.
27 return n;33 return n;
28}34}
2935
30fn passthruDiscard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {36fn discard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
31 const l: *Limited = @alignCast(@ptrCast(context));37 const l: *Limited = @alignCast(@ptrCast(context));
32 const combined_limit = limit.min(l.remaining);38 const combined_limit = limit.min(l.remaining);
33 const n = try l.unlimited_reader.discard(combined_limit);39 const n = try l.unlimited_reader.discard(combined_limit);
34 l.remaining = l.remaining.subtract(n).?;40 l.remaining = l.remaining.subtract(n).?;
35 return n;41 return n;
36}42}
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 {...@@ -114,32 +114,27 @@ test writeSignedFixed {
114}114}
115115
116fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {116fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
117 var br: std.io.BufferedReader = undefined;117 var br: std.io.Reader = .fixed(encoded);
118 br.initFixed(encoded);
119 return br.takeIleb128(T);118 return br.takeIleb128(T);
120}119}
121120
122fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {121fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {
123 var br: std.io.BufferedReader = undefined;122 var br: std.io.Reader = .fixed(encoded);
124 br.initFixed(encoded);
125 return br.takeUleb128(T);123 return br.takeUleb128(T);
126}124}
127125
128fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {126fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
129 var br: std.io.BufferedReader = undefined;127 var br: std.io.Reader = .fixed(encoded);
130 br.initFixed(encoded);
131 return br.readIleb128(T);128 return br.readIleb128(T);
132}129}
133130
134fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {131fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
135 var br: std.io.BufferedReader = undefined;132 var br: std.io.Reader = .fixed(encoded);
136 br.initFixed(encoded);
137 return br.readUleb128(T);133 return br.readUleb128(T);
138}134}
139135
140fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {136fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {
141 var br: std.io.BufferedReader = undefined;137 var br: std.io.Reader = .fixed(encoded);
142 br.initFixed(encoded);
143 var i: usize = 0;138 var i: usize = 0;
144 while (i < N) : (i += 1) {139 while (i < N) : (i += 1) {
145 _ = try br.readIleb128(T);140 _ = try br.readIleb128(T);
...@@ -147,8 +142,7 @@ fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u...@@ -147,8 +142,7 @@ fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u
147}142}
148143
149fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {144fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void {
150 var br: std.io.BufferedReader = undefined;145 var br: std.io.Reader = .fixed(encoded);
151 br.initFixed(encoded);
152 var i: usize = 0;146 var i: usize = 0;
153 while (i < N) : (i += 1) {147 while (i < N) : (i += 1) {
154 _ = try br.readUleb128(T);148 _ = try br.readUleb128(T);
...@@ -248,7 +242,7 @@ fn test_write_leb128(value: anytype) !void {...@@ -248,7 +242,7 @@ fn test_write_leb128(value: anytype) !void {
248 const t_signed = signedness == .signed;242 const t_signed = signedness == .signed;
249243
250 const writeStream = if (t_signed) std.io.BufferedWriter.writeIleb128 else std.io.BufferedWriter.writeUleb128;244 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
253 // decode to a larger bit size too, to ensure sign extension247 // decode to a larger bit size too, to ensure sign extension
254 // is working as expected248 // is working as expected
...@@ -275,8 +269,7 @@ fn test_write_leb128(value: anytype) !void {...@@ -275,8 +269,7 @@ fn test_write_leb128(value: anytype) !void {
275 try testing.expect(bw.buffer.items.len == bytes_needed);269 try testing.expect(bw.buffer.items.len == bytes_needed);
276270
277 // stream read271 // stream read
278 var br: std.io.BufferedReader = undefined;272 var br: std.io.Reader = .fixed(&buf);
279 br.initFixed(&buf);
280 const sr = try readStream(&br, T);273 const sr = try readStream(&br, T);
281 try testing.expect(br.seek == bytes_needed);274 try testing.expect(br.seek == bytes_needed);
282 try testing.expect(sr == value);275 try testing.expect(sr == value);
lib/std/net.zig+2-2
...@@ -1378,7 +1378,7 @@ fn parseHosts(...@@ -1378,7 +1378,7 @@ fn parseHosts(
1378 name: []const u8,1378 name: []const u8,
1379 family: posix.sa_family_t,1379 family: posix.sa_family_t,
1380 port: u16,1380 port: u16,
1381 br: *std.io.BufferedReader,1381 br: *std.io.Reader,
1382) error{ OutOfMemory, ReadFailed }!void {1382) error{ OutOfMemory, ReadFailed }!void {
1383 while (true) {1383 while (true) {
1384 const line = br.takeDelimiterExclusive('\n') catch |err| switch (err) {1384 const line = br.takeDelimiterExclusive('\n') catch |err| switch (err) {
...@@ -1592,7 +1592,7 @@ const ResolvConf = struct {...@@ -1592,7 +1592,7 @@ const ResolvConf = struct {
1592 };1592 };
1593 }1593 }
15941594
1595 fn parse(rc: *ResolvConf, br: *std.io.BufferedReader) !void {1595 fn parse(rc: *ResolvConf, br: *std.io.Reader) !void {
1596 const gpa = rc.gpa;1596 const gpa = rc.gpa;
1597 while (br.takeSentinel('\n')) |line_with_comment| {1597 while (br.takeSentinel('\n')) |line_with_comment| {
1598 const line = line: {1598 const line = line: {
lib/std/process/Child.zig+5-5
...@@ -348,15 +348,15 @@ pub const RunResult = struct {...@@ -348,15 +348,15 @@ pub const RunResult = struct {
348 stderr: []u8,348 stderr: []u8,
349};349};
350350
351fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), br: *std.io.BufferedReader) !void {351fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), r: *std.io.Reader) !void {
352 assert(br.seek == 0);352 assert(r.seek == 0);
353 if (list.capacity == 0) {353 if (list.capacity == 0) {
354 list.* = .{354 list.* = .{
355 .items = br.bufferContents(),355 .items = r.bufferContents(),
356 .capacity = br.buffer.len,356 .capacity = r.buffer.len,
357 };357 };
358 } else {358 } else {
359 try list.appendSlice(allocator, br.bufferContents());359 try list.appendSlice(allocator, r.bufferContents());
360 }360 }
361}361}
362362
lib/std/tar.zig+15-15
...@@ -302,7 +302,7 @@ pub const FileKind = enum {...@@ -302,7 +302,7 @@ pub const FileKind = enum {
302302
303/// Iterator over entries in the tar file represented by reader.303/// Iterator over entries in the tar file represented by reader.
304pub const Iterator = struct {304pub const Iterator = struct {
305 reader: *std.io.BufferedReader,305 reader: *std.io.Reader,
306 diagnostics: ?*Diagnostics = null,306 diagnostics: ?*Diagnostics = null,
307307
308 // buffers for heeader and file attributes308 // buffers for heeader and file attributes
...@@ -328,7 +328,7 @@ pub const Iterator = struct {...@@ -328,7 +328,7 @@ pub const Iterator = struct {
328328
329 /// Iterates over files in tar archive.329 /// Iterates over files in tar archive.
330 /// `next` returns each file in tar archive.330 /// `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 {
332 return .{332 return .{
333 .reader = reader,333 .reader = reader,
334 .diagnostics = options.diagnostics,334 .diagnostics = options.diagnostics,
...@@ -345,7 +345,7 @@ pub const Iterator = struct {...@@ -345,7 +345,7 @@ pub const Iterator = struct {
345 kind: FileKind = .file,345 kind: FileKind = .file,
346346
347 unread_bytes: *u64,347 unread_bytes: *u64,
348 parent_reader: *std.io.BufferedReader,348 parent_reader: *std.io.Reader,
349349
350 pub fn reader(self: *File) std.io.Reader {350 pub fn reader(self: *File) std.io.Reader {
351 return .{351 return .{
...@@ -537,14 +537,14 @@ const pax_max_size_attr_len = 64;...@@ -537,14 +537,14 @@ const pax_max_size_attr_len = 64;
537537
538pub const PaxIterator = struct {538pub const PaxIterator = struct {
539 size: usize, // cumulative size of all pax attributes539 size: usize, // cumulative size of all pax attributes
540 reader: *std.io.BufferedReader,540 reader: *std.io.Reader,
541541
542 const Self = @This();542 const Self = @This();
543543
544 const Attribute = struct {544 const Attribute = struct {
545 kind: PaxAttributeKind,545 kind: PaxAttributeKind,
546 len: usize, // length of the attribute value546 len: usize, // length of the attribute value
547 reader: *std.io.BufferedReader, // reader positioned at value start547 reader: *std.io.Reader, // reader positioned at value start
548548
549 // Copies pax attribute value into destination buffer.549 // Copies pax attribute value into destination buffer.
550 // Must be called with destination buffer of size at least Attribute.len.550 // Must be called with destination buffer of size at least Attribute.len.
...@@ -611,13 +611,13 @@ pub const PaxIterator = struct {...@@ -611,13 +611,13 @@ pub const PaxIterator = struct {
611 }611 }
612612
613 // Checks that each record ends with new line.613 // Checks that each record ends with new line.
614 fn validateAttributeEnding(reader: *std.io.BufferedReader) !void {614 fn validateAttributeEnding(reader: *std.io.Reader) !void {
615 if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd;615 if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd;
616 }616 }
617};617};
618618
619/// Saves tar file content to the file systems.619/// 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 {
621 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;621 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
622 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;622 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
623 var iter: Iterator = .init(reader, .{623 var iter: Iterator = .init(reader, .{
...@@ -818,7 +818,7 @@ test PaxIterator {...@@ -818,7 +818,7 @@ test PaxIterator {
818 var buffer: [1024]u8 = undefined;818 var buffer: [1024]u8 = undefined;
819819
820 outer: for (cases) |case| {820 outer: for (cases) |case| {
821 var br: std.io.BufferedReader = undefined;821 var br: std.io.Reader = undefined;
822 br.initFixed(case.data);822 br.initFixed(case.data);
823 var iter: PaxIterator = .init(&br, case.data.len);823 var iter: PaxIterator = .init(&br, case.data.len);
824824
...@@ -955,7 +955,7 @@ test Iterator {...@@ -955,7 +955,7 @@ test Iterator {
955 // example/empty/955 // example/empty/
956956
957 const data = @embedFile("tar/testdata/example.tar");957 const data = @embedFile("tar/testdata/example.tar");
958 var br: std.io.BufferedReader = undefined;958 var br: std.io.Reader = undefined;
959 br.initFixed(data);959 br.initFixed(data);
960960
961 // User provided buffers to the iterator961 // User provided buffers to the iterator
...@@ -1015,7 +1015,7 @@ test pipeToFileSystem {...@@ -1015,7 +1015,7 @@ test pipeToFileSystem {
1015 // example/empty/1015 // example/empty/
10161016
1017 const data = @embedFile("tar/testdata/example.tar");1017 const data = @embedFile("tar/testdata/example.tar");
1018 var br: std.io.BufferedReader = undefined;1018 var br: std.io.Reader = undefined;
1019 br.initFixed(data);1019 br.initFixed(data);
10201020
1021 var tmp = testing.tmpDir(.{ .no_follow = true });1021 var tmp = testing.tmpDir(.{ .no_follow = true });
...@@ -1047,7 +1047,7 @@ test pipeToFileSystem {...@@ -1047,7 +1047,7 @@ test pipeToFileSystem {
10471047
1048test "pipeToFileSystem root_dir" {1048test "pipeToFileSystem root_dir" {
1049 const data = @embedFile("tar/testdata/example.tar");1049 const data = @embedFile("tar/testdata/example.tar");
1050 var br: std.io.BufferedReader = undefined;1050 var br: std.io.Reader = undefined;
1051 br.initFixed(data);1051 br.initFixed(data);
10521052
1053 // with strip_components = 11053 // with strip_components = 1
...@@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" {...@@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" {
10961096
1097test "findRoot with single file archive" {1097test "findRoot with single file archive" {
1098 const data = @embedFile("tar/testdata/22752.tar");1098 const data = @embedFile("tar/testdata/22752.tar");
1099 var br: std.io.BufferedReader = undefined;1099 var br: std.io.Reader = undefined;
1100 br.initFixed(data);1100 br.initFixed(data);
11011101
1102 var tmp = testing.tmpDir(.{});1102 var tmp = testing.tmpDir(.{});
...@@ -1111,7 +1111,7 @@ test "findRoot with single file archive" {...@@ -1111,7 +1111,7 @@ test "findRoot with single file archive" {
11111111
1112test "findRoot without explicit root dir" {1112test "findRoot without explicit root dir" {
1113 const data = @embedFile("tar/testdata/19820.tar");1113 const data = @embedFile("tar/testdata/19820.tar");
1114 var br: std.io.BufferedReader = undefined;1114 var br: std.io.Reader = undefined;
1115 br.initFixed(data);1115 br.initFixed(data);
11161116
1117 var tmp = testing.tmpDir(.{});1117 var tmp = testing.tmpDir(.{});
...@@ -1126,7 +1126,7 @@ test "findRoot without explicit root dir" {...@@ -1126,7 +1126,7 @@ test "findRoot without explicit root dir" {
11261126
1127test "pipeToFileSystem strip_components" {1127test "pipeToFileSystem strip_components" {
1128 const data = @embedFile("tar/testdata/example.tar");1128 const data = @embedFile("tar/testdata/example.tar");
1129 var br: std.io.BufferedReader = undefined;1129 var br: std.io.Reader = undefined;
1130 br.initFixed(data);1130 br.initFixed(data);
11311131
1132 var tmp = testing.tmpDir(.{ .no_follow = true });1132 var tmp = testing.tmpDir(.{ .no_follow = true });
...@@ -1188,7 +1188,7 @@ test "executable bit" {...@@ -1188,7 +1188,7 @@ test "executable bit" {
1188 const data = @embedFile("tar/testdata/example.tar");1188 const data = @embedFile("tar/testdata/example.tar");
11891189
1190 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {1190 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {
1191 var br: std.io.BufferedReader = undefined;1191 var br: std.io.Reader = undefined;
1192 br.initFixed(data);1192 br.initFixed(data);
11931193
1194 var tmp = testing.tmpDir(.{ .no_follow = true });1194 var tmp = testing.tmpDir(.{ .no_follow = true });
lib/std/tar/Writer.zig+4-4
...@@ -67,7 +67,7 @@ pub fn writeFileStream(...@@ -67,7 +67,7 @@ pub fn writeFileStream(
67 w: *Writer,67 w: *Writer,
68 sub_path: []const u8,68 sub_path: []const u8,
69 size: usize,69 size: usize,
70 reader: *std.io.BufferedReader,70 reader: *std.io.Reader,
71 options: Options,71 options: Options,
72) std.io.Reader.StreamError!void {72) std.io.Reader.StreamError!void {
73 try w.writeHeader(.regular, sub_path, "", @intCast(size), options);73 try w.writeHeader(.regular, sub_path, "", @intCast(size), options);
...@@ -441,7 +441,7 @@ test "write files" {...@@ -441,7 +441,7 @@ test "write files" {
441 for (files) |file|441 for (files) |file|
442 try wrt.writeFileBytes(file.path, file.content, .{});442 try wrt.writeFileBytes(file.path, file.content, .{});
443443
444 var input: std.io.BufferedReader = undefined;444 var input: std.io.Reader = undefined;
445 input.initFixed(output.getWritten());445 input.initFixed(output.getWritten());
446 var iter = std.tar.iterator(&input, .{446 var iter = std.tar.iterator(&input, .{
447 .file_name_buffer = &file_name_buffer,447 .file_name_buffer = &file_name_buffer,
...@@ -476,12 +476,12 @@ test "write files" {...@@ -476,12 +476,12 @@ test "write files" {
476 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };476 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };
477 defer output.deinit();477 defer output.deinit();
478 for (files) |file| {478 for (files) |file| {
479 var content: std.io.BufferedReader = undefined;479 var content: std.io.Reader = undefined;
480 content.initFixed(file.content);480 content.initFixed(file.content);
481 try wrt.writeFileStream(file.path, file.content.len, &content, .{});481 try wrt.writeFileStream(file.path, file.content.len, &content, .{});
482 }482 }
483483
484 var input: std.io.BufferedReader = undefined;484 var input: std.io.Reader = undefined;
485 input.initFixed(output.getWritten());485 input.initFixed(output.getWritten());
486 var iter = std.tar.iterator(&input, .{486 var iter = std.tar.iterator(&input, .{
487 .file_name_buffer = &file_name_buffer,487 .file_name_buffer = &file_name_buffer,
lib/std/tar/test.zig+9-14
...@@ -346,8 +346,7 @@ test "run test cases" {...@@ -346,8 +346,7 @@ test "run test cases" {
346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
347347
348 for (cases) |case| {348 for (cases) |case| {
349 var br: std.io.BufferedReader = undefined;349 var br: std.io.Reader = .fixed(case.data);
350 br.initFixed(case.data);
351 var iter = tar.iterator(&br, .{350 var iter = tar.iterator(&br, .{
352 .file_name_buffer = &file_name_buffer,351 .file_name_buffer = &file_name_buffer,
353 .link_name_buffer = &link_name_buffer,352 .link_name_buffer = &link_name_buffer,
...@@ -391,8 +390,7 @@ test "pax/gnu long names with small buffer" {...@@ -391,8 +390,7 @@ test "pax/gnu long names with small buffer" {
391 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };390 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };
392391
393 for (long_name_cases) |case| {392 for (long_name_cases) |case| {
394 var br: std.io.BufferedReader = undefined;393 var br: std.io.Reader = .fixed(case.data);
395 br.initFixed(case.data);
396 var iter = tar.iterator(&br, .{394 var iter = tar.iterator(&br, .{
397 .file_name_buffer = &min_file_name_buffer,395 .file_name_buffer = &min_file_name_buffer,
398 .link_name_buffer = &min_link_name_buffer,396 .link_name_buffer = &min_link_name_buffer,
...@@ -413,8 +411,7 @@ test "insufficient buffer in Header name filed" {...@@ -413,8 +411,7 @@ test "insufficient buffer in Header name filed" {
413 var min_file_name_buffer: [9]u8 = undefined;411 var min_file_name_buffer: [9]u8 = undefined;
414 var min_link_name_buffer: [100]u8 = undefined;412 var min_link_name_buffer: [100]u8 = undefined;
415413
416 var br: std.io.BufferedReader = undefined;414 var br: std.io.Reader = .fixed(cases[0].data);
417 br.initFixed(cases[0].data);
418 var iter = tar.iterator(&br, .{415 var iter = tar.iterator(&br, .{
419 .file_name_buffer = &min_file_name_buffer,416 .file_name_buffer = &min_file_name_buffer,
420 .link_name_buffer = &min_link_name_buffer,417 .link_name_buffer = &min_link_name_buffer,
...@@ -469,22 +466,21 @@ test "should not overwrite existing file" {...@@ -469,22 +466,21 @@ test "should not overwrite existing file" {
469 // This ensures that file is not overwritten.466 // This ensures that file is not overwritten.
470 //467 //
471 const data = @embedFile("testdata/overwrite_file.tar");468 const data = @embedFile("testdata/overwrite_file.tar");
472 var br: std.io.BufferedReader = undefined;469 var r: std.io.Reader = .fixed(data);
473 br.initFixed(data);
474470
475 // Unpack with strip_components = 1 should fail471 // Unpack with strip_components = 1 should fail
476 var root = std.testing.tmpDir(.{});472 var root = std.testing.tmpDir(.{});
477 defer root.cleanup();473 defer root.cleanup();
478 try testing.expectError(474 try testing.expectError(
479 error.PathAlreadyExists,475 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 }),
481 );477 );
482478
483 // Unpack with strip_components = 0 should pass479 // Unpack with strip_components = 0 should pass
484 br.initFixed(data);480 r = .fixed(data);
485 var root2 = std.testing.tmpDir(.{});481 var root2 = std.testing.tmpDir(.{});
486 defer root2.cleanup();482 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 });
488}484}
489485
490test "case sensitivity" {486test "case sensitivity" {
...@@ -498,13 +494,12 @@ test "case sensitivity" {...@@ -498,13 +494,12 @@ test "case sensitivity" {
498 // 18089/alacritty/Darkermatrix.yml494 // 18089/alacritty/Darkermatrix.yml
499 //495 //
500 const data = @embedFile("testdata/18089.tar");496 const data = @embedFile("testdata/18089.tar");
501 var br: std.io.BufferedReader = undefined;497 var r: std.io.Reader = .fixed(data);
502 br.initFixed(data);
503498
504 var root = std.testing.tmpDir(.{});499 var root = std.testing.tmpDir(.{});
505 defer root.cleanup();500 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| {
508 // on case insensitive fs we fail on overwrite existing file503 // on case insensitive fs we fail on overwrite existing file
509 try testing.expectEqual(error.PathAlreadyExists, err);504 try testing.expectEqual(error.PathAlreadyExists, err);
510 return;505 return;
lib/std/tz.zig+4-4
...@@ -54,7 +54,7 @@ pub const Tz = struct {...@@ -54,7 +54,7 @@ pub const Tz = struct {
54 },54 },
55 };55 };
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 {
58 var legacy_header = try reader.takeStruct(Header);58 var legacy_header = try reader.takeStruct(Header);
59 if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader;59 if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader;
60 if (legacy_header.version != 0 and legacy_header.version != '2' and legacy_header.version != '3') return error.BadVersion;60 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 {...@@ -215,7 +215,7 @@ pub const Tz = struct {
215215
216test "slim" {216test "slim" {
217 const data = @embedFile("tz/asia_tokyo.tzif");217 const data = @embedFile("tz/asia_tokyo.tzif");
218 var in_stream: std.io.BufferedReader = undefined;218 var in_stream: std.io.Reader = undefined;
219 in_stream.initFixed(data);219 in_stream.initFixed(data);
220220
221 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);221 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
...@@ -229,7 +229,7 @@ test "slim" {...@@ -229,7 +229,7 @@ test "slim" {
229229
230test "fat" {230test "fat" {
231 const data = @embedFile("tz/antarctica_davis.tzif");231 const data = @embedFile("tz/antarctica_davis.tzif");
232 var in_stream: std.io.BufferedReader = undefined;232 var in_stream: std.io.Reader = undefined;
233 in_stream.initFixed(data);233 in_stream.initFixed(data);
234234
235 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);235 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
...@@ -243,7 +243,7 @@ test "fat" {...@@ -243,7 +243,7 @@ test "fat" {
243test "legacy" {243test "legacy" {
244 // Taken from Slackware 8.0, from 2001244 // Taken from Slackware 8.0, from 2001
245 const data = @embedFile("tz/europe_vatican.tzif");245 const data = @embedFile("tz/europe_vatican.tzif");
246 var in_stream: std.io.BufferedReader = undefined;246 var in_stream: std.io.Reader = undefined;
247 in_stream.initFixed(data);247 in_stream.initFixed(data);
248248
249 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);249 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
lib/std/zig/Server.zig+2-2
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1in: *std.io.BufferedReader,1in: *std.io.Reader,
2out: *std.io.BufferedWriter,2out: *std.io.BufferedWriter,
33
4pub const Message = struct {4pub const Message = struct {
...@@ -93,7 +93,7 @@ pub const Message = struct {...@@ -93,7 +93,7 @@ pub const Message = struct {
93};93};
9494
95pub const Options = struct {95pub const Options = struct {
96 in: *std.io.BufferedReader,96 in: *std.io.Reader,
97 out: *std.io.BufferedWriter,97 out: *std.io.BufferedWriter,
98 zig_version: []const u8,98 zig_version: []const u8,
99};99};
lib/std/zig/llvm/BitcodeReader.zig+7-7
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1allocator: std.mem.Allocator,1allocator: std.mem.Allocator,
2record_arena: std.heap.ArenaAllocator.State,2record_arena: std.heap.ArenaAllocator.State,
3br: *std.io.BufferedReader,3reader: *std.io.Reader,
4keep_names: bool,4keep_names: bool,
5bit_buffer: u32,5bit_buffer: u32,
6bit_offset: u5,6bit_offset: u5,
...@@ -93,14 +93,14 @@ pub const Record = struct {...@@ -93,14 +93,14 @@ pub const Record = struct {
93};93};
9494
95pub const InitOptions = struct {95pub const InitOptions = struct {
96 br: *std.io.BufferedReader,96 reader: *std.io.Reader,
97 keep_names: bool = false,97 keep_names: bool = false,
98};98};
99pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {99pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
100 return .{100 return .{
101 .allocator = allocator,101 .allocator = allocator,
102 .record_arena = .{},102 .record_arena = .{},
103 .br = options.br,103 .reader = options.reader,
104 .keep_names = options.keep_names,104 .keep_names = options.keep_names,
105 .bit_buffer = 0,105 .bit_buffer = 0,
106 .bit_offset = 0,106 .bit_offset = 0,
...@@ -172,7 +172,7 @@ pub fn next(bc: *BitcodeReader) !?Item {...@@ -172,7 +172,7 @@ pub fn next(bc: *BitcodeReader) !?Item {
172172
173pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {173pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {
174 assert(bc.bit_offset == 0);174 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));
176 try bc.endBlock();176 try bc.endBlock();
177}177}
178178
...@@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void {...@@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void {
371371
372fn read32Bits(bc: *BitcodeReader) !u32 {372fn read32Bits(bc: *BitcodeReader) !u32 {
373 assert(bc.bit_offset == 0);373 assert(bc.bit_offset == 0);
374 return bc.br.takeInt(u32, .little);374 return bc.reader.takeInt(u32, .little);
375}375}
376376
377fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {377fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {
378 assert(bc.bit_offset == 0);378 assert(bc.bit_offset == 0);
379 try bc.br.read(bytes);379 try bc.reader.read(bytes);
380380
381 const trailing_bytes = bytes.len % 4;381 const trailing_bytes = bytes.len % 4;
382 if (trailing_bytes > 0) {382 if (trailing_bytes > 0) {
383 var bit_buffer: [4]u8 = @splat(0);383 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..]);
385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);
386 bc.bit_offset = @intCast(8 * trailing_bytes);386 bc.bit_offset = @intCast(8 * trailing_bytes);
387 }387 }
lib/std/zig/system/linux.zig+2-3
...@@ -342,9 +342,8 @@ fn testParser(...@@ -342,9 +342,8 @@ fn testParser(
342 expected_model: *const Target.Cpu.Model,342 expected_model: *const Target.Cpu.Model,
343 input: []const u8,343 input: []const u8,
344) !void {344) !void {
345 var br: std.io.BufferedReader = undefined;345 var r: std.io.Reader = .fixed(input);
346 br.initFixed(@constCast(input));346 const result = try parser.parse(arch, &r);
347 const result = try parser.parse(arch, &br);
348 try testing.expectEqual(expected_model, result.?.model);347 try testing.expectEqual(expected_model, result.?.model);
349 try testing.expect(expected_model.features.eql(result.?.features));348 try testing.expect(expected_model.features.eql(result.?.features));
350}349}
lib/std/zip.zig+3-3
...@@ -161,14 +161,14 @@ pub const EndRecord = extern struct {...@@ -161,14 +161,14 @@ pub const EndRecord = extern struct {
161161
162pub const Decompress = union {162pub const Decompress = union {
163 inflate: std.compress.flate.Decompress,163 inflate: std.compress.flate.Decompress,
164 store: *std.io.BufferedReader,164 store: *std.io.Reader,
165165
166 fn readable(166 fn readable(
167 d: *Decompress,167 d: *Decompress,
168 reader: *std.io.BufferedReader,168 reader: *std.io.Reader,
169 method: CompressionMethod,169 method: CompressionMethod,
170 buffer: []u8,170 buffer: []u8,
171 ) std.io.BufferedReader {171 ) std.io.Reader {
172 switch (method) {172 switch (method) {
173 .store => {173 .store => {
174 d.* = .{ .store = reader };174 d.* = .{ .store = reader };
lib/std/zip/test.zig+2-2
...@@ -51,7 +51,7 @@ const FileStore = struct {...@@ -51,7 +51,7 @@ const FileStore = struct {
51 uncompressed_size: usize,51 uncompressed_size: usize,
52};52};
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 {
55 const store = try std.testing.allocator.alloc(FileStore, files.len);55 const store = try std.testing.allocator.alloc(FileStore, files.len);
56 defer std.testing.allocator.free(store);56 defer std.testing.allocator.free(store);
57 return makeZipWithStore(file_writer, files, options, store);57 return makeZipWithStore(file_writer, files, options, store);
...@@ -198,7 +198,7 @@ const Zipper = struct {...@@ -198,7 +198,7 @@ const Zipper = struct {
198 },198 },
199 .deflate => {199 .deflate => {
200 const offset = writer.count;200 const offset = writer.count;
201 var br: std.io.BufferedReader = undefined;201 var br: std.io.Reader = undefined;
202 br.initFixed(@constCast(opt.content));202 br.initFixed(@constCast(opt.content));
203 var compress: std.compress.flate.Compress = .init(&br, .{});203 var compress: std.compress.flate.Compress = .init(&br, .{});
204 var compress_br = compress.readable(&.{});204 var compress_br = compress.readable(&.{});
src/Compilation.zig+2-3
...@@ -1076,9 +1076,8 @@ pub const CObject = struct {...@@ -1076,9 +1076,8 @@ pub const CObject = struct {
1076 var buffer: [1024]u8 = undefined;1076 var buffer: [1024]u8 = undefined;
1077 const file = try std.fs.cwd().openFile(path, .{});1077 const file = try std.fs.cwd().openFile(path, .{});
1078 defer file.close();1078 defer file.close();
1079 var br: std.io.BufferedReader = undefined;1079 var file_reader = file.reader(&buffer);
1080 br.init(file.reader(), &buffer);1080 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });
1081 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .br = &br });
1082 defer bc.deinit();1081 defer bc.deinit();
10831082
1084 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;1083 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) {...@@ -79,7 +79,7 @@ pub const Oid = union(Format) {
79 };79 };
80 }80 }
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 {
83 return switch (oid_format) {83 return switch (oid_format) {
84 .sha1 => {84 .sha1 => {
85 var result: Oid = .{ .sha1 = undefined };85 var result: Oid = .{ .sha1 = undefined };
...@@ -593,7 +593,7 @@ const Packet = union(enum) {...@@ -593,7 +593,7 @@ const Packet = union(enum) {
593 const max_data_length = 65516;593 const max_data_length = 65516;
594594
595 /// Reads a packet in pkt-line format.595 /// 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 {
597 const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket;597 const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket;
598 switch (length) {598 switch (length) {
599 0 => return .flush,599 0 => return .flush,
...@@ -1107,7 +1107,7 @@ const PackHeader = struct {...@@ -1107,7 +1107,7 @@ const PackHeader = struct {
1107 const signature = "PACK";1107 const signature = "PACK";
1108 const supported_version = 2;1108 const supported_version = 2;
11091109
1110 fn read(reader: *std.io.BufferedReader) !PackHeader {1110 fn read(reader: *std.io.Reader) !PackHeader {
1111 const actual_signature = try reader.take(4);1111 const actual_signature = try reader.take(4);
1112 if (!mem.eql(u8, actual_signature, signature)) return error.InvalidHeader;1112 if (!mem.eql(u8, actual_signature, signature)) return error.InvalidHeader;
1113 const version = try reader.takeInt(u32, .big);1113 const version = try reader.takeInt(u32, .big);
...@@ -1161,7 +1161,7 @@ const EntryHeader = union(Type) {...@@ -1161,7 +1161,7 @@ const EntryHeader = union(Type) {
1161 };1161 };
1162 }1162 }
11631163
1164 fn read(format: Oid.Format, reader: *std.io.BufferedReader) !EntryHeader {1164 fn read(format: Oid.Format, reader: *std.io.Reader) !EntryHeader {
1165 const InitialByte = packed struct { len: u4, type: u3, has_next: bool };1165 const InitialByte = packed struct { len: u4, type: u3, has_next: bool };
1166 const initial: InitialByte = @bitCast(try reader.takeByte());1166 const initial: InitialByte = @bitCast(try reader.takeByte());
1167 const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0;1167 const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0;
...@@ -1187,7 +1187,7 @@ const EntryHeader = union(Type) {...@@ -1187,7 +1187,7 @@ const EntryHeader = union(Type) {
1187 }1187 }
1188};1188};
11891189
1190fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {1190fn readSizeVarInt(r: *std.io.Reader) !u64 {
1191 const Byte = packed struct { value: u7, has_next: bool };1191 const Byte = packed struct { value: u7, has_next: bool };
1192 var b: Byte = @bitCast(try r.takeByte());1192 var b: Byte = @bitCast(try r.takeByte());
1193 var value: u64 = b.value;1193 var value: u64 = b.value;
...@@ -1200,7 +1200,7 @@ fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {...@@ -1200,7 +1200,7 @@ fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {
1200 return value;1200 return value;
1201}1201}
12021202
1203fn readOffsetVarInt(r: *std.io.BufferedReader) !u64 {1203fn readOffsetVarInt(r: *std.io.Reader) !u64 {
1204 const Byte = packed struct { value: u7, has_next: bool };1204 const Byte = packed struct { value: u7, has_next: bool };
1205 var b: Byte = @bitCast(try r.takeByte());1205 var b: Byte = @bitCast(try r.takeByte());
1206 var value: u64 = b.value;1206 var value: u64 = b.value;
...@@ -1219,7 +1219,7 @@ const IndexHeader = struct {...@@ -1219,7 +1219,7 @@ const IndexHeader = struct {
1219 const supported_version = 2;1219 const supported_version = 2;
1220 const size = 4 + 4 + @sizeOf([256]u32);1220 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 {
1223 const sig = try br.take(4);1223 const sig = try br.take(4);
1224 if (!mem.eql(u8, sig, signature)) return error.InvalidHeader;1224 if (!mem.eql(u8, sig, signature)) return error.InvalidHeader;
1225 const version = try br.takeInt(u32, .big);1225 const version = try br.takeInt(u32, .big);
...@@ -1493,7 +1493,7 @@ fn resolveDeltaChain(...@@ -1493,7 +1493,7 @@ fn resolveDeltaChain(
1493}1493}
14941494
1495/// Reads the complete contents of an object from `reader`.1495/// 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 {
1497 const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge;1497 const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge;
1498 var decompress: zlib.Decompressor = .init(reader);1498 var decompress: zlib.Decompressor = .init(reader);
1499 var buffer: std.ArrayListUnmanaged(u8) = .empty;1499 var buffer: std.ArrayListUnmanaged(u8) = .empty;
...@@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u...@@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u
15051505
1506/// The format of the delta data is documented in1506/// The format of the delta data is documented in
1507/// [pack-format](https://git-scm.com/docs/pack-format).1507/// [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 {
1509 var base_offset: u32 = 0;1509 var base_offset: u32 = 0;
1510 while (true) {1510 while (true) {
1511 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.takeByte() catch |e| switch (e) {1511 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 {...@@ -2828,7 +2828,7 @@ pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
2828 };2828 };
2829}2829}
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 {
2832 var instructions: std.MultiArrayList(Zir.Inst) = .{};2832 var instructions: std.MultiArrayList(Zir.Inst) = .{};
2833 errdefer instructions.deinit(gpa);2833 errdefer instructions.deinit(gpa);
28342834
...@@ -2947,7 +2947,7 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir...@@ -2947,7 +2947,7 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir
2947 };2947 };
2948}2948}
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 {
2951 var zoir: Zoir = .{2951 var zoir: Zoir = .{
2952 .nodes = .empty,2952 .nodes = .empty,
2953 .extra = &.{},2953 .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...@@ -372,7 +372,7 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi
372}372}
373373
374fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {374fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
375 var br: std.io.BufferedReader = undefined;375 var br: std.io.Reader = undefined;
376 br.initFixed(dis.code[dis.pos..]);376 br.initFixed(dis.code[dis.pos..]);
377 defer dis.pos += br.seek;377 defer dis.pos += br.seek;
378 return switch (kind) {378 return switch (kind) {
...@@ -388,7 +388,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {...@@ -388,7 +388,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
388}388}
389389
390fn parseOffset(dis: *Disassembler) !u64 {390fn parseOffset(dis: *Disassembler) !u64 {
391 var br: std.io.BufferedReader = undefined;391 var br: std.io.Reader = undefined;
392 br.initFixed(dis.code[dis.pos..]);392 br.initFixed(dis.code[dis.pos..]);
393 defer dis.pos += br.seek;393 defer dis.pos += br.seek;
394 return br.takeInt(u64, .little);394 return br.takeInt(u64, .little);
...@@ -464,8 +464,7 @@ fn parseSibByte(dis: *Disassembler) !Sib {...@@ -464,8 +464,7 @@ fn parseSibByte(dis: *Disassembler) !Sib {
464}464}
465465
466fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 {466fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 {
467 var br: std.io.BufferedReader = undefined;467 var br: std.io.Reader = .fixed(dis.code[dis.pos..]);
468 br.initFixed(dis.code[dis.pos..]);
469 defer dis.pos += br.seek;468 defer dis.pos += br.seek;
470 if (sib) |info| {469 if (sib) |info| {
471 if (info.base == 0b101 and modrm.mod == 0) {470 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...@@ -793,8 +793,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
793 // twice, which causes a "duplicate symbol" assembler error.793 // twice, which causes a "duplicate symbol" assembler error.
794 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);794 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);
795795
796 var inc_br: std.io.BufferedReader = undefined;796 var inc_br: std.io.Reader = .fixed(metadata.inclusions);
797 inc_br.initFixed(metadata.inclusions);
798797
799 const fn_inclusions_len = try inc_br.takeInt(u16, .little);798 const fn_inclusions_len = try inc_br.takeInt(u16, .little);
800799
src/link/Dwarf.zig+2-3
...@@ -142,8 +142,7 @@ const DebugInfo = struct {...@@ -142,8 +142,7 @@ const DebugInfo = struct {
142 &abbrev_code_buf,142 &abbrev_code_buf,
143 debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,143 debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,
144 ) != abbrev_code_buf.len) return error.InputOutput;144 ) != abbrev_code_buf.len) return error.InputOutput;
145 var abbrev_code_br: std.io.BufferedReader = undefined;145 var abbrev_code_br: std.io.Reader = .fixed(&abbrev_code_buf);
146 abbrev_code_br.initFixed(&abbrev_code_buf);
147 return @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);146 return @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
148 }147 }
149148
...@@ -2757,7 +2756,7 @@ fn finishWipNavFuncInner(...@@ -2757,7 +2756,7 @@ fn finishWipNavFuncInner(
2757 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));2756 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2758 } else {2757 } else {
2759 const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes];2758 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;
2761 abbrev_code_br.initFixed(abbrev_code_buf);2760 abbrev_code_br.initFixed(abbrev_code_buf);
2762 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);2761 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
2763 std.leb.writeUnsignedFixed(2762 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...@@ -1192,18 +1192,17 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
1192 const atom_ptr = self.atom(atom_index).?;1192 const atom_ptr = self.atom(atom_index).?;
1193 const shdr = atom_ptr.inputShdr(elf_file);1193 const shdr = atom_ptr.inputShdr(elf_file);
1194 const handle = elf_file.fileHandle(self.file_handle);1194 const handle = elf_file.fileHandle(self.file_handle);
1195 var br: std.io.BufferedReader = undefined;1195 var r: std.io.Reader = .fixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index));
1196 br.initFixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index));1196 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(r.storageBuffer());
1197 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(br.storageBuffer());
11981197
1199 if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {1198 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)).*;
1201 switch (chdr.ch_type) {1200 switch (chdr.ch_type) {
1202 .ZLIB => {1201 .ZLIB => {
1203 var bw: std.io.BufferedWriter = undefined;1202 var bw: std.io.BufferedWriter = undefined;
1204 bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));1203 bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));
1205 errdefer gpa.free(bw.buffer);1204 errdefer gpa.free(bw.buffer);
1206 try std.compress.zlib.decompress(&br, &bw);1205 try std.compress.zlib.decompress(&r, &bw);
1207 if (bw.end != bw.buffer.len) return error.InputOutput;1206 if (bw.end != bw.buffer.len) return error.InputOutput;
1208 return bw.buffer;1207 return bw.buffer;
1209 },1208 },
...@@ -1211,7 +1210,7 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index...@@ -1211,7 +1210,7 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
1211 }1210 }
1212 }1211 }
12131212
1214 return br.storageBuffer();1213 return r.storageBuffer();
1215}1214}
12161215
1217fn locals(self: *Object) []Symbol {1216fn locals(self: *Object) []Symbol {
src/link/Elf/eh_frame.zig+6-6
...@@ -187,7 +187,7 @@ pub const Cie = struct {...@@ -187,7 +187,7 @@ pub const Cie = struct {
187};187};
188188
189pub const Iterator = struct {189pub const Iterator = struct {
190 br: std.io.BufferedReader,190 reader: std.io.Reader,
191191
192 pub const Record = struct {192 pub const Record = struct {
193 tag: enum { fde, cie },193 tag: enum { fde, cie },
...@@ -196,18 +196,18 @@ pub const Iterator = struct {...@@ -196,18 +196,18 @@ pub const Iterator = struct {
196 };196 };
197197
198 pub fn next(it: *Iterator) !?Record {198 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);
202 if (size == 0xFFFFFFFF) @panic("DWARF CFI is 32bit on macOS");202 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);
205 const record: Record = .{205 const record: Record = .{
206 .tag = if (id == 0) .cie else .fde,206 .tag = if (id == 0) .cie else .fde,
207 .offset = it.br.seek,207 .offset = it.reader.seek,
208 .size = size,208 .size = size,
209 };209 };
210 try it.br.discard(size);210 try it.reader.discard(size);
211211
212 return record;212 return record;
213 }213 }
src/link/MachO/Dwarf.zig+6-8
...@@ -273,10 +273,9 @@ pub const InfoReader = struct {...@@ -273,10 +273,9 @@ pub const InfoReader = struct {
273 }273 }
274274
275 pub fn readLeb128(p: *InfoReader, comptime Type: type) !Type {275 pub fn readLeb128(p: *InfoReader, comptime Type: type) !Type {
276 var br: std.io.BufferedReader = undefined;276 var r: std.io.Reader = .fixed(p.bytes()[p.pos..]);
277 br.initFixed(p.bytes()[p.pos..]);277 defer p.pos += r.seek;
278 defer p.pos += br.seek;278 return r.takeLeb128(Type);
279 return br.takeLeb128(Type);
280 }279 }
281280
282 pub fn seekTo(p: *InfoReader, off: u64) !void {281 pub fn seekTo(p: *InfoReader, off: u64) !void {
...@@ -331,10 +330,9 @@ pub const AbbrevReader = struct {...@@ -331,10 +330,9 @@ pub const AbbrevReader = struct {
331 }330 }
332331
333 pub fn readLeb128(p: *AbbrevReader, comptime Type: type) !Type {332 pub fn readLeb128(p: *AbbrevReader, comptime Type: type) !Type {
334 var br: std.io.BufferedReader = undefined;333 var r: std.io.Reader = .fixed(p.bytes()[p.pos..]);
335 br.initFixed(p.bytes()[p.pos..]);334 defer p.pos += r.seek;
336 defer p.pos += br.seek;335 return r.takeLeb128(Type);
337 return br.takeLeb128(Type);
338 }336 }
339337
340 pub fn seekTo(p: *AbbrevReader, off: u64) !void {338 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...@@ -167,7 +167,7 @@ pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Ex
167167
168fn parseTrieNode(168fn parseTrieNode(
169 self: *Dylib,169 self: *Dylib,
170 br: *std.io.BufferedReader,170 br: *std.io.Reader,
171 allocator: Allocator,171 allocator: Allocator,
172 arena: Allocator,172 arena: Allocator,
173 prefix: []const u8,173 prefix: []const u8,
...@@ -216,9 +216,8 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {...@@ -216,9 +216,8 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {
216 var arena = std.heap.ArenaAllocator.init(gpa);216 var arena = std.heap.ArenaAllocator.init(gpa);
217 defer arena.deinit();217 defer arena.deinit();
218218
219 var br: std.io.BufferedReader = undefined;219 var r: std.io.Reader = .fixed(data);
220 br.initFixed(data);220 try self.parseTrieNode(&r, gpa, arena.allocator(), "");
221 try self.parseTrieNode(&br, gpa, arena.allocator(), "");
222}221}
223222
224fn parseTbd(self: *Dylib, macho_file: *MachO) !void {223fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
src/link/MachO/eh_frame.zig+13-14
...@@ -12,34 +12,33 @@ pub const Cie = struct {...@@ -12,34 +12,33 @@ pub const Cie = struct {
12 const tracy = trace(@src());12 const tracy = trace(@src());
13 defer tracy.end();13 defer tracy.end();
1414
15 var br: std.io.BufferedReader = undefined;15 var r: std.io.Reader = .fixed(cie.getData(macho_file));
16 br.initFixed(cie.getData(macho_file));
1716
18 try br.discard(9);17 try r.discard(9);
19 const aug = try br.takeSentinel(0);18 const aug = try r.takeSentinel(0);
20 if (aug[0] != 'z') return; // TODO should we error out?19 if (aug[0] != 'z') return; // TODO should we error out?
2120
22 _ = try br.takeLeb128(u64); // code alignment factor21 _ = try r.takeLeb128(u64); // code alignment factor
23 _ = try br.takeLeb128(u64); // data alignment factor22 _ = try r.takeLeb128(u64); // data alignment factor
24 _ = try br.takeLeb128(u64); // return address register23 _ = try r.takeLeb128(u64); // return address register
25 _ = try br.takeLeb128(u64); // augmentation data length24 _ = try r.takeLeb128(u64); // augmentation data length
2625
27 for (aug[1..]) |ch| switch (ch) {26 for (aug[1..]) |ch| switch (ch) {
28 'R' => {27 'R' => {
29 const enc = try br.takeByte();28 const enc = try r.takeByte();
30 if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) {29 if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) {
31 @panic("unexpected pointer encoding"); // TODO error30 @panic("unexpected pointer encoding"); // TODO error
32 }31 }
33 },32 },
34 'P' => {33 'P' => {
35 const enc = try br.takeByte();34 const enc = try r.takeByte();
36 if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) {35 if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) {
37 @panic("unexpected personality pointer encoding"); // TODO error36 @panic("unexpected personality pointer encoding"); // TODO error
38 }37 }
39 _ = try br.takeInt(u32, .little); // personality pointer38 _ = try r.takeInt(u32, .little); // personality pointer
40 },39 },
41 'L' => {40 'L' => {
42 const enc = try br.takeByte();41 const enc = try r.takeByte();
43 switch (enc & DW_EH_PE.type_mask) {42 switch (enc & DW_EH_PE.type_mask) {
44 DW_EH_PE.sdata4 => cie.lsda_size = .p32,43 DW_EH_PE.sdata4 => cie.lsda_size = .p32,
45 DW_EH_PE.absptr => cie.lsda_size = .p64,44 DW_EH_PE.absptr => cie.lsda_size = .p64,
...@@ -143,7 +142,7 @@ pub const Fde = struct {...@@ -143,7 +142,7 @@ pub const Fde = struct {
143 const object = fde.getObject(macho_file);142 const object = fde.getObject(macho_file);
144 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];143 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;
147 br.initFixed(fde.getData(macho_file));146 br.initFixed(fde.getData(macho_file));
148147
149 try br.discard(4);148 try br.discard(4);
...@@ -267,7 +266,7 @@ pub const Fde = struct {...@@ -267,7 +266,7 @@ pub const Fde = struct {
267};266};
268267
269pub const Iterator = struct {268pub const Iterator = struct {
270 br: std.io.BufferedReader,269 br: std.io.Reader,
271270
272 pub const Record = struct {271 pub const Record = struct {
273 tag: enum { fde, cie },272 tag: enum { fde, cie },
src/link/Wasm.zig+4-5
...@@ -2087,10 +2087,9 @@ pub const Expr = enum(u32) {...@@ -2087,10 +2087,9 @@ pub const Expr = enum(u32) {
2087 pub const end = @intFromEnum(std.wasm.Opcode.end);2087 pub const end = @intFromEnum(std.wasm.Opcode.end);
20882088
2089 pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {2089 pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {
2090 var br: std.io.BufferedReader = undefined;2090 var r: std.io.Reader = .fixed(wasm.string_bytes.items[@intFromEnum(index)..]);
2091 br.initFixed(wasm.string_bytes.items[@intFromEnum(index)..]);2091 Object.skipInit(&r) catch unreachable;
2092 Object.skipInit(&br) catch unreachable;2092 return r.storageBuffer()[0 .. r.seek - 1 :end];
2093 return br.storageBuffer()[0 .. br.seek - 1 :end];
2094 }2093 }
2095};2094};
20962095
...@@ -3038,7 +3037,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3038,7 +3037,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3038 const stat = try obj.file.stat();3037 const stat = try obj.file.stat();
3039 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;3038 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;
3042 br.initFixed(try gpa.alloc(u8, size));3041 br.initFixed(try gpa.alloc(u8, size));
3043 defer gpa.free(br.storageBuffer());3042 defer gpa.free(br.storageBuffer());
30443043
src/link/Wasm/Archive.zig+2-4
...@@ -167,10 +167,8 @@ pub fn parseObject(...@@ -167,10 +167,8 @@ pub fn parseObject(
167 };167 };
168168
169 const object_file_size = try header.parsedSize();169 const object_file_size = try header.parsedSize();
170 var br: std.io.BufferedReader = undefined;170 var r: std.io.Reader = .fixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]);
171 br.initFixed(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);
172
173 return Object.parse(wasm, &br, path, object_name, host_name, scratch_space, must_link, gc_sections);
174}172}
175173
176const Archive = @This();174const Archive = @This();
src/link/Wasm/Object.zig+5-5
...@@ -252,7 +252,7 @@ pub const ScratchSpace = struct {...@@ -252,7 +252,7 @@ pub const ScratchSpace = struct {
252252
253pub fn parse(253pub fn parse(
254 wasm: *Wasm,254 wasm: *Wasm,
255 br: *std.io.BufferedReader,255 br: *std.io.Reader,
256 path: Path,256 path: Path,
257 archive_member_name: ?[]const u8,257 archive_member_name: ?[]const u8,
258 host_name: Wasm.OptionalString,258 host_name: Wasm.OptionalString,
...@@ -1402,7 +1402,7 @@ pub fn parse(...@@ -1402,7 +1402,7 @@ pub fn parse(
1402/// Based on the "features" custom section, parses it into a list of1402/// Based on the "features" custom section, parses it into a list of
1403/// features that tell the linker what features were enabled and may be mandatory1403/// features that tell the linker what features were enabled and may be mandatory
1404/// to be able to link.1404/// 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 {
1406 const gpa = wasm.base.comp.gpa;1406 const gpa = wasm.base.comp.gpa;
1407 const diags = &wasm.base.comp.link_diags;1407 const diags = &wasm.base.comp.link_diags;
1408 const features_len = try br.takeLeb128(u32);1408 const features_len = try br.takeLeb128(u32);
...@@ -1430,7 +1430,7 @@ fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) error{ Out...@@ -1430,7 +1430,7 @@ fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) error{ Out
1430 return .fromString(try wasm.internString(@ptrCast(feature_buffer)));1430 return .fromString(try wasm.internString(@ptrCast(feature_buffer)));
1431}1431}
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 {
1434 const flags: std.wasm.Limits.Flags = @bitCast(try br.takeByte());1434 const flags: std.wasm.Limits.Flags = @bitCast(try br.takeByte());
1435 const min = try br.takeLeb128(u32);1435 const min = try br.takeLeb128(u32);
1436 const max = if (flags.has_max) try br.takeLeb128(u32) else 0;1436 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 {...@@ -1441,13 +1441,13 @@ fn readLimits(br: *std.io.BufferedReader) std.io.Reader.Error!std.wasm.Limits {
1441 };1441 };
1442}1442}
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 {
1445 const start = br.seek;1445 const start = br.seek;
1446 try skipInit(br); // one after the end opcode1446 try skipInit(br); // one after the end opcode
1447 return wasm.addExpr(br.storageBuffer()[start..br.seek]);1447 return wasm.addExpr(br.storageBuffer()[start..br.seek]);
1448}1448}
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 {
1451 switch (try br.takeEnum(std.wasm.Opcode, .little)) {1451 switch (try br.takeEnum(std.wasm.Opcode, .little)) {
1452 .i32_const => _ = try br.takeLeb128(i32),1452 .i32_const => _ = try br.takeLeb128(i32),
1453 .i64_const => _ = try br.takeLeb128(i64),1453 .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....@@ -13,9 +13,8 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.
13 switch (op) {13 switch (op) {
14 .set => try overwriteUleb(@intCast(addend), bw),14 .set => try overwriteUleb(@intCast(addend), bw),
15 .sub => {15 .sub => {
16 var br: std.io.BufferedReader = undefined;16 var r: std.io.Reader = .fixed(try bw.writableArray(1));
17 br.initFixed(try bw.writableArray(1));17 const old_value = try r.takeLeb128(u64);
18 const old_value = try br.takeLeb128(u64);
19 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);18 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);
20 },19 },
21 }20 }