| author | |
| committer | |
| log | 3c98e2c826e1a8650090a889cf3a1560335b2968 |
| tree | 7511982b72d00266ba33347e7d92f0f6cc1436b3 |
| parent | 2ed47f1ed813d786e4d7d4adf18bd95d81e8e931 |
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, |
| 1087 | 1087 | ||
| 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 line | 1089 | // We don't do line comparison for this error, so don't print the note if the line |
| 1092 | // number is different | 1090 | // 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 { |
| 778 | const Oom = error{OutOfMemory}; | 778 | const Oom = error{OutOfMemory}; |
| 779 | 779 | ||
| 780 | fn unpackInner(tar_bytes: []u8) !void { | 780 | fn 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 | } |
| 1239 | 1239 | ||
| 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)); | ||
| 1243 | 1242 | ||
| 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 | } |
| 1350 | 1349 | ||
| 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)); |
| 1354 | 1353 | ||
| 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(); |
| 1448 | 1447 | ||
| 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); |
| 1453 | 1452 | ||
| ... | @@ -1517,7 +1516,7 @@ const MachODumper = struct { | ... | @@ -1517,7 +1516,7 @@ const MachODumper = struct { |
| 1517 | 1516 | ||
| 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 { |
| 1705 | 1704 | ||
| 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)); |
| 1710 | 1709 | ||
| 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 | } |
| 1781 | 1780 | ||
| 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 { |
| 1851 | 1850 | ||
| 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)); |
| 1856 | 1855 | ||
| 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 { |
| 2354 | 2353 | ||
| 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)); |
| 2359 | 2358 | ||
| 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 | } |
| 2447 | 2446 | ||
| 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 | } |
| 2578 | 2577 | ||
| 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 | } |
| 2587 | 2586 | ||
| 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); |
| 2591 | 2590 | ||
| ... | @@ -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 | } |
| 2595 | 2594 | ||
| 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 | } |
| 2614 | 2613 | ||
| 2615 | /// https://webassembly.github.io/spec/core/appendix/custom.html | 2614 | /// 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 name | 2619 | // 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 | } |
| 2664 | 2663 | ||
| 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 | } |
| 2692 | 2691 | ||
| 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"; |
| 1089 | 1089 | ||
| 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); |
| 1096 | 1095 | ||
| ... | @@ -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; |
| 1122 | 1121 | ||
| 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); | ||
| 1126 | 1124 | ||
| 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 offset | 1128 | // 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" { |
| 229 | 229 | ||
| 230 | // compress original stream to compressed stream | 230 | // 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 stream | 246 | // 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 interface | 266 | // 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" { |
| 287 | 284 | ||
| 288 | // compress original stream to compressed stream | 285 | // 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 stream | 300 | // 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" { |
| 323 | 318 | ||
| 324 | // compress original stream to compressed stream | 319 | // 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 stream | 335 | // 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 | } |
| 354 | 347 | ||
| 355 | fn testDecompress(comptime container: Container, compressed: []const u8, expected_plain: []const u8) !void { | 348 | fn 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); |
| 504 | 496 | ||
| 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); |
| 517 | 508 | ||
| 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, .{}); |
| 521 | 511 | ||
| 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); |
| 534 | 523 | ||
| 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(); |
| 540 | 528 | ||
| 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); |
| 556 | 543 | ||
| 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); |
| 560 | 546 | ||
| 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); |
| 573 | 558 | ||
| 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(); |
| 579 | 563 | ||
| 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); |
| 595 | 578 | ||
| 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); |
| 599 | 581 | ||
| 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); |
| 612 | 593 | ||
| 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(); |
| 618 | 598 | ||
| 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 | }; |
| 652 | 631 | ||
| 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(); |
| 656 | 634 | ||
| 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; |
| 59 | lookup: Lookup = .{}, | 59 | lookup: Lookup = .{}, |
| 60 | tokens: Tokens = .{}, | 60 | tokens: 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`. |
| 62 | input: *std.io.BufferedReader, | 62 | input: *std.io.Reader, |
| 63 | block_writer: BlockWriter, | 63 | block_writer: BlockWriter, |
| 64 | level: LevelArgs, | 64 | level: LevelArgs, |
| 65 | hasher: Container.Hasher, | 65 | hasher: Container.Hasher, |
| ... | @@ -69,7 +69,7 @@ hasher: Container.Hasher, | ... | @@ -69,7 +69,7 @@ hasher: Container.Hasher, |
| 69 | prev_match: ?Token = null, | 69 | prev_match: ?Token = null, |
| 70 | prev_literal: ?u8 = null, | 70 | prev_literal: ?u8 = null, |
| 71 | 71 | ||
| 72 | pub fn readable(c: *Compress, buffer: []u8) std.io.BufferedReader { | 72 | pub 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 | }; |
| 128 | 128 | ||
| 129 | pub fn init(input: *std.io.BufferedReader, options: Options) Compress { | 129 | pub 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; |
| 1148 | 1148 | ||
| 1149 | for (levels, 0..) |level, i| { // for each compression level | 1149 | 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); |
| 1152 | 1152 | ||
| 1153 | // buffer for decompressed data | 1153 | // 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 | }; |
| 1224 | 1224 | ||
| 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"); |
| 24 | const testing = std.testing; | 24 | const testing = std.testing; |
| 25 | const Decompress = @This(); | 25 | const Decompress = @This(); |
| 26 | 26 | ||
| 27 | input: *std.io.BufferedReader, | 27 | input: *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. |
| 29 | hasher: Container.Hasher, | 29 | hasher: Container.Hasher, |
| 30 | 30 | ||
| ... | @@ -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 | }; |
| 69 | 69 | ||
| 70 | pub fn init(input: *std.io.BufferedReader, container: Container) Decompress { | 70 | pub 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 | } |
| 363 | 363 | ||
| 364 | pub fn readable(self: *Decompress, buffer: []u8) std.io.BufferedReader { | 364 | pub fn readable(self: *Decompress, buffer: []u8) std.io.Reader { |
| 365 | return reader(self).buffered(buffer); | 365 | return reader(self).buffered(buffer); |
| 366 | } | 366 | } |
| 367 | 367 | ||
| ... | @@ -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 | }; |
| 881 | 881 | ||
| 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"); |
| 905 | 905 | ||
| 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, nlen | 921 | 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 data | 922 | '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, |
| 13 | 13 | ||
| 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 | } |
| 27 | 27 | ||
| 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 | } |
| 34 | 34 | ||
| 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; |
| 37 | 37 | ||
| 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 | } |
| 45 | 45 | ||
| 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 | } |
| 53 | 53 | ||
| 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.*; |
| 56 | 56 | ||
| 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 { |
| 74 | 74 | ||
| 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 { |
| 90 | 90 | ||
| 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 { |
| 117 | 117 | ||
| 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 { |
| 148 | 148 | ||
| 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 { |
| 157 | 157 | ||
| 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, |
| 224 | 224 | ||
| 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 { |
| 460 | 460 | ||
| 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 { |
| 502 | 502 | ||
| 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 }; |
| 543 | 543 | ||
| 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), |
| 547 | 547 | ||
| 548 | buffer: LzCircularBuffer, | 548 | buffer: LzCircularBuffer, |
| 549 | decoder: RangeDecoder, | 549 | decoder: RangeDecoder, |
| 550 | state: Decode, | 550 | state: Decode, |
| 551 | 551 | ||
| 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 | } |
| 556 | 556 | ||
| 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" { |
| 839 | 839 | ||
| 840 | fn testDecompress(compressed: []const u8) ![]u8 { | 840 | fn 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" { |
| 927 | 927 | ||
| 928 | test "reading one byte" { | 928 | test "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"); |
| 2 | const Allocator = std.mem.Allocator; | 2 | const Allocator = std.mem.Allocator; |
| 3 | const lzma = std.compress.lzma; | 3 | const lzma = std.compress.lzma; |
| 4 | 4 | ||
| 5 | pub fn decompress(gpa: Allocator, reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) std.io.Reader.StreamError!void { | 5 | pub 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 { |
| 149 | 149 | ||
| 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; |
| 3 | const xz = std.compress.xz; | 3 | const xz = std.compress.xz; |
| 4 | 4 | ||
| 5 | fn decompress(data: []const u8) ![]u8 { | 5 | fn 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); | ||
| 8 | 7 | ||
| 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(); |
| 11 | 10 | ||
| 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); |
| 84 | 84 | ||
| 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); |
| 89 | 88 | ||
| ... | @@ -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); |
| 105 | 104 | ||
| 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; |
| 4 | const Reader = std.io.Reader; | 4 | const Reader = std.io.Reader; |
| 5 | const Limit = std.io.Limit; | 5 | const Limit = std.io.Limit; |
| 6 | const BufferedWriter = std.io.BufferedWriter; | 6 | const BufferedWriter = std.io.BufferedWriter; |
| 7 | const BufferedReader = std.io.BufferedReader; | ||
| 8 | const zstd = @import("../zstd.zig"); | 7 | const zstd = @import("../zstd.zig"); |
| 9 | 8 | ||
| 10 | input: *BufferedReader, | 9 | input: *Reader, |
| 11 | state: State, | 10 | state: State, |
| 12 | verify_checksum: bool, | 11 | verify_checksum: bool, |
| 13 | err: ?Error = null, | 12 | err: ?Error = null, |
| ... | @@ -63,7 +62,7 @@ pub const Error = error{ | ... | @@ -63,7 +62,7 @@ pub const Error = error{ |
| 63 | WindowSizeUnknown, | 62 | WindowSizeUnknown, |
| 64 | }; | 63 | }; |
| 65 | 64 | ||
| 66 | pub fn init(input: *BufferedReader, options: Options) Decompress { | 65 | pub 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 { |
| 305 | 304 | ||
| 306 | pub const DecodeError = Reader.Error || error{ReservedBitSet}; | 305 | pub const DecodeError = Reader.Error || error{ReservedBitSet}; |
| 307 | 306 | ||
| 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()); |
| 310 | 309 | ||
| 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, |
| 859 | 858 | ||
| 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 | }; |
| 967 | 966 | ||
| 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 | } |
| 977 | 976 | ||
| 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 | } |
| 994 | 993 | ||
| 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 | }; |
| 1164 | 1163 | ||
| 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 | }; |
| 1235 | 1234 | ||
| 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; |
| 1238 | 1237 | ||
| 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 { |
| 154 | 154 | ||
| 155 | test Tag { | 155 | test 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..]); | ||
| 190 | 188 | ||
| 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 | } |
| 156 | 156 | ||
| 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 | } |
| 174 | 174 | ||
| ... | @@ -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 | } |
| 656 | 656 | ||
| 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 { |
| 672 | 672 | ||
| 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`. |
| 24 | input: *std.io.BufferedReader, | 24 | input: *std.io.Reader, |
| 25 | 25 | ||
| 26 | /// The encrypted stream from the client to the server. Bytes are pushed here | 26 | /// 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 | }; |
| 87 | 87 | ||
| 88 | /// The `std.io.BufferedReader` supplied to `init` requires a buffer capacity | 88 | /// The `std.io.Reader` supplied to `init` requires a buffer capacity |
| 89 | /// at least this amount. | 89 | /// at least this amount. |
| 90 | pub const min_buffer_len = tls.max_ciphertext_record_len; | 90 | pub const min_buffer_len = tls.max_ciphertext_record_len; |
| 91 | 91 | ||
| ... | @@ -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`. |
| 176 | pub fn init( | 176 | pub 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 { |
| 2235 | 2235 | ||
| 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 | }, |
| 137 | 137 | ||
| 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 | } |
| 775 | 775 | ||
| 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. |
| 2 | 2 | ||
| 3 | // TODO I'm pretty sure this can be deleted thanks to the new std.io.BufferedReader semantics | 3 | // TODO I'm pretty sure this can be deleted thanks to the new std.io.Reader semantics |
| 4 | 4 | ||
| 5 | const std = @import("../std.zig"); | 5 | const std = @import("../std.zig"); |
| 6 | const MemoryAccessor = std.debug.MemoryAccessor; | 6 | const MemoryAccessor = std.debug.MemoryAccessor; |
| ... | @@ -52,7 +52,7 @@ pub fn readIntChecked( | ... | @@ -52,7 +52,7 @@ pub fn readIntChecked( |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T { | 54 | pub 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; |
| 2027 | 2027 | ||
| 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 | }; | ||
| 2031 | 2032 | ||
| 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 { |
| 510 | 510 | ||
| 511 | pub const ReadError = std.io.Reader.Error || ParseError; | 511 | pub const ReadError = std.io.Reader.Error || ParseError; |
| 512 | 512 | ||
| 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 | } |
| 519 | 519 |
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, | ||
| 907 | 908 | ||
| 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 | }; |
| 942 | 943 | ||
| 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 | } |
| 952 | 956 | ||
| 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 | } |
| 956 | 963 | ||
| 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; |
| 1022 | 1029 | ||
| 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 | } |
| 1053 | 1060 | ||
| 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 not | 1365 | /// Positional is more threadsafe, since the global seek position is not |
| 1359 | /// affected. | 1366 | /// affected. |
| 1360 | pub fn reader(file: File) Reader { | 1367 | pub fn reader(file: File, buffer: []u8) Reader { |
| 1361 | return .{ .file = file }; | 1368 | return .init(file, buffer); |
| 1362 | } | 1369 | } |
| 1363 | 1370 | ||
| 1364 | /// Positional is more threadsafe, since the global seek position is not | 1371 | /// 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 | }; |
| 326 | 326 | ||
| 327 | pub const Reader = struct { | 327 | pub 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 HTTP | 330 | /// 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 { |
| 703 | 703 | ||
| 704 | pub const Decompressor = struct { | 704 | pub const Decompressor = struct { |
| 705 | compression: Compression, | 705 | compression: Compression, |
| 706 | buffered_reader: std.io.BufferedReader, | 706 | buffered_reader: std.io.Reader, |
| 707 | 707 | ||
| 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, |
| 305 | 305 |
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. |
| 23 | pub fn init(in: *std.io.BufferedReader, out: *std.io.BufferedWriter) Server { | 23 | pub 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/rfc6455 | 610 | /// See https://tools.ietf.org/html/rfc6455 |
| 611 | pub const WebSocket = struct { | 611 | pub 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, |
| 615 | 615 | ||
| 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) { |
| 72 | pub const Reader = @import("io/Reader.zig"); | 72 | pub const Reader = @import("io/Reader.zig"); |
| 73 | pub const Writer = @import("io/Writer.zig"); | 73 | pub const Writer = @import("io/Writer.zig"); |
| 74 | 74 | ||
| 75 | pub const BufferedReader = @import("io/BufferedReader.zig"); | ||
| 76 | pub const BufferedWriter = @import("io/BufferedWriter.zig"); | ||
| 77 | pub const AllocatingWriter = @import("io/AllocatingWriter.zig"); | 75 | pub const AllocatingWriter = @import("io/AllocatingWriter.zig"); |
| 78 | 76 | ||
| 79 | pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream; | 77 | pub 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; |
| 132 | 130 | ||
| 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 | } |
| 169 | 167 | ||
| ... | @@ -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 | } |
| 185 | 183 | ||
| 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 | } |
| 189 | 187 | ||
| ... | @@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type { | ... | @@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type { |
| 295 | } | 293 | } |
| 296 | 294 | ||
| 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 error | 297 | // 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; |
| 337 | fn windowsAsyncReadToFifoAndQueueSmallRead( | 335 | fn 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); |
| 349 | 347 | ||
| 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 | }; |
| 367 | 365 | ||
| 368 | read_any_data = true; | 366 | read_any_data = true; |
| 369 | br.update(num_bytes_read); | 367 | r.update(num_bytes_read); |
| 370 | 368 | ||
| 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 | } |
| 401 | 399 | ||
| 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 { |
| 488 | 486 | ||
| 489 | test { | 487 | test { |
| 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 of | 6 | //! `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 the | 7 | //! an array list, filling it up completely before making a call through the |
| 8 | //! vtable, causing a resize. Consequently, the same, optimized, non-generic | 8 | //! 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. |
| 11 | 11 | ||
| 12 | const std = @import("../std.zig"); | 12 | const std = @import("../std.zig"); |
lib/std/io/BufferedReader.zig deleted-1230| ... | @@ -1,1230 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const native_endian = builtin.target.cpu.arch.endian(); | ||
| 3 | |||
| 4 | const std = @import("../std.zig"); | ||
| 5 | const assert = std.debug.assert; | ||
| 6 | const testing = std.testing; | ||
| 7 | const BufferedWriter = std.io.BufferedWriter; | ||
| 8 | const Reader = std.io.Reader; | ||
| 9 | const Writer = std.io.Writer; | ||
| 10 | const Allocator = std.mem.Allocator; | ||
| 11 | const ArrayList = std.ArrayListUnmanaged; | ||
| 12 | const Limit = std.io.Limit; | ||
| 13 | |||
| 14 | const BufferedReader = @This(); | ||
| 15 | |||
| 16 | unbuffered_reader: Reader, | ||
| 17 | buffer: []u8, | ||
| 18 | /// In `buffer` before this are buffered bytes, after this is `undefined`. | ||
| 19 | end: usize, | ||
| 20 | /// Number of bytes which have been consumed from `buffer`. | ||
| 21 | seek: 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`. | ||
| 27 | pub 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 | |||
| 36 | pub fn bufferContents(br: *BufferedReader) []u8 { | ||
| 37 | return br.buffer[br.seek..br.end]; | ||
| 38 | } | ||
| 39 | |||
| 40 | pub 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. | ||
| 47 | pub 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 | |||
| 58 | pub 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`. | ||
| 63 | pub 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`. | ||
| 68 | pub 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`. | ||
| 73 | pub fn discard(br: *BufferedReader, limit: Limit) Reader.Error!usize { | ||
| 74 | return passthruDiscard(br, limit); | ||
| 75 | } | ||
| 76 | |||
| 77 | pub 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. | ||
| 95 | pub 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`. | ||
| 107 | pub 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. | ||
| 118 | pub 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 | |||
| 170 | fn 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 | |||
| 181 | fn 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 | |||
| 197 | fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize { | ||
| 198 | const br: *BufferedReader = @alignCast(@ptrCast(context)); | ||
| 199 | return readVecLimit(br, data, .unlimited); | ||
| 200 | } | ||
| 201 | |||
| 202 | fn 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` | ||
| 238 | pub 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` | ||
| 257 | pub 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`. | ||
| 272 | pub 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())`. | ||
| 278 | pub 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. | ||
| 287 | pub 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` | ||
| 304 | pub 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` | ||
| 320 | pub 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` | ||
| 335 | pub fn discardAll(br: *BufferedReader, n: usize) Reader.Error!void { | ||
| 336 | if ((try br.discardShort(n)) != n) return error.EndOfStream; | ||
| 337 | } | ||
| 338 | |||
| 339 | pub 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` | ||
| 359 | pub 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. | ||
| 381 | pub 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` | ||
| 398 | pub 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` | ||
| 413 | pub 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` | ||
| 453 | pub 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 | |||
| 463 | pub 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. | ||
| 467 | pub 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 | |||
| 481 | pub 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` | ||
| 499 | pub 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` | ||
| 518 | pub 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 | |||
| 556 | pub 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` | ||
| 579 | pub 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 | |||
| 585 | pub 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` | ||
| 601 | pub 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` | ||
| 618 | pub 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` | ||
| 659 | pub 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` | ||
| 689 | pub 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. | ||
| 704 | pub 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. | ||
| 719 | pub 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 | |||
| 731 | pub 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. | ||
| 742 | pub 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 | |||
| 756 | fn 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. | ||
| 786 | pub 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. | ||
| 796 | pub 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`. | ||
| 809 | pub 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. | ||
| 826 | pub 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. | ||
| 836 | pub 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. | ||
| 849 | pub 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. | ||
| 856 | pub 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`. | ||
| 861 | pub 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`. | ||
| 867 | pub 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` | ||
| 878 | pub 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` | ||
| 890 | pub 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. | ||
| 900 | pub 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. | ||
| 910 | pub 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 | |||
| 916 | pub 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)`. | ||
| 923 | pub 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)`. | ||
| 932 | pub 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 | |||
| 942 | pub const TakeLeb128Error = Reader.Error || error{Overflow}; | ||
| 943 | |||
| 944 | /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. | ||
| 945 | pub 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 | |||
| 953 | pub 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 | |||
| 964 | pub const FillAllocError = Reader.Error || Allocator.Error; | ||
| 965 | |||
| 966 | pub 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. | ||
| 976 | pub 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. | ||
| 997 | pub fn advanceBufferEnd(br: *BufferedReader, n: usize) void { | ||
| 998 | assert(n <= br.buffer.len - br.end); | ||
| 999 | br.end += n; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | fn 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. | ||
| 1033 | pub 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. | ||
| 1045 | pub 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. | ||
| 1057 | pub 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. | ||
| 1068 | pub 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 | |||
| 1074 | test 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 | |||
| 1087 | test peek { | ||
| 1088 | return error.Unimplemented; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | test peekGreedy { | ||
| 1092 | return error.Unimplemented; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | test toss { | ||
| 1096 | return error.Unimplemented; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | test take { | ||
| 1100 | return error.Unimplemented; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | test takeArray { | ||
| 1104 | return error.Unimplemented; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | test peekArray { | ||
| 1108 | return error.Unimplemented; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | test 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 | |||
| 1120 | test discardRemaining { | ||
| 1121 | return error.Unimplemented; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | test read { | ||
| 1125 | return error.Unimplemented; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | test takeSentinel { | ||
| 1129 | return error.Unimplemented; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | test peekSentinel { | ||
| 1133 | return error.Unimplemented; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | test takeDelimiterInclusive { | ||
| 1137 | return error.Unimplemented; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | test peekDelimiterInclusive { | ||
| 1141 | return error.Unimplemented; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | test takeDelimiterExclusive { | ||
| 1145 | return error.Unimplemented; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | test peekDelimiterExclusive { | ||
| 1149 | return error.Unimplemented; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | test readDelimiter { | ||
| 1153 | return error.Unimplemented; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | test readDelimiterEnding { | ||
| 1157 | return error.Unimplemented; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | test readDelimiterLimit { | ||
| 1161 | return error.Unimplemented; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | test discardDelimiterExclusive { | ||
| 1165 | return error.Unimplemented; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | test discardDelimiterInclusive { | ||
| 1169 | return error.Unimplemented; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | test fill { | ||
| 1173 | return error.Unimplemented; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | test takeByte { | ||
| 1177 | return error.Unimplemented; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | test takeByteSigned { | ||
| 1181 | return error.Unimplemented; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | test takeInt { | ||
| 1185 | return error.Unimplemented; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | test takeVarInt { | ||
| 1189 | return error.Unimplemented; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | test takeStruct { | ||
| 1193 | return error.Unimplemented; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | test peekStruct { | ||
| 1197 | return error.Unimplemented; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | test takeStructEndian { | ||
| 1201 | return error.Unimplemented; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | test peekStructEndian { | ||
| 1205 | return error.Unimplemented; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | test takeEnum { | ||
| 1209 | return error.Unimplemented; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | test takeLeb128 { | ||
| 1213 | return error.Unimplemented; | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | test readSliceShort { | ||
| 1217 | return error.Unimplemented; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | test readVec { | ||
| 1221 | return error.Unimplemented; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | test "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 @@ |
| 1 | const std = @import("../std.zig"); | ||
| 2 | const Reader = @This(); | 1 | const Reader = @This(); |
| 2 | |||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const native_endian = builtin.target.cpu.arch.endian(); | ||
| 5 | |||
| 6 | const std = @import("../std.zig"); | ||
| 7 | const Writer = std.io.Writer; | ||
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| 4 | const BufferedWriter = std.io.BufferedWriter; | 9 | const testing = std.testing; |
| 5 | const BufferedReader = std.io.BufferedReader; | ||
| 6 | const Allocator = std.mem.Allocator; | 10 | const Allocator = std.mem.Allocator; |
| 7 | const ArrayList = std.ArrayListUnmanaged; | 11 | const ArrayList = std.ArrayListUnmanaged; |
| 8 | const Limit = std.io.Limit; | 12 | const 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"); |
| 11 | 15 | ||
| 12 | context: ?*anyopaque, | 16 | context: ?*anyopaque, |
| 13 | vtable: *const VTable, | 17 | vtable: *const VTable, |
| 18 | buffer: []u8, | ||
| 19 | /// Number of bytes which have been consumed from `buffer`. | ||
| 20 | seek: usize, | ||
| 21 | /// In `buffer` before this are buffered bytes, after this is `undefined`. | ||
| 22 | end: usize, | ||
| 14 | 23 | ||
| 15 | pub const VTable = struct { | 24 | pub 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` and | 27 | /// Returns the number of bytes written, which will be at minimum `0` and |
| 19 | /// at most `limit`. The number returned, including zero, does not indicate | 28 | /// 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 buffer | 35 | /// 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, |
| 30 | 39 | ||
| 31 | /// Consumes bytes from the internally tracked stream position without | 40 | /// 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 is | 54 | /// The default implementation is is based on calling `read`, borrowing |
| 46 | /// provided which is based on calling `read`, borrowing | 55 | /// `buffer` to construct a temporary `Writer` and ignoring the written |
| 47 | /// `BufferedReader.buffer` to construct a temporary `BufferedWriter` and | 56 | /// 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 | }; |
| 51 | 59 | ||
| 52 | pub const StreamError = error{ | 60 | pub 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 | }; |
| 79 | 87 | ||
| 80 | pub fn read(r: Reader, bw: *BufferedWriter, limit: Limit) StreamError!usize { | 88 | pub 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 | |||
| 99 | pub const ending: Reader = .fixed(&.{}); | ||
| 100 | |||
| 101 | pub 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. | ||
| 106 | pub 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 | |||
| 121 | pub 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 | } |
| 87 | 135 | ||
| 88 | pub fn discard(r: Reader, limit: Limit) Error!usize { | 136 | pub 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 | |||
| 152 | pub 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 | } |
| 93 | 170 | ||
| 94 | /// Returns total number of bytes written to `bw`. | 171 | /// "Pump" data from the reader to the writer, handling `error.EndOfStream` as |
| 95 | pub 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`. | ||
| 175 | pub 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 |
| 105 | 184 | ||
| 106 | /// Consumes the stream until the end, ignoring all the data, returning the | 185 | /// Consumes the stream until the end, ignoring all the data, returning the |
| 107 | /// number of bytes discarded. | 186 | /// number of bytes discarded. |
| 108 | pub fn discardRemaining(r: Reader) ShortError!usize { | 187 | pub 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, up | 201 | /// 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, the | 204 | /// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In |
| 125 | /// stream is advanced one byte beyond the limit, and the consumed data is | 205 | /// 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` | 212 | pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 { |
| 131 | pub 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 | } |
| 137 | 218 | ||
| 138 | /// Transfers all bytes from the current position to the end of the stream, up | 219 | /// 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 exceeded | 226 | /// Asserts `buffer` has nonzero capacity. |
| 147 | /// limit. | ||
| 148 | /// | 227 | /// |
| 149 | /// See also: | 228 | /// See also: |
| 150 | /// * `BufferedReader.readRemainingArrayList` | 229 | /// * `allocRemaining` |
| 151 | pub fn readRemainingArrayList( | 230 | pub 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 | } |
| 171 | 267 | ||
| 172 | pub 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. | ||
| 276 | pub 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. | ||
| 287 | pub 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 | |||
| 339 | pub fn bufferContents(r: *Reader) []u8 { | ||
| 340 | return r.buffer[r.seek..r.end]; | ||
| 341 | } | ||
| 342 | |||
| 343 | pub fn bufferedLen(r: *const Reader) usize { | ||
| 344 | return r.end - r.seek; | ||
| 345 | } | ||
| 346 | |||
| 347 | pub fn hashed(r: *Reader, hasher: anytype) Hashed(@TypeOf(hasher)) { | ||
| 348 | return .{ .in = r, .hasher = hasher }; | ||
| 349 | } | ||
| 350 | |||
| 351 | pub 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. | ||
| 369 | pub 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` | ||
| 391 | pub 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` | ||
| 410 | pub 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`. | ||
| 425 | pub 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())`. | ||
| 431 | pub 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. | ||
| 440 | pub 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` | ||
| 457 | pub 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` | ||
| 473 | pub 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` | ||
| 488 | pub fn discardAll(r: *Reader, n: usize) Error!void { | ||
| 489 | if ((try r.discardShort(n)) != n) return error.EndOfStream; | ||
| 490 | } | ||
| 491 | |||
| 492 | pub 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` | ||
| 512 | pub 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` | ||
| 543 | pub 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` | ||
| 558 | pub 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` | ||
| 598 | pub 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 | |||
| 608 | pub 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. | ||
| 612 | pub 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 | |||
| 626 | pub 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 | |||
| 633 | pub 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 | }; |
| 179 | 644 | ||
| 180 | pub 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` | ||
| 656 | pub 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 | |||
| 662 | pub 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` | ||
| 678 | pub 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` | ||
| 695 | pub 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` | ||
| 736 | pub 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` | ||
| 766 | pub 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. | ||
| 781 | pub 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. | ||
| 796 | pub 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 | |||
| 808 | pub 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 | }; |
| 187 | 814 | ||
| 188 | pub 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. | ||
| 819 | pub 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 | } |
| 191 | 832 | ||
| 192 | pub fn buffered(r: Reader, buffer: []u8) BufferedReader { | 833 | fn 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. | ||
| 863 | pub 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. | ||
| 873 | pub 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`. | ||
| 886 | pub 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. | ||
| 903 | pub 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. | ||
| 913 | pub 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. | ||
| 926 | pub 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. | ||
| 933 | pub 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`. | ||
| 938 | pub 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`. | ||
| 944 | pub 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` | ||
| 955 | pub 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` | ||
| 967 | pub 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. | ||
| 977 | pub 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. | ||
| 987 | pub 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 | |||
| 993 | pub 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)`. | ||
| 1000 | pub 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)`. | ||
| 1009 | pub 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 | } |
| 200 | 1018 | ||
| 201 | pub fn limited(r: Reader, limit: Limit) Limited { | 1019 | pub 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, | 1022 | pub 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 | |||
| 1030 | pub 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 | |||
| 1041 | pub const FillAllocError = Error || Allocator.Error; | ||
| 1042 | |||
| 1043 | pub 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. | ||
| 1053 | pub 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. | ||
| 1074 | pub fn advanceBufferEnd(r: *Reader, n: usize) void { | ||
| 1075 | assert(n <= r.buffer.len - r.end); | ||
| 1076 | r.end += n; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | fn 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. | ||
| 1110 | pub 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 | } |
| 207 | 1117 | ||
| 208 | fn 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. | ||
| 1122 | pub 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. | ||
| 1134 | pub 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. | ||
| 1145 | pub 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 | |||
| 1151 | test 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 | |||
| 1164 | test peek { | ||
| 1165 | return error.Unimplemented; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | test peekGreedy { | ||
| 1169 | return error.Unimplemented; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | test toss { | ||
| 1173 | return error.Unimplemented; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | test take { | ||
| 1177 | return error.Unimplemented; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | test takeArray { | ||
| 1181 | return error.Unimplemented; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | test peekArray { | ||
| 1185 | return error.Unimplemented; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | test 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 | |||
| 1197 | test discardRemaining { | ||
| 1198 | return error.Unimplemented; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | test stream { | ||
| 1202 | return error.Unimplemented; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | test takeSentinel { | ||
| 1206 | return error.Unimplemented; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | test peekSentinel { | ||
| 1210 | return error.Unimplemented; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | test takeDelimiterInclusive { | ||
| 1214 | return error.Unimplemented; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | test peekDelimiterInclusive { | ||
| 1218 | return error.Unimplemented; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | test takeDelimiterExclusive { | ||
| 1222 | return error.Unimplemented; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | test peekDelimiterExclusive { | ||
| 1226 | return error.Unimplemented; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | test readDelimiter { | ||
| 1230 | return error.Unimplemented; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | test readDelimiterEnding { | ||
| 1234 | return error.Unimplemented; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | test readDelimiterLimit { | ||
| 1238 | return error.Unimplemented; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | test discardDelimiterExclusive { | ||
| 1242 | return error.Unimplemented; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | test discardDelimiterInclusive { | ||
| 1246 | return error.Unimplemented; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | test fill { | ||
| 1250 | return error.Unimplemented; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | test takeByte { | ||
| 1254 | return error.Unimplemented; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | test takeByteSigned { | ||
| 1258 | return error.Unimplemented; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | test takeInt { | ||
| 1262 | return error.Unimplemented; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | test takeVarInt { | ||
| 1266 | return error.Unimplemented; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | test takeStruct { | ||
| 1270 | return error.Unimplemented; | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | test peekStruct { | ||
| 1274 | return error.Unimplemented; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | test takeStructEndian { | ||
| 1278 | return error.Unimplemented; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | test peekStructEndian { | ||
| 1282 | return error.Unimplemented; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | test takeEnum { | ||
| 1286 | return error.Unimplemented; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | test takeLeb128 { | ||
| 1290 | return error.Unimplemented; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | test readSliceShort { | ||
| 1294 | return error.Unimplemented; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | test readVec { | ||
| 1298 | return error.Unimplemented; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | test "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 | |||
| 1309 | fn 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 | } |
| 214 | 1315 | ||
| 215 | fn endingDiscard(context: ?*anyopaque, limit: Limit) Error!usize { | 1316 | fn 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 | } |
| 220 | 1321 | ||
| 221 | fn failingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize { | 1322 | fn 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 | } |
| 227 | 1328 | ||
| 228 | fn failingDiscard(context: ?*anyopaque, limit: Limit) Error!usize { | 1329 | fn 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. |
| 271 | pub fn Hashed(comptime Hasher: type) type { | 1372 | pub 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, | ||
| 275 | 1377 | ||
| 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 | } |
| 309 | 1393 | ||
| 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; |
| 5 | const BufferedWriter = std.io.BufferedWriter; | 5 | const BufferedWriter = std.io.BufferedWriter; |
| 6 | const Limit = std.io.Limit; | 6 | const Limit = std.io.Limit; |
| 7 | 7 | ||
| 8 | unlimited_reader: Reader, | 8 | unlimited: *Reader, |
| 9 | remaining: Limit, | 9 | remaining: Limit, |
| 10 | interface: Reader, | ||
| 10 | 11 | ||
| 11 | pub fn reader(l: *Limited) Reader { | 12 | pub 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 | } |
| 21 | 27 | ||
| 22 | fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize { | 28 | fn 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 | } |
| 29 | 35 | ||
| 30 | fn passthruDiscard(context: ?*anyopaque, limit: Limit) Reader.Error!usize { | 36 | fn 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 | |||
| 38 | fn 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 | } |
| 115 | 115 | ||
| 116 | fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T { | 116 | fn 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 | } |
| 121 | 120 | ||
| 122 | fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T { | 121 | fn 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 | } |
| 127 | 125 | ||
| 128 | fn test_read_ileb128(comptime T: type, encoded: []const u8) !T { | 126 | fn 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 | } |
| 133 | 130 | ||
| 134 | fn test_read_uleb128(comptime T: type, encoded: []const u8) !T { | 131 | fn 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 | } |
| 139 | 135 | ||
| 140 | fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void { | 136 | fn 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 | } |
| 148 | 143 | ||
| 149 | fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void { | 144 | fn 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; |
| 249 | 243 | ||
| 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; |
| 252 | 246 | ||
| 253 | // decode to a larger bit size too, to ensure sign extension | 247 | // decode to a larger bit size too, to ensure sign extension |
| 254 | // is working as expected | 248 | // 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); |
| 276 | 270 | ||
| 277 | // stream read | 271 | // 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 | } |
| 1594 | 1594 | ||
| 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 | }; |
| 350 | 350 | ||
| 351 | fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), br: *std.io.BufferedReader) !void { | 351 | fn 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 | } |
| 362 | 362 |
lib/std/tar.zig+15-15| ... | @@ -302,7 +302,7 @@ pub const FileKind = enum { | ... | @@ -302,7 +302,7 @@ pub const FileKind = enum { |
| 302 | 302 | ||
| 303 | /// Iterator over entries in the tar file represented by reader. | 303 | /// Iterator over entries in the tar file represented by reader. |
| 304 | pub const Iterator = struct { | 304 | pub const Iterator = struct { |
| 305 | reader: *std.io.BufferedReader, | 305 | reader: *std.io.Reader, |
| 306 | diagnostics: ?*Diagnostics = null, | 306 | diagnostics: ?*Diagnostics = null, |
| 307 | 307 | ||
| 308 | // buffers for heeader and file attributes | 308 | // buffers for heeader and file attributes |
| ... | @@ -328,7 +328,7 @@ pub const Iterator = struct { | ... | @@ -328,7 +328,7 @@ pub const Iterator = struct { |
| 328 | 328 | ||
| 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, |
| 346 | 346 | ||
| 347 | unread_bytes: *u64, | 347 | unread_bytes: *u64, |
| 348 | parent_reader: *std.io.BufferedReader, | 348 | parent_reader: *std.io.Reader, |
| 349 | 349 | ||
| 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; |
| 537 | 537 | ||
| 538 | pub const PaxIterator = struct { | 538 | pub const PaxIterator = struct { |
| 539 | size: usize, // cumulative size of all pax attributes | 539 | size: usize, // cumulative size of all pax attributes |
| 540 | reader: *std.io.BufferedReader, | 540 | reader: *std.io.Reader, |
| 541 | 541 | ||
| 542 | const Self = @This(); | 542 | const Self = @This(); |
| 543 | 543 | ||
| 544 | const Attribute = struct { | 544 | const Attribute = struct { |
| 545 | kind: PaxAttributeKind, | 545 | kind: PaxAttributeKind, |
| 546 | len: usize, // length of the attribute value | 546 | len: usize, // length of the attribute value |
| 547 | reader: *std.io.BufferedReader, // reader positioned at value start | 547 | reader: *std.io.Reader, // reader positioned at value start |
| 548 | 548 | ||
| 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 | } |
| 612 | 612 | ||
| 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 | }; |
| 618 | 618 | ||
| 619 | /// Saves tar file content to the file systems. | 619 | /// Saves tar file content to the file systems. |
| 620 | pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.BufferedReader, options: PipeOptions) !void { | 620 | pub 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; |
| 819 | 819 | ||
| 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); |
| 824 | 824 | ||
| ... | @@ -955,7 +955,7 @@ test Iterator { | ... | @@ -955,7 +955,7 @@ test Iterator { |
| 955 | // example/empty/ | 955 | // example/empty/ |
| 956 | 956 | ||
| 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); |
| 960 | 960 | ||
| 961 | // User provided buffers to the iterator | 961 | // User provided buffers to the iterator |
| ... | @@ -1015,7 +1015,7 @@ test pipeToFileSystem { | ... | @@ -1015,7 +1015,7 @@ test pipeToFileSystem { |
| 1015 | // example/empty/ | 1015 | // example/empty/ |
| 1016 | 1016 | ||
| 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); |
| 1020 | 1020 | ||
| 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 { |
| 1047 | 1047 | ||
| 1048 | test "pipeToFileSystem root_dir" { | 1048 | test "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); |
| 1052 | 1052 | ||
| 1053 | // with strip_components = 1 | 1053 | // with strip_components = 1 |
| ... | @@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" { | ... | @@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" { |
| 1096 | 1096 | ||
| 1097 | test "findRoot with single file archive" { | 1097 | test "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); |
| 1101 | 1101 | ||
| 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" { |
| 1111 | 1111 | ||
| 1112 | test "findRoot without explicit root dir" { | 1112 | test "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); |
| 1116 | 1116 | ||
| 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" { |
| 1126 | 1126 | ||
| 1127 | test "pipeToFileSystem strip_components" { | 1127 | test "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); |
| 1131 | 1131 | ||
| 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"); |
| 1189 | 1189 | ||
| 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); |
| 1193 | 1193 | ||
| 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, .{}); |
| 443 | 443 | ||
| 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 | } |
| 483 | 483 | ||
| 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; |
| 347 | 347 | ||
| 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] }; |
| 392 | 391 | ||
| 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; |
| 415 | 413 | ||
| 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); | ||
| 474 | 470 | ||
| 475 | // Unpack with strip_components = 1 should fail | 471 | // 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 | ); |
| 482 | 478 | ||
| 483 | // Unpack with strip_components = 0 should pass | 479 | // 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 | } |
| 489 | 485 | ||
| 490 | test "case sensitivity" { | 486 | test "case sensitivity" { |
| ... | @@ -498,13 +494,12 @@ test "case sensitivity" { | ... | @@ -498,13 +494,12 @@ test "case sensitivity" { |
| 498 | // 18089/alacritty/Darkermatrix.yml | 494 | // 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); | ||
| 503 | 498 | ||
| 504 | var root = std.testing.tmpDir(.{}); | 499 | var root = std.testing.tmpDir(.{}); |
| 505 | defer root.cleanup(); | 500 | defer root.cleanup(); |
| 506 | 501 | ||
| 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 file | 503 | // 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 | }; |
| 56 | 56 | ||
| 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 { |
| 215 | 215 | ||
| 216 | test "slim" { | 216 | test "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); |
| 220 | 220 | ||
| 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" { |
| 229 | 229 | ||
| 230 | test "fat" { | 230 | test "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); |
| 234 | 234 | ||
| 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" { |
| 243 | test "legacy" { | 243 | test "legacy" { |
| 244 | // Taken from Slackware 8.0, from 2001 | 244 | // 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); |
| 248 | 248 | ||
| 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 @@ |
| 1 | in: *std.io.BufferedReader, | 1 | in: *std.io.Reader, |
| 2 | out: *std.io.BufferedWriter, | 2 | out: *std.io.BufferedWriter, |
| 3 | 3 | ||
| 4 | pub const Message = struct { | 4 | pub const Message = struct { |
| ... | @@ -93,7 +93,7 @@ pub const Message = struct { | ... | @@ -93,7 +93,7 @@ pub const Message = struct { |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | pub const Options = struct { | 95 | pub 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 @@ |
| 1 | allocator: std.mem.Allocator, | 1 | allocator: std.mem.Allocator, |
| 2 | record_arena: std.heap.ArenaAllocator.State, | 2 | record_arena: std.heap.ArenaAllocator.State, |
| 3 | br: *std.io.BufferedReader, | 3 | reader: *std.io.Reader, |
| 4 | keep_names: bool, | 4 | keep_names: bool, |
| 5 | bit_buffer: u32, | 5 | bit_buffer: u32, |
| 6 | bit_offset: u5, | 6 | bit_offset: u5, |
| ... | @@ -93,14 +93,14 @@ pub const Record = struct { | ... | @@ -93,14 +93,14 @@ pub const Record = struct { |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | pub const InitOptions = struct { | 95 | pub 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 | }; |
| 99 | pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader { | 99 | pub 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 { |
| 172 | 172 | ||
| 173 | pub fn skipBlock(bc: *BitcodeReader, block: Block) !void { | 173 | pub 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 | } |
| 178 | 178 | ||
| ... | @@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void { | ... | @@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void { |
| 371 | 371 | ||
| 372 | fn read32Bits(bc: *BitcodeReader) !u32 { | 372 | fn 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 | } |
| 376 | 376 | ||
| 377 | fn readBytes(bc: *BitcodeReader, bytes: []u8) !void { | 377 | fn 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); |
| 380 | 380 | ||
| 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 { |
| 161 | 161 | ||
| 162 | pub const Decompress = union { | 162 | pub 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, |
| 165 | 165 | ||
| 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 | }; |
| 53 | 53 | ||
| 54 | fn makeZip(file_writer: *std.fs.File.Writer, files: []const File, options: WriteZipOptions) !std.io.BufferedReader { | 54 | fn 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(); |
| 1083 | 1082 | ||
| 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 | } |
| 81 | 81 | ||
| 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; |
| 594 | 594 | ||
| 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; |
| 1109 | 1109 | ||
| 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 | } |
| 1163 | 1163 | ||
| 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 | }; |
| 1189 | 1189 | ||
| 1190 | fn readSizeVarInt(r: *std.io.BufferedReader) !u64 { | 1190 | fn 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 | } |
| 1202 | 1202 | ||
| 1203 | fn readOffsetVarInt(r: *std.io.BufferedReader) !u64 { | 1203 | fn 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); |
| 1221 | 1221 | ||
| 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 | } |
| 1494 | 1494 | ||
| 1495 | /// Reads the complete contents of an object from `reader`. | 1495 | /// Reads the complete contents of an object from `reader`. |
| 1496 | fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u8 { | 1496 | fn 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 |
| 1505 | 1505 | ||
| 1506 | /// The format of the delta data is documented in | 1506 | /// 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). |
| 1508 | fn expandDelta(base_object: []const u8, delta_reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void { | 1508 | fn 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 | } |
| 2830 | 2830 | ||
| 2831 | pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *std.io.BufferedReader) !Zir { | 2831 | pub 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); |
| 2834 | 2834 | ||
| ... | @@ -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 | } |
| 2949 | 2949 | ||
| 2950 | pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_br: *std.io.BufferedReader) !Zoir { | 2950 | pub 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 | } |
| 373 | 373 | ||
| 374 | fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate { | 374 | fn 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 | } |
| 389 | 389 | ||
| 390 | fn parseOffset(dis: *Disassembler) !u64 { | 390 | fn 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 | } |
| 465 | 465 | ||
| 466 | fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 { | 466 | fn 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); |
| 795 | 795 | ||
| 796 | var inc_br: std.io.BufferedReader = undefined; | 796 | var inc_br: std.io.Reader = .fixed(metadata.inclusions); |
| 797 | inc_br.initFixed(metadata.inclusions); | ||
| 798 | 797 | ||
| 799 | const fn_inclusions_len = try inc_br.takeInt(u16, .little); | 798 | const fn_inclusions_len = try inc_br.takeInt(u16, .little); |
| 800 | 799 |
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 | } |
| 149 | 148 | ||
| ... | @@ -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()); | ||
| 1198 | 1197 | ||
| 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 | } |
| 1213 | 1212 | ||
| 1214 | return br.storageBuffer(); | 1213 | return r.storageBuffer(); |
| 1215 | } | 1214 | } |
| 1216 | 1215 | ||
| 1217 | fn locals(self: *Object) []Symbol { | 1216 | fn 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 | }; |
| 188 | 188 | ||
| 189 | pub const Iterator = struct { | 189 | pub const Iterator = struct { |
| 190 | br: std.io.BufferedReader, | 190 | reader: std.io.Reader, |
| 191 | 191 | ||
| 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 | }; |
| 197 | 197 | ||
| 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; |
| 200 | 200 | ||
| 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"); |
| 203 | 203 | ||
| 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); |
| 211 | 211 | ||
| 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 | } |
| 274 | 274 | ||
| 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 | } |
| 281 | 280 | ||
| 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 | } |
| 332 | 331 | ||
| 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 | } |
| 339 | 337 | ||
| 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 |
| 167 | 167 | ||
| 168 | fn parseTrieNode( | 168 | fn 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(); |
| 218 | 218 | ||
| 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 | } |
| 223 | 222 | ||
| 224 | fn parseTbd(self: *Dylib, macho_file: *MachO) !void { | 223 | fn 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(); |
| 14 | 14 | ||
| 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)); | ||
| 17 | 16 | ||
| 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? |
| 21 | 20 | ||
| 22 | _ = try br.takeLeb128(u64); // code alignment factor | 21 | _ = try r.takeLeb128(u64); // code alignment factor |
| 23 | _ = try br.takeLeb128(u64); // data alignment factor | 22 | _ = try r.takeLeb128(u64); // data alignment factor |
| 24 | _ = try br.takeLeb128(u64); // return address register | 23 | _ = try r.takeLeb128(u64); // return address register |
| 25 | _ = try br.takeLeb128(u64); // augmentation data length | 24 | _ = try r.takeLeb128(u64); // augmentation data length |
| 26 | 25 | ||
| 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 error | 30 | @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 error | 36 | @panic("unexpected personality pointer encoding"); // TODO error |
| 38 | } | 37 | } |
| 39 | _ = try br.takeInt(u32, .little); // personality pointer | 38 | _ = 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.?]; |
| 145 | 144 | ||
| 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)); |
| 148 | 147 | ||
| 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 | }; |
| 268 | 267 | ||
| 269 | pub const Iterator = struct { | 268 | pub const Iterator = struct { |
| 270 | br: std.io.BufferedReader, | 269 | br: std.io.Reader, |
| 271 | 270 | ||
| 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); |
| 2088 | 2088 | ||
| 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 | }; |
| 2096 | 2095 | ||
| ... | @@ -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; |
| 3040 | 3039 | ||
| 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()); |
| 3044 | 3043 |
src/link/Wasm/Archive.zig+2-4| ... | @@ -167,10 +167,8 @@ pub fn parseObject( | ... | @@ -167,10 +167,8 @@ pub fn parseObject( |
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 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 | } |
| 175 | 173 | ||
| 176 | const Archive = @This(); | 174 | const 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 { |
| 252 | 252 | ||
| 253 | pub fn parse( | 253 | pub 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 of | 1402 | /// 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 mandatory | 1403 | /// 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. |
| 1405 | fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) error{ OutOfMemory, LinkFailure }!Wasm.Feature.Set { | 1405 | fn 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 | } |
| 1432 | 1432 | ||
| 1433 | fn readLimits(br: *std.io.BufferedReader) std.io.Reader.Error!std.wasm.Limits { | 1433 | fn 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 | } |
| 1443 | 1443 | ||
| 1444 | fn readInit(wasm: *Wasm, br: *std.io.BufferedReader) std.io.Reader.Error!Wasm.Expr { | 1444 | fn 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 opcode | 1446 | 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 | } |
| 1449 | 1449 | ||
| 1450 | pub fn skipInit(br: *std.io.BufferedReader) std.io.Reader.Error!void { | 1450 | pub 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 | } |