| 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 | 1082 | at_eof: bool = false, |
| 1083 | 1083 | span: SourceMappings.CorrespondingSpan, |
| 1084 | 1084 | file: std.fs.File, |
| 1085 | buffered_reader: BufferedReaderType, | |
| 1085 | buffered_reader: *std.io.Reader, | |
| 1086 | 1086 | code_page: SupportedCodePage, |
| 1087 | 1087 | |
| 1088 | const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.Reader); | |
| 1089 | ||
| 1090 | 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 | 1089 | // We don't do line comparison for this error, so don't print the note if the line |
| 1092 | 1090 | // number is different |
| ... | ... | @@ -1105,7 +1103,7 @@ const CorrespondingLines = struct { |
| 1105 | 1103 | .buffered_reader = undefined, |
| 1106 | 1104 | .code_page = err_details.code_page, |
| 1107 | 1105 | }; |
| 1108 | corresponding_lines.buffered_reader = BufferedReaderType{ | |
| 1106 | corresponding_lines.buffered_reader = .{ | |
| 1109 | 1107 | .unbuffered_reader = corresponding_lines.file.reader(), |
| 1110 | 1108 | }; |
| 1111 | 1109 | errdefer corresponding_lines.deinit(); |
lib/compiler/std-docs.zig+1-1| ... | ... | @@ -390,7 +390,7 @@ fn receiveWasmMessage( |
| 390 | 390 | gpa: Allocator, |
| 391 | 391 | arena: Allocator, |
| 392 | 392 | context: *Context, |
| 393 | br: *std.io.BufferedReader, | |
| 393 | br: *std.io.Reader, | |
| 394 | 394 | result: *?Cache.Path, |
| 395 | 395 | result_error_bundle: *std.zig.ErrorBundle, |
| 396 | 396 | ) !void { |
lib/docs/wasm/main.zig+1-2| ... | ... | @@ -778,8 +778,7 @@ export fn decl_type_html(decl_index: Decl.Index) String { |
| 778 | 778 | const Oom = error{OutOfMemory}; |
| 779 | 779 | |
| 780 | 780 | fn unpackInner(tar_bytes: []u8) !void { |
| 781 | var br: std.io.BufferedReader = undefined; | |
| 782 | br.initFixed(tar_bytes); | |
| 781 | var br: std.io.Reader = .fixed(tar_bytes); | |
| 783 | 782 | var file_name_buffer: [1024]u8 = undefined; |
| 784 | 783 | var link_name_buffer: [1024]u8 = undefined; |
| 785 | 784 | var it = std.tar.Iterator.init(&br, .{ |
lib/std/Build/Step/CheckObject.zig+19-20| ... | ... | @@ -1238,8 +1238,7 @@ const MachODumper = struct { |
| 1238 | 1238 | } |
| 1239 | 1239 | |
| 1240 | 1240 | fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void { |
| 1241 | var br: std.io.BufferedReader = undefined; | |
| 1242 | br.initFixed(@constCast(data)); | |
| 1241 | var br: std.io.Reader = .fixed(data); | |
| 1243 | 1242 | |
| 1244 | 1243 | var seg_id: ?u8 = null; |
| 1245 | 1244 | var offset: u64 = 0; |
| ... | ... | @@ -1349,7 +1348,7 @@ const MachODumper = struct { |
| 1349 | 1348 | } |
| 1350 | 1349 | |
| 1351 | 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 | 1352 | br.initFixed(@constCast(data)); |
| 1354 | 1353 | |
| 1355 | 1354 | var seg_id: ?u8 = null; |
| ... | ... | @@ -1447,7 +1446,7 @@ const MachODumper = struct { |
| 1447 | 1446 | defer arena.deinit(); |
| 1448 | 1447 | |
| 1449 | 1448 | var exports: std.ArrayList(Export) = .init(arena.allocator()); |
| 1450 | var br: std.io.BufferedReader = undefined; | |
| 1449 | var br: std.io.Reader = undefined; | |
| 1451 | 1450 | br.initFixed(@constCast(data)); |
| 1452 | 1451 | try parseTrieNode(arena.allocator(), &br, "", &exports); |
| 1453 | 1452 | |
| ... | ... | @@ -1517,7 +1516,7 @@ const MachODumper = struct { |
| 1517 | 1516 | |
| 1518 | 1517 | fn parseTrieNode( |
| 1519 | 1518 | arena: Allocator, |
| 1520 | br: *std.io.BufferedReader, | |
| 1519 | br: *std.io.Reader, | |
| 1521 | 1520 | prefix: []const u8, |
| 1522 | 1521 | exports: *std.ArrayList(Export), |
| 1523 | 1522 | ) !void { |
| ... | ... | @@ -1705,7 +1704,7 @@ const ElfDumper = struct { |
| 1705 | 1704 | |
| 1706 | 1705 | fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 1707 | 1706 | const gpa = step.owner.allocator; |
| 1708 | var br: std.io.BufferedReader = undefined; | |
| 1707 | var br: std.io.Reader = undefined; | |
| 1709 | 1708 | br.initFixed(@constCast(bytes)); |
| 1710 | 1709 | |
| 1711 | 1710 | if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber; |
| ... | ... | @@ -1780,7 +1779,7 @@ const ElfDumper = struct { |
| 1780 | 1779 | } |
| 1781 | 1780 | |
| 1782 | 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 | 1783 | br.initFixed(@constCast(data)); |
| 1785 | 1784 | const num = switch (ptr_width) { |
| 1786 | 1785 | .p32 => try br.takeInt(u32, .big), |
| ... | ... | @@ -1851,7 +1850,7 @@ const ElfDumper = struct { |
| 1851 | 1850 | |
| 1852 | 1851 | fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 1853 | 1852 | const gpa = step.owner.allocator; |
| 1854 | var br: std.io.BufferedReader = undefined; | |
| 1853 | var br: std.io.Reader = undefined; | |
| 1855 | 1854 | br.initFixed(@constCast(bytes)); |
| 1856 | 1855 | |
| 1857 | 1856 | const hdr = try br.takeStruct(elf.Elf64_Ehdr); |
| ... | ... | @@ -2354,7 +2353,7 @@ const WasmDumper = struct { |
| 2354 | 2353 | |
| 2355 | 2354 | fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 2356 | 2355 | const gpa = step.owner.allocator; |
| 2357 | var br: std.io.BufferedReader = undefined; | |
| 2356 | var br: std.io.Reader = undefined; | |
| 2358 | 2357 | br.initFixed(@constCast(bytes)); |
| 2359 | 2358 | |
| 2360 | 2359 | const buf = try br.takeArray(8); |
| ... | ... | @@ -2376,10 +2375,10 @@ const WasmDumper = struct { |
| 2376 | 2375 | fn parseAndDumpInner( |
| 2377 | 2376 | step: *Step, |
| 2378 | 2377 | check: Check, |
| 2379 | br: *std.io.BufferedReader, | |
| 2378 | br: *std.io.Reader, | |
| 2380 | 2379 | bw: *std.io.BufferedWriter, |
| 2381 | 2380 | ) !void { |
| 2382 | var section_br: std.io.BufferedReader = undefined; | |
| 2381 | var section_br: std.io.Reader = undefined; | |
| 2383 | 2382 | switch (check.kind) { |
| 2384 | 2383 | .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| { |
| 2385 | 2384 | section_br.initFixed(try br.take(try br.takeLeb128(u32))); |
| ... | ... | @@ -2396,7 +2395,7 @@ const WasmDumper = struct { |
| 2396 | 2395 | fn parseAndDumpSection( |
| 2397 | 2396 | step: *Step, |
| 2398 | 2397 | section: std.wasm.Section, |
| 2399 | br: *std.io.BufferedReader, | |
| 2398 | br: *std.io.Reader, | |
| 2400 | 2399 | bw: *std.io.BufferedWriter, |
| 2401 | 2400 | ) !void { |
| 2402 | 2401 | try bw.print( |
| ... | ... | @@ -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 | 2448 | switch (section) { |
| 2450 | 2449 | .type => { |
| 2451 | 2450 | var i: u32 = 0; |
| ... | ... | @@ -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 | 2579 | const tag = br.takeEnum(E, .little) catch |err| switch (err) { |
| 2581 | 2580 | error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}), |
| 2582 | 2581 | else => |e| return e, |
| ... | ... | @@ -2585,7 +2584,7 @@ const WasmDumper = struct { |
| 2585 | 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 | 2588 | const flags = try br.takeLeb128(u8); |
| 2590 | 2589 | const min = try br.takeLeb128(u32); |
| 2591 | 2590 | |
| ... | ... | @@ -2593,7 +2592,7 @@ const WasmDumper = struct { |
| 2593 | 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 | 2596 | const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) { |
| 2598 | 2597 | error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}), |
| 2599 | 2598 | else => |e| return e, |
| ... | ... | @@ -2613,8 +2612,8 @@ const WasmDumper = struct { |
| 2613 | 2612 | } |
| 2614 | 2613 | |
| 2615 | 2614 | /// https://webassembly.github.io/spec/core/appendix/custom.html |
| 2616 | fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void { | |
| 2617 | var subsection_br: std.io.BufferedReader = undefined; | |
| 2615 | fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void { | |
| 2616 | var subsection_br: std.io.Reader = undefined; | |
| 2618 | 2617 | while (br.seek < br.buffer.len) { |
| 2619 | 2618 | switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) { |
| 2620 | 2619 | // The module name subsection ... consists of a single name |
| ... | ... | @@ -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 | 2665 | const field_count = try br.takeLeb128(u32); |
| 2667 | 2666 | try bw.print( |
| 2668 | 2667 | \\fields {d} |
| ... | ... | @@ -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 | 2693 | const feature_count = try br.takeLeb128(u32); |
| 2695 | 2694 | try bw.print( |
| 2696 | 2695 | \\features {d} |
lib/std/coff.zig+6-8| ... | ... | @@ -1087,10 +1087,9 @@ pub const Coff = struct { |
| 1087 | 1087 | const pe_pointer_offset = 0x3C; |
| 1088 | 1088 | const pe_magic = "PE\x00\x00"; |
| 1089 | 1089 | |
| 1090 | var reader: std.io.BufferedReader = undefined; | |
| 1091 | reader.initFixed(data[pe_pointer_offset..]); | |
| 1090 | var reader: std.io.Reader = .fixed(data[pe_pointer_offset..]); | |
| 1092 | 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 | 1093 | const magic = try reader.peek(4); |
| 1095 | 1094 | const is_image = mem.eql(u8, pe_magic, magic); |
| 1096 | 1095 | |
| ... | ... | @@ -1121,16 +1120,15 @@ pub const Coff = struct { |
| 1121 | 1120 | if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null; |
| 1122 | 1121 | |
| 1123 | 1122 | const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)]; |
| 1124 | var reader: std.io.BufferedReader = undefined; | |
| 1125 | reader.initFixed(self.data); | |
| 1123 | var reader: std.io.Reader = .fixed(self.data); | |
| 1126 | 1124 | |
| 1127 | 1125 | if (self.is_loaded) { |
| 1128 | reader.initFixed(self.data[debug_dir.virtual_address..]); | |
| 1126 | reader = .fixed(self.data[debug_dir.virtual_address..]); | |
| 1129 | 1127 | } else { |
| 1130 | 1128 | // Find what section the debug_dir is in, in order to convert the RVA to a file offset |
| 1131 | 1129 | for (self.getSectionHeaders()) |*sect| { |
| 1132 | 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 | 1132 | break; |
| 1135 | 1133 | } |
| 1136 | 1134 | } else return error.InvalidDebugDirectory; |
| ... | ... | @@ -1144,7 +1142,7 @@ pub const Coff = struct { |
| 1144 | 1142 | const debug_dir_entry = try reader.takeStruct(DebugDirectoryEntry); |
| 1145 | 1143 | if (debug_dir_entry.type == .CODEVIEW) { |
| 1146 | 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 | 1146 | break; |
| 1149 | 1147 | } |
| 1150 | 1148 | } else return null; |
lib/std/compress/flate.zig+22-44| ... | ... | @@ -229,8 +229,7 @@ test "compress/decompress" { |
| 229 | 229 | |
| 230 | 230 | // compress original stream to compressed stream |
| 231 | 231 | { |
| 232 | var original: std.io.BufferedReader = undefined; | |
| 233 | original.initFixed(@constCast(data)); | |
| 232 | var original: std.io.Reader = .fixed(data); | |
| 234 | 233 | var compressed: std.io.BufferedWriter = undefined; |
| 235 | 234 | compressed.initFixed(&cmp_buf); |
| 236 | 235 | var compress: Compress = .init(&original, .raw); |
| ... | ... | @@ -246,8 +245,7 @@ test "compress/decompress" { |
| 246 | 245 | } |
| 247 | 246 | // decompress compressed stream to decompressed stream |
| 248 | 247 | { |
| 249 | var compressed: std.io.BufferedReader = undefined; | |
| 250 | compressed.initFixed(cmp_buf[0..compressed_size]); | |
| 248 | var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]); | |
| 251 | 249 | var decompressed: std.io.BufferedWriter = undefined; |
| 252 | 250 | decompressed.initFixed(&dcm_buf); |
| 253 | 251 | try Decompress.pump(container, &compressed, &decompressed); |
| ... | ... | @@ -267,8 +265,7 @@ test "compress/decompress" { |
| 267 | 265 | } |
| 268 | 266 | // decompressor reader interface |
| 269 | 267 | { |
| 270 | var compressed: std.io.BufferedReader = undefined; | |
| 271 | compressed.initFixed(cmp_buf[0..compressed_size]); | |
| 268 | var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]); | |
| 272 | 269 | var dcm = Decompress.pump(container, &compressed); |
| 273 | 270 | var dcm_rdr = dcm.reader(); |
| 274 | 271 | const n = try dcm_rdr.readAll(&dcm_buf); |
| ... | ... | @@ -287,8 +284,7 @@ test "compress/decompress" { |
| 287 | 284 | |
| 288 | 285 | // compress original stream to compressed stream |
| 289 | 286 | { |
| 290 | var original: std.io.BufferedReader = undefined; | |
| 291 | original.initFixed(data); | |
| 287 | var original: std.io.Reader = .fixed(data); | |
| 292 | 288 | var compressed: std.io.BufferedWriter = undefined; |
| 293 | 289 | compressed.initFixed(&cmp_buf); |
| 294 | 290 | var cmp = try Compress.Huffman.init(container, &compressed); |
| ... | ... | @@ -303,8 +299,7 @@ test "compress/decompress" { |
| 303 | 299 | } |
| 304 | 300 | // decompress compressed stream to decompressed stream |
| 305 | 301 | { |
| 306 | var compressed: std.io.BufferedReader = undefined; | |
| 307 | compressed.initFixed(cmp_buf[0..compressed_size]); | |
| 302 | var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]); | |
| 308 | 303 | var decompressed: std.io.BufferedWriter = undefined; |
| 309 | 304 | decompressed.initFixed(&dcm_buf); |
| 310 | 305 | try Decompress.pump(container, &compressed, &decompressed); |
| ... | ... | @@ -323,8 +318,7 @@ test "compress/decompress" { |
| 323 | 318 | |
| 324 | 319 | // compress original stream to compressed stream |
| 325 | 320 | { |
| 326 | var original: std.io.BufferedReader = undefined; | |
| 327 | original.initFixed(data); | |
| 321 | var original: std.io.Reader = .fixed(data); | |
| 328 | 322 | var compressed: std.io.BufferedWriter = undefined; |
| 329 | 323 | compressed.initFixed(&cmp_buf); |
| 330 | 324 | var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed); |
| ... | ... | @@ -340,8 +334,7 @@ test "compress/decompress" { |
| 340 | 334 | } |
| 341 | 335 | // decompress compressed stream to decompressed stream |
| 342 | 336 | { |
| 343 | var compressed: std.io.BufferedReader = undefined; | |
| 344 | compressed.initFixed(cmp_buf[0..compressed_size]); | |
| 337 | var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]); | |
| 345 | 338 | var decompressed: std.io.BufferedWriter = undefined; |
| 346 | 339 | decompressed.initFixed(&dcm_buf); |
| 347 | 340 | try Decompress.pump(container, &compressed, &decompressed); |
| ... | ... | @@ -353,8 +346,7 @@ test "compress/decompress" { |
| 353 | 346 | } |
| 354 | 347 | |
| 355 | 348 | fn testDecompress(comptime container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
| 356 | var in: std.io.BufferedReader = undefined; | |
| 357 | in.initFixed(compressed); | |
| 349 | var in: std.io.Reader = .fixed(compressed); | |
| 358 | 350 | var out: std.io.AllocatingWriter = undefined; |
| 359 | 351 | out.init(testing.allocator); |
| 360 | 352 | defer out.deinit(); |
| ... | ... | @@ -502,8 +494,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const |
| 502 | 494 | var plain: std.io.BufferedWriter = undefined; |
| 503 | 495 | plain.initFixed(&buffer2); |
| 504 | 496 | |
| 505 | var in: std.io.BufferedReader = undefined; | |
| 506 | in.initFixed(gzip_data); | |
| 497 | var in: std.io.Reader = .fixed(gzip_data); | |
| 507 | 498 | try pkg.decompress(&in, &plain); |
| 508 | 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 | 506 | var compressed: std.io.BufferedWriter = undefined; |
| 516 | 507 | compressed.initFixed(&buffer1); |
| 517 | 508 | |
| 518 | var in: std.io.BufferedReader = undefined; | |
| 519 | in.initFixed(plain_data); | |
| 509 | var in: std.io.Reader = .fixed(plain_data); | |
| 520 | 510 | try pkg.compress(&in, &compressed, .{}); |
| 521 | 511 | |
| 522 | var compressed_br: std.io.BufferedReader = undefined; | |
| 523 | compressed_br.initFixed(&buffer1); | |
| 512 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 524 | 513 | try pkg.decompress(&compressed_br, &plain); |
| 525 | 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 | 521 | var compressed: std.io.BufferedWriter = undefined; |
| 533 | 522 | compressed.initFixed(&buffer1); |
| 534 | 523 | |
| 535 | var in: std.io.BufferedReader = undefined; | |
| 536 | in.initFixed(plain_data); | |
| 524 | var in: std.io.Reader = .fixed(plain_data); | |
| 537 | 525 | var cmp = try pkg.compressor(&compressed, .{}); |
| 538 | 526 | try cmp.compress(&in); |
| 539 | 527 | try cmp.finish(); |
| 540 | 528 | |
| 541 | var compressed_br: std.io.BufferedReader = undefined; | |
| 542 | compressed_br.initFixed(&buffer1); | |
| 529 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 543 | 530 | var dcp = pkg.decompressor(&compressed_br); |
| 544 | 531 | try dcp.decompress(&plain); |
| 545 | 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 | 541 | var compressed: std.io.BufferedWriter = undefined; |
| 555 | 542 | compressed.initFixed(&buffer1); |
| 556 | 543 | |
| 557 | var in: std.io.BufferedReader = undefined; | |
| 558 | in.initFixed(plain_data); | |
| 544 | var in: std.io.Reader = .fixed(plain_data); | |
| 559 | 545 | try pkg.huffman.compress(&in, &compressed); |
| 560 | 546 | |
| 561 | var compressed_br: std.io.BufferedReader = undefined; | |
| 562 | compressed_br.initFixed(&buffer1); | |
| 547 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 563 | 548 | try pkg.decompress(&compressed_br, &plain); |
| 564 | 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 | 556 | var compressed: std.io.BufferedWriter = undefined; |
| 572 | 557 | compressed.initFixed(&buffer1); |
| 573 | 558 | |
| 574 | var in: std.io.BufferedReader = undefined; | |
| 575 | in.initFixed(plain_data); | |
| 559 | var in: std.io.Reader = .fixed(plain_data); | |
| 576 | 560 | var cmp = try pkg.huffman.compressor(&compressed); |
| 577 | 561 | try cmp.compress(&in); |
| 578 | 562 | try cmp.finish(); |
| 579 | 563 | |
| 580 | var compressed_br: std.io.BufferedReader = undefined; | |
| 581 | compressed_br.initFixed(&buffer1); | |
| 564 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 582 | 565 | try pkg.decompress(&compressed_br, &plain); |
| 583 | 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 | 576 | var compressed: std.io.BufferedWriter = undefined; |
| 594 | 577 | compressed.initFixed(&buffer1); |
| 595 | 578 | |
| 596 | var in: std.io.BufferedReader = undefined; | |
| 597 | in.initFixed(plain_data); | |
| 579 | var in: std.io.Reader = .fixed(plain_data); | |
| 598 | 580 | try pkg.store.compress(&in, &compressed); |
| 599 | 581 | |
| 600 | var compressed_br: std.io.BufferedReader = undefined; | |
| 601 | compressed_br.initFixed(&buffer1); | |
| 582 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 602 | 583 | try pkg.decompress(&compressed_br, &plain); |
| 603 | 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 | 591 | var compressed: std.io.BufferedWriter = undefined; |
| 611 | 592 | compressed.initFixed(&buffer1); |
| 612 | 593 | |
| 613 | var in: std.io.BufferedReader = undefined; | |
| 614 | in.initFixed(plain_data); | |
| 594 | var in: std.io.Reader = .fixed(plain_data); | |
| 615 | 595 | var cmp = try pkg.store.compressor(&compressed); |
| 616 | 596 | try cmp.compress(&in); |
| 617 | 597 | try cmp.finish(); |
| 618 | 598 | |
| 619 | var compressed_br: std.io.BufferedReader = undefined; | |
| 620 | compressed_br.initFixed(&buffer1); | |
| 599 | var compressed_br: std.io.Reader = .fixed(&buffer1); | |
| 621 | 600 | try pkg.decompress(&compressed_br, &plain); |
| 622 | 601 | try testing.expectEqualSlices(u8, plain_data, plain.getWritten()); |
| 623 | 602 | } |
| ... | ... | @@ -650,8 +629,7 @@ test "zlib should not overshoot" { |
| 650 | 629 | 0x03, 0x00, 0x8b, 0x61, 0x0f, 0xa4, 0x52, 0x5a, 0x94, 0x12, |
| 651 | 630 | }; |
| 652 | 631 | |
| 653 | var stream: std.io.BufferedReader = undefined; | |
| 654 | stream.initFixed(&data); | |
| 632 | var stream: std.io.Reader = .fixed(&data); | |
| 655 | 633 | const reader = stream.reader(); |
| 656 | 634 | |
| 657 | 635 | var dcp = Decompress.init(reader); |
lib/std/compress/flate/Compress.zig+5-5| ... | ... | @@ -59,7 +59,7 @@ const huffman = flate.huffman; |
| 59 | 59 | lookup: Lookup = .{}, |
| 60 | 60 | tokens: Tokens = .{}, |
| 61 | 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 | 63 | block_writer: BlockWriter, |
| 64 | 64 | level: LevelArgs, |
| 65 | 65 | hasher: Container.Hasher, |
| ... | ... | @@ -69,7 +69,7 @@ hasher: Container.Hasher, |
| 69 | 69 | prev_match: ?Token = null, |
| 70 | 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 | 73 | return .{ |
| 74 | 74 | .unbuffered_reader = .{ |
| 75 | 75 | .context = c, |
| ... | ... | @@ -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 | 130 | return .{ |
| 131 | 131 | .input = input, |
| 132 | 132 | .block_writer = undefined, |
| ... | ... | @@ -1147,7 +1147,7 @@ test "file tokenization" { |
| 1147 | 1147 | const data = case.data; |
| 1148 | 1148 | |
| 1149 | 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 | 1151 | original.initFixed(data); |
| 1152 | 1152 | |
| 1153 | 1153 | // buffer for decompressed data |
| ... | ... | @@ -1222,7 +1222,7 @@ test "store simple compressor" { |
| 1222 | 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 | 1226 | fbs.initFixed(data); |
| 1227 | 1227 | var al = std.ArrayList(u8).init(testing.allocator); |
| 1228 | 1228 | defer al.deinit(); |
lib/std/compress/flate/Decompress.zig+9-9| ... | ... | @@ -24,7 +24,7 @@ const Token = @import("Token.zig"); |
| 24 | 24 | const testing = std.testing; |
| 25 | 25 | const Decompress = @This(); |
| 26 | 26 | |
| 27 | input: *std.io.BufferedReader, | |
| 27 | input: *std.io.Reader, | |
| 28 | 28 | // Hashes, produces checksum, of uncompressed data for gzip/zlib footer. |
| 29 | 29 | hasher: Container.Hasher, |
| 30 | 30 | |
| ... | ... | @@ -67,7 +67,7 @@ pub const Error = Container.Error || error{ |
| 67 | 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 | 71 | return .{ |
| 72 | 72 | .input = input, |
| 73 | 73 | .hasher = .init(container), |
| ... | ... | @@ -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 | 365 | return reader(self).buffered(buffer); |
| 366 | 366 | } |
| 367 | 367 | |
| ... | ... | @@ -727,7 +727,7 @@ test "decompress" { |
| 727 | 727 | }, |
| 728 | 728 | }; |
| 729 | 729 | for (cases) |c| { |
| 730 | var fb: std.io.BufferedReader = undefined; | |
| 730 | var fb: std.io.Reader = undefined; | |
| 731 | 731 | fb.initFixed(@constCast(c.in)); |
| 732 | 732 | var aw: std.io.AllocatingWriter = undefined; |
| 733 | 733 | aw.init(testing.allocator); |
| ... | ... | @@ -788,7 +788,7 @@ test "gzip decompress" { |
| 788 | 788 | }, |
| 789 | 789 | }; |
| 790 | 790 | for (cases) |c| { |
| 791 | var fb: std.io.BufferedReader = undefined; | |
| 791 | var fb: std.io.Reader = undefined; | |
| 792 | 792 | fb.initFixed(@constCast(c.in)); |
| 793 | 793 | var aw: std.io.AllocatingWriter = undefined; |
| 794 | 794 | aw.init(testing.allocator); |
| ... | ... | @@ -818,7 +818,7 @@ test "zlib decompress" { |
| 818 | 818 | }, |
| 819 | 819 | }; |
| 820 | 820 | for (cases) |c| { |
| 821 | var fb: std.io.BufferedReader = undefined; | |
| 821 | var fb: std.io.Reader = undefined; | |
| 822 | 822 | fb.initFixed(@constCast(c.in)); |
| 823 | 823 | var aw: std.io.AllocatingWriter = undefined; |
| 824 | 824 | aw.init(testing.allocator); |
| ... | ... | @@ -880,7 +880,7 @@ test "fuzzing tests" { |
| 880 | 880 | }; |
| 881 | 881 | |
| 882 | 882 | inline for (cases, 0..) |c, case_no| { |
| 883 | var in: std.io.BufferedReader = undefined; | |
| 883 | var in: std.io.Reader = undefined; | |
| 884 | 884 | in.initFixed(@constCast(@embedFile("testdata/fuzz/" ++ c.input ++ ".input"))); |
| 885 | 885 | var aw: std.io.AllocatingWriter = undefined; |
| 886 | 886 | aw.init(testing.allocator); |
| ... | ... | @@ -903,7 +903,7 @@ test "bug 18966" { |
| 903 | 903 | const input = @embedFile("testdata/fuzz/bug_18966.input"); |
| 904 | 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 | 907 | in.initFixed(@constCast(input)); |
| 908 | 908 | var aw: std.io.AllocatingWriter = undefined; |
| 909 | 909 | aw.init(testing.allocator); |
| ... | ... | @@ -921,7 +921,7 @@ test "reading into empty buffer" { |
| 921 | 921 | 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen |
| 922 | 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 | 925 | in.initFixed(@constCast(input)); |
| 926 | 926 | var decomp: Decompress = .init(&in, .raw); |
| 927 | 927 | var decompress_br = decomp.readable(&.{}); |
lib/std/compress/lzma.zig+21-21| ... | ... | @@ -11,7 +11,7 @@ pub const RangeDecoder = struct { |
| 11 | 11 | range: u32, |
| 12 | 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 | 15 | const reserved = try br.takeByte(); |
| 16 | 16 | if (reserved != 0) return error.CorruptInput; |
| 17 | 17 | rd.* = .{ |
| ... | ... | @@ -25,14 +25,14 @@ pub const RangeDecoder = struct { |
| 25 | 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 | 29 | if (self.range < 0x0100_0000) { |
| 30 | 30 | self.range <<= 8; |
| 31 | 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 | 36 | self.range >>= 1; |
| 37 | 37 | |
| 38 | 38 | const bit = self.code >= self.range; |
| ... | ... | @@ -43,7 +43,7 @@ pub const RangeDecoder = struct { |
| 43 | 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 | 47 | var result: u32 = 0; |
| 48 | 48 | var i: usize = 0; |
| 49 | 49 | while (i < count) : (i += 1) |
| ... | ... | @@ -51,7 +51,7 @@ pub const RangeDecoder = struct { |
| 51 | 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 | 55 | const bound = (self.range >> 11) * prob.*; |
| 56 | 56 | |
| 57 | 57 | if (self.code < bound) { |
| ... | ... | @@ -74,7 +74,7 @@ pub const RangeDecoder = struct { |
| 74 | 74 | |
| 75 | 75 | fn parseBitTree( |
| 76 | 76 | self: *RangeDecoder, |
| 77 | br: *std.io.BufferedReader, | |
| 77 | br: *std.io.Reader, | |
| 78 | 78 | num_bits: u5, |
| 79 | 79 | probs: []u16, |
| 80 | 80 | update: bool, |
| ... | ... | @@ -90,7 +90,7 @@ pub const RangeDecoder = struct { |
| 90 | 90 | |
| 91 | 91 | pub fn parseReverseBitTree( |
| 92 | 92 | self: *RangeDecoder, |
| 93 | br: *std.io.BufferedReader, | |
| 93 | br: *std.io.Reader, | |
| 94 | 94 | num_bits: u5, |
| 95 | 95 | probs: []u16, |
| 96 | 96 | offset: usize, |
| ... | ... | @@ -117,7 +117,7 @@ pub const LenDecoder = struct { |
| 117 | 117 | |
| 118 | 118 | pub fn decode( |
| 119 | 119 | self: *LenDecoder, |
| 120 | br: *std.io.BufferedReader, | |
| 120 | br: *std.io.Reader, | |
| 121 | 121 | decoder: *RangeDecoder, |
| 122 | 122 | pos_state: usize, |
| 123 | 123 | update: bool, |
| ... | ... | @@ -148,7 +148,7 @@ pub fn BitTree(comptime num_bits: usize) type { |
| 148 | 148 | |
| 149 | 149 | pub fn parse( |
| 150 | 150 | self: *Self, |
| 151 | br: *std.io.BufferedReader, | |
| 151 | br: *std.io.Reader, | |
| 152 | 152 | decoder: *RangeDecoder, |
| 153 | 153 | update: bool, |
| 154 | 154 | ) !u32 { |
| ... | ... | @@ -157,7 +157,7 @@ pub fn BitTree(comptime num_bits: usize) type { |
| 157 | 157 | |
| 158 | 158 | pub fn parseReverse( |
| 159 | 159 | self: *Self, |
| 160 | br: *std.io.BufferedReader, | |
| 160 | br: *std.io.Reader, | |
| 161 | 161 | decoder: *RangeDecoder, |
| 162 | 162 | update: bool, |
| 163 | 163 | ) !u32 { |
| ... | ... | @@ -222,7 +222,7 @@ pub const Decode = struct { |
| 222 | 222 | dict_size: u32, |
| 223 | 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 | 226 | var props = try br.readByte(); |
| 227 | 227 | if (props >= 225) { |
| 228 | 228 | return error.CorruptInput; |
| ... | ... | @@ -319,7 +319,7 @@ pub const Decode = struct { |
| 319 | 319 | fn processNextInner( |
| 320 | 320 | self: *Decode, |
| 321 | 321 | allocator: Allocator, |
| 322 | br: *std.io.BufferedReader, | |
| 322 | br: *std.io.Reader, | |
| 323 | 323 | bw: *std.io.BufferedWriter, |
| 324 | 324 | buffer: anytype, |
| 325 | 325 | decoder: *RangeDecoder, |
| ... | ... | @@ -416,7 +416,7 @@ pub const Decode = struct { |
| 416 | 416 | fn processNext( |
| 417 | 417 | self: *Decode, |
| 418 | 418 | allocator: Allocator, |
| 419 | br: *std.io.BufferedReader, | |
| 419 | br: *std.io.Reader, | |
| 420 | 420 | bw: *std.io.BufferedWriter, |
| 421 | 421 | buffer: anytype, |
| 422 | 422 | decoder: *RangeDecoder, |
| ... | ... | @@ -428,7 +428,7 @@ pub const Decode = struct { |
| 428 | 428 | pub fn process( |
| 429 | 429 | self: *Decode, |
| 430 | 430 | allocator: Allocator, |
| 431 | br: *std.io.BufferedReader, | |
| 431 | br: *std.io.Reader, | |
| 432 | 432 | bw: *std.io.BufferedWriter, |
| 433 | 433 | buffer: anytype, |
| 434 | 434 | decoder: *RangeDecoder, |
| ... | ... | @@ -460,7 +460,7 @@ pub const Decode = struct { |
| 460 | 460 | |
| 461 | 461 | fn decodeLiteral( |
| 462 | 462 | self: *Decode, |
| 463 | br: *std.io.BufferedReader, | |
| 463 | br: *std.io.Reader, | |
| 464 | 464 | buffer: anytype, |
| 465 | 465 | decoder: *RangeDecoder, |
| 466 | 466 | update: bool, |
| ... | ... | @@ -502,7 +502,7 @@ pub const Decode = struct { |
| 502 | 502 | |
| 503 | 503 | fn decodeDistance( |
| 504 | 504 | self: *Decode, |
| 505 | br: *std.io.BufferedReader, | |
| 505 | br: *std.io.Reader, | |
| 506 | 506 | decoder: *RangeDecoder, |
| 507 | 507 | length: usize, |
| 508 | 508 | update: bool, |
| ... | ... | @@ -542,19 +542,19 @@ pub const Decompress = struct { |
| 542 | 542 | error{ CorruptInput, EndOfStream, Overflow }; |
| 543 | 543 | |
| 544 | 544 | allocator: Allocator, |
| 545 | in_reader: *std.io.BufferedReader, | |
| 545 | in_reader: *std.io.Reader, | |
| 546 | 546 | to_read: std.ArrayListUnmanaged(u8), |
| 547 | 547 | |
| 548 | 548 | buffer: LzCircularBuffer, |
| 549 | 549 | decoder: RangeDecoder, |
| 550 | 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 | 553 | const params = try Decode.Params.readHeader(br, options); |
| 554 | 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 | 558 | return .{ |
| 559 | 559 | .allocator = allocator, |
| 560 | 560 | .in_reader = source, |
| ... | ... | @@ -839,7 +839,7 @@ test "Vec2D get addition overflow" { |
| 839 | 839 | |
| 840 | 840 | fn testDecompress(compressed: []const u8) ![]u8 { |
| 841 | 841 | const allocator = std.testing.allocator; |
| 842 | var br: std.io.BufferedReader = undefined; | |
| 842 | var br: std.io.Reader = undefined; | |
| 843 | 843 | br.initFixed(compressed); |
| 844 | 844 | var decompressor = try Decompress.initOptions(allocator, &br, .{}); |
| 845 | 845 | defer decompressor.deinit(); |
| ... | ... | @@ -927,7 +927,7 @@ test "too small uncompressed size in header" { |
| 927 | 927 | |
| 928 | 928 | test "reading one byte" { |
| 929 | 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 | 931 | br.initFixed(compressed); |
| 932 | 932 | var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{}); |
| 933 | 933 | defer decompressor.deinit(); |
lib/std/compress/lzma2.zig+5-5| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../std.zig"); |
| 2 | 2 | const Allocator = std.mem.Allocator; |
| 3 | 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 | 6 | var decoder = try Decode.init(gpa); |
| 7 | 7 | defer decoder.deinit(gpa); |
| 8 | 8 | return decoder.decompress(gpa, reader, writer); |
| ... | ... | @@ -33,7 +33,7 @@ pub const Decode = struct { |
| 33 | 33 | pub fn decompress( |
| 34 | 34 | self: *Decode, |
| 35 | 35 | allocator: Allocator, |
| 36 | reader: *std.io.BufferedReader, | |
| 36 | reader: *std.io.Reader, | |
| 37 | 37 | writer: *std.io.BufferedWriter, |
| 38 | 38 | ) !void { |
| 39 | 39 | var accum = LzAccumBuffer.init(std.math.maxInt(usize)); |
| ... | ... | @@ -56,7 +56,7 @@ pub const Decode = struct { |
| 56 | 56 | fn parseLzma( |
| 57 | 57 | self: *Decode, |
| 58 | 58 | allocator: Allocator, |
| 59 | br: *std.io.BufferedReader, | |
| 59 | br: *std.io.Reader, | |
| 60 | 60 | writer: *std.io.BufferedWriter, |
| 61 | 61 | accum: *LzAccumBuffer, |
| 62 | 62 | status: u8, |
| ... | ... | @@ -149,7 +149,7 @@ pub const Decode = struct { |
| 149 | 149 | |
| 150 | 150 | fn parseUncompressed( |
| 151 | 151 | allocator: Allocator, |
| 152 | reader: *std.io.BufferedReader, | |
| 152 | reader: *std.io.Reader, | |
| 153 | 153 | writer: *std.io.BufferedWriter, |
| 154 | 154 | accum: *LzAccumBuffer, |
| 155 | 155 | reset_dict: bool, |
| ... | ... | @@ -276,7 +276,7 @@ test decompress { |
| 276 | 276 | 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, |
| 277 | 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 | 280 | stream.initFixed(&compressed); |
| 281 | 281 | var decomp: std.io.AllocatingWriter = undefined; |
| 282 | 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 | 3 | const xz = std.compress.xz; |
| 4 | 4 | |
| 5 | 5 | fn decompress(data: []const u8) ![]u8 { |
| 6 | var in_stream: std.io.BufferedReader = undefined; | |
| 7 | in_stream.initFixed(data); | |
| 6 | var r: std.io.Reader = .fixed(data); | |
| 8 | 7 | |
| 9 | var xz_stream = try xz.decompress(testing.allocator, &in_stream); | |
| 8 | var xz_stream = try xz.decompress(testing.allocator, &r); | |
| 10 | 9 | defer xz_stream.deinit(); |
| 11 | 10 | |
| 12 | 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 | 82 | var out: std.ArrayListUnmanaged(u8) = .empty; |
| 83 | 83 | defer out.deinit(gpa); |
| 84 | 84 | |
| 85 | var in: std.io.BufferedReader = undefined; | |
| 86 | in.initFixed(@constCast(compressed)); | |
| 85 | var in: std.io.Reader = .fixed(compressed); | |
| 87 | 86 | var zstd_stream: Decompress = .init(&in, .{}); |
| 88 | 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 | 102 | var out: std.ArrayListUnmanaged(u8) = .empty; |
| 104 | 103 | defer out.deinit(gpa); |
| 105 | 104 | |
| 106 | var in: std.io.BufferedReader = undefined; | |
| 107 | in.initFixed(@constCast(compressed)); | |
| 105 | var in: std.io.Reader = .fixed(compressed); | |
| 108 | 106 | var zstd_stream: Decompress = .init(&in, .{}); |
| 109 | 107 | try std.testing.expectError( |
| 110 | 108 | error.ReadFailed, |
lib/std/compress/zstd/Decompress.zig+11-12| ... | ... | @@ -4,10 +4,9 @@ const assert = std.debug.assert; |
| 4 | 4 | const Reader = std.io.Reader; |
| 5 | 5 | const Limit = std.io.Limit; |
| 6 | 6 | const BufferedWriter = std.io.BufferedWriter; |
| 7 | const BufferedReader = std.io.BufferedReader; | |
| 8 | 7 | const zstd = @import("../zstd.zig"); |
| 9 | 8 | |
| 10 | input: *BufferedReader, | |
| 9 | input: *Reader, | |
| 11 | 10 | state: State, |
| 12 | 11 | verify_checksum: bool, |
| 13 | 12 | err: ?Error = null, |
| ... | ... | @@ -63,7 +62,7 @@ pub const Error = error{ |
| 63 | 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 | 66 | return .{ |
| 68 | 67 | .input = input, |
| 69 | 68 | .state = .new_frame, |
| ... | ... | @@ -305,7 +304,7 @@ pub const Frame = struct { |
| 305 | 304 | |
| 306 | 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 | 308 | const descriptor: Descriptor = @bitCast(try in.takeByte()); |
| 310 | 309 | |
| 311 | 310 | if (descriptor.reserved) return error.ReservedBitSet; |
| ... | ... | @@ -446,7 +445,7 @@ pub const Frame = struct { |
| 446 | 445 | /// FSE tables from `in`. |
| 447 | 446 | pub fn prepare( |
| 448 | 447 | self: *Decode, |
| 449 | in: *BufferedReader, | |
| 448 | in: *Reader, | |
| 450 | 449 | remaining: *Limit, |
| 451 | 450 | literals: LiteralsSection, |
| 452 | 451 | sequences_header: SequencesSection.Header, |
| ... | ... | @@ -536,7 +535,7 @@ pub const Frame = struct { |
| 536 | 535 | /// TODO: don't use `@field` |
| 537 | 536 | fn updateFseTable( |
| 538 | 537 | self: *Decode, |
| 539 | in: *BufferedReader, | |
| 538 | in: *Reader, | |
| 540 | 539 | remaining: *Limit, |
| 541 | 540 | comptime choice: DataType, |
| 542 | 541 | mode: SequencesSection.Header.Mode, |
| ... | ... | @@ -858,7 +857,7 @@ pub const LiteralsSection = struct { |
| 858 | 857 | compressed_size: ?u18, |
| 859 | 858 | |
| 860 | 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 | 861 | remaining.* = remaining.subtract(1) orelse return error.EndOfStream; |
| 863 | 862 | const byte0 = try in.takeByte(); |
| 864 | 863 | const block_type: BlockType = @enumFromInt(byte0 & 0b11); |
| ... | ... | @@ -965,7 +964,7 @@ pub const LiteralsSection = struct { |
| 965 | 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 | 968 | remaining.* = remaining.subtract(1) orelse return error.EndOfStream; |
| 970 | 969 | const header = try in.takeByte(); |
| 971 | 970 | if (header < 128) { |
| ... | ... | @@ -976,7 +975,7 @@ pub const LiteralsSection = struct { |
| 976 | 975 | } |
| 977 | 976 | |
| 978 | 977 | fn decodeDirect( |
| 979 | in: *BufferedReader, | |
| 978 | in: *Reader, | |
| 980 | 979 | remaining: *Limit, |
| 981 | 980 | encoded_symbol_count: usize, |
| 982 | 981 | ) HuffmanTree.DecodeError!HuffmanTree { |
| ... | ... | @@ -993,7 +992,7 @@ pub const LiteralsSection = struct { |
| 993 | 992 | } |
| 994 | 993 | |
| 995 | 994 | fn decodeFse( |
| 996 | in: *BufferedReader, | |
| 995 | in: *Reader, | |
| 997 | 996 | remaining: *Limit, |
| 998 | 997 | compressed_size: usize, |
| 999 | 998 | ) HuffmanTree.DecodeError!HuffmanTree { |
| ... | ... | @@ -1162,7 +1161,7 @@ pub const LiteralsSection = struct { |
| 1162 | 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 | 1165 | const header = try Header.decode(in, remaining); |
| 1167 | 1166 | switch (header.block_type) { |
| 1168 | 1167 | .raw => { |
| ... | ... | @@ -1233,7 +1232,7 @@ pub const SequencesSection = struct { |
| 1233 | 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 | 1236 | var sequence_count: u24 = undefined; |
| 1238 | 1237 | |
| 1239 | 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 | 154 | |
| 155 | 155 | test Tag { |
| 156 | 156 | const buf = [_]u8{0xa3}; |
| 157 | var stream: std.io.BufferedReader = undefined; | |
| 158 | stream.initFixed(&buf); | |
| 157 | var stream: std.io.Reader = .fixed(&buf); | |
| 159 | 158 | const t = Tag.decode(stream.reader()); |
| 160 | 159 | try std.testing.expectEqual(Tag.init(@enumFromInt(3), true, .context_specific), t); |
| 161 | 160 | } |
| ... | ... | @@ -185,8 +184,7 @@ pub const Element = struct { |
| 185 | 184 | /// - Ensures length is within `bytes` |
| 186 | 185 | /// - Ensures length is less than `std.math.maxInt(Index)` |
| 187 | 186 | pub fn decode(bytes: []const u8, index: Index) DecodeError!Element { |
| 188 | var reader: std.io.BufferedReader = undefined; | |
| 189 | reader.initFixed(bytes[index..]); | |
| 187 | var reader: std.io.Reader = .fixed(bytes[index..]); | |
| 190 | 188 | |
| 191 | 189 | const tag = try Tag.decode(reader); |
| 192 | 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 | 155 | } |
| 156 | 156 | |
| 157 | 157 | // Read a DER-encoded integer. |
| 158 | // Asserts `br` has storage capacity >= 2. | |
| 159 | fn readDerInt(out: []u8, br: *std.io.BufferedReader) EncodingError!void { | |
| 160 | const buf = br.take(2) catch return error.InvalidEncoding; | |
| 158 | // Asserts `r` has storage capacity >= 2. | |
| 159 | fn readDerInt(out: []u8, r: *std.io.Reader) EncodingError!void { | |
| 160 | const buf = r.take(2) catch return error.InvalidEncoding; | |
| 161 | 161 | if (buf[0] != 0x02) return error.InvalidEncoding; |
| 162 | 162 | var expected_len: usize = buf[1]; |
| 163 | 163 | if (expected_len == 0 or expected_len > 1 + out.len) return error.InvalidEncoding; |
| 164 | 164 | var has_top_bit = false; |
| 165 | 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 | 167 | expected_len -= 1; |
| 168 | 168 | has_top_bit = true; |
| 169 | 169 | } |
| 170 | 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 | 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 | 176 | /// Returns InvalidEncoding if the DER encoding is invalid. |
| 177 | 177 | pub fn fromDer(der: []const u8) EncodingError!Signature { |
| 178 | 178 | if (der.len < 2) return error.InvalidEncoding; |
| 179 | var br: std.io.BufferedReader = undefined; | |
| 180 | br.initFixed(@constCast(der)); | |
| 181 | const buf = br.take(2) catch return error.InvalidEncoding; | |
| 179 | var r: std.io.Reader = .fixed(der); | |
| 180 | const buf = r.take(2) catch return error.InvalidEncoding; | |
| 182 | 181 | if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) return error.InvalidEncoding; |
| 183 | 182 | var sig: Signature = mem.zeroInit(Signature, .{}); |
| 184 | try readDerInt(&sig.r, &br); | |
| 185 | try readDerInt(&sig.s, &br); | |
| 186 | if (br.seek != der.len) return error.InvalidEncoding; | |
| 183 | try readDerInt(&sig.r, &r); | |
| 184 | try readDerInt(&sig.s, &r); | |
| 185 | if (r.seek != der.len) return error.InvalidEncoding; | |
| 187 | 186 | return sig; |
| 188 | 187 | } |
| 189 | 188 | }; |
lib/std/crypto/tls.zig+2-2| ... | ... | @@ -655,7 +655,7 @@ pub const Decoder = struct { |
| 655 | 655 | } |
| 656 | 656 | |
| 657 | 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 | 659 | assert(!d.disable_reads); |
| 660 | 660 | const existing_amt = d.cap - d.idx; |
| 661 | 661 | d.their_end = d.idx + their_amt; |
| ... | ... | @@ -672,7 +672,7 @@ pub const Decoder = struct { |
| 672 | 672 | |
| 673 | 673 | /// Same as `readAtLeast` but also increases `our_end` by exactly `our_amt`. |
| 674 | 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 | 676 | assert(!d.disable_reads); |
| 677 | 677 | try readAtLeast(d, stream, our_amt); |
| 678 | 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 | 21 | /// here via `reader`. |
| 22 | 22 | /// |
| 23 | 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 | 26 | /// The encrypted stream from the client to the server. Bytes are pushed here |
| 27 | 27 | /// via `writer`. |
| ... | ... | @@ -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 | 89 | /// at least this amount. |
| 90 | 90 | pub const min_buffer_len = tls.max_ciphertext_record_len; |
| 91 | 91 | |
| ... | ... | @@ -175,7 +175,7 @@ const InitError = error{ |
| 175 | 175 | /// `input` is asserted to have buffer capacity at least `min_buffer_len`. |
| 176 | 176 | pub fn init( |
| 177 | 177 | client: *Client, |
| 178 | input: *std.io.BufferedReader, | |
| 178 | input: *std.io.Reader, | |
| 179 | 179 | output: *std.io.BufferedWriter, |
| 180 | 180 | options: Options, |
| 181 | 181 | ) InitError!void { |
lib/std/debug/Dwarf.zig+1-2| ... | ... | @@ -2235,8 +2235,7 @@ pub const ElfModule = struct { |
| 2235 | 2235 | |
| 2236 | 2236 | const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); |
| 2237 | 2237 | sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: { |
| 2238 | var section_reader: std.io.BufferedReader = undefined; | |
| 2239 | section_reader.initFixed(@constCast(section_bytes)); | |
| 2238 | var section_reader: std.io.Reader = .fixed(section_bytes); | |
| 2240 | 2239 | const chdr = section_reader.takeStruct(elf.Chdr) catch continue; |
| 2241 | 2240 | if (chdr.ch_type != .ZLIB) continue; |
| 2242 | 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 | 136 | }, |
| 137 | 137 | |
| 138 | 138 | pub fn read( |
| 139 | reader: *std.io.BufferedReader, | |
| 139 | reader: *std.io.Reader, | |
| 140 | 140 | addr_size_bytes: u8, |
| 141 | 141 | endian: std.builtin.Endian, |
| 142 | 142 | ) !Instruction { |
lib/std/debug/Dwarf/expression.zig+1-2| ... | ... | @@ -774,8 +774,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 774 | 774 | } |
| 775 | 775 | |
| 776 | 776 | fn nextLeb128(expression: []const u8, i: *usize, comptime I: type) !I { |
| 777 | var br: std.io.BufferedReader = undefined; | |
| 778 | br.initFixed(@constCast(expression)); | |
| 777 | var br: std.io.Reader = .fixed(expression); | |
| 779 | 778 | br.seek = i.*; |
| 780 | 779 | assert(br.seek <= br.end); |
| 781 | 780 | const result = br.takeLeb128(I) catch |err| switch (err) { |
lib/std/debug/FixedBufferReader.zig+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 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 | 5 | const std = @import("../std.zig"); |
| 6 | 6 | const MemoryAccessor = std.debug.MemoryAccessor; |
| ... | ... | @@ -52,7 +52,7 @@ pub fn readIntChecked( |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 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 | 56 | br.initFixed(@constCast(fbr.buf)); |
| 57 | 57 | br.seek = fbr.pos; |
| 58 | 58 | const result = br.takeLeb128(T); |
lib/std/debug/SelfInfo.zig+4-3| ... | ... | @@ -2025,9 +2025,10 @@ pub const VirtualMachine = struct { |
| 2025 | 2025 | assert(self.cie_row == null); |
| 2026 | 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; | |
| 2029 | readers[0].initFixed(@constCast(cie.initial_instructions)); | |
| 2030 | readers[1].initFixed(@constCast(fde.instructions)); | |
| 2028 | var readers: [2]std.io.Reader = .{ | |
| 2029 | .fixed(cie.initial_instructions), | |
| 2030 | .fixed(fde.instructions), | |
| 2031 | }; | |
| 2031 | 2032 | |
| 2032 | 2033 | var prev_row: Row = self.current_row; |
| 2033 | 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 | 510 | |
| 511 | 511 | pub const ReadError = std.io.Reader.Error || ParseError; |
| 512 | 512 | |
| 513 | pub fn read(br: *std.io.BufferedReader) ReadError!Header { | |
| 514 | const buf = try br.peek(@sizeOf(Elf64_Ehdr)); | |
| 513 | pub fn read(r: *std.io.Reader) ReadError!Header { | |
| 514 | const buf = try r.peek(@sizeOf(Elf64_Ehdr)); | |
| 515 | 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 | 517 | return result; |
| 518 | 518 | } |
| 519 | 519 |
lib/std/fs/File.zig+18-11| ... | ... | @@ -904,6 +904,7 @@ pub const Reader = struct { |
| 904 | 904 | size: ?u64 = null, |
| 905 | 905 | size_err: ?GetEndPosError = null, |
| 906 | 906 | seek_err: ?Reader.SeekError = null, |
| 907 | interface: std.io.Reader, | |
| 907 | 908 | |
| 908 | 909 | pub const SeekError = File.SeekError || error{ |
| 909 | 910 | /// Seeking fell back to reading, and reached the end before the requested seek position. |
| ... | ... | @@ -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 | 945 | return .{ |
| 945 | .context = r, | |
| 946 | .context = undefined, | |
| 946 | 947 | .vtable = &.{ |
| 947 | .read = Reader.stream, | |
| 948 | .stream = Reader.stream, | |
| 948 | 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 { | |
| 954 | return interface(r).buffered(buffer); | |
| 957 | pub fn init(file: File, buffer: []u8) Reader { | |
| 958 | return .{ | |
| 959 | .file = file, | |
| 960 | .interface = initInterface(buffer), | |
| 961 | }; | |
| 955 | 962 | } |
| 956 | 963 | |
| 957 | 964 | pub fn getSize(r: *Reader) GetEndPosError!u64 { |
| ... | ... | @@ -1021,11 +1028,11 @@ pub const Reader = struct { |
| 1021 | 1028 | const max_buffers_len = 16; |
| 1022 | 1029 | |
| 1023 | 1030 | fn stream( |
| 1024 | context: ?*anyopaque, | |
| 1031 | io_reader: *std.io.Reader, | |
| 1025 | 1032 | bw: *BufferedWriter, |
| 1026 | 1033 | limit: std.io.Limit, |
| 1027 | 1034 | ) std.io.Reader.StreamError!usize { |
| 1028 | const r: *Reader = @ptrCast(@alignCast(context)); | |
| 1035 | const r: *Reader = @fieldParentPtr("interface", io_reader); | |
| 1029 | 1036 | switch (r.mode) { |
| 1030 | 1037 | .positional, .streaming => return bw.writeFile(r, limit, &.{}, 0) catch |write_err| switch (write_err) { |
| 1031 | 1038 | error.ReadFailed => return error.ReadFailed, |
| ... | ... | @@ -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 { | |
| 1055 | const r: *Reader = @ptrCast(@alignCast(context)); | |
| 1061 | fn discard(io_reader: *std.io.Reader, limit: std.io.Limit) std.io.Reader.Error!usize { | |
| 1062 | const r: *Reader = @fieldParentPtr("interface", io_reader); | |
| 1056 | 1063 | const file = r.file; |
| 1057 | 1064 | const pos = r.pos; |
| 1058 | 1065 | switch (r.mode) { |
| ... | ... | @@ -1357,8 +1364,8 @@ pub const Writer = struct { |
| 1357 | 1364 | /// |
| 1358 | 1365 | /// Positional is more threadsafe, since the global seek position is not |
| 1359 | 1366 | /// affected. |
| 1360 | pub fn reader(file: File) Reader { | |
| 1361 | return .{ .file = file }; | |
| 1367 | pub fn reader(file: File, buffer: []u8) Reader { | |
| 1368 | return .init(file, buffer); | |
| 1362 | 1369 | } |
| 1363 | 1370 | |
| 1364 | 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 | 325 | }; |
| 326 | 326 | |
| 327 | 327 | pub const Reader = struct { |
| 328 | in: *std.io.BufferedReader, | |
| 328 | in: *std.io.Reader, | |
| 329 | 329 | /// Keeps track of whether the stream is ready to accept a new request, |
| 330 | 330 | /// making invalid API usage cause assertion failures rather than HTTP |
| 331 | 331 | /// protocol violations. |
| ... | ... | @@ -703,7 +703,7 @@ pub const Reader = struct { |
| 703 | 703 | |
| 704 | 704 | pub const Decompressor = struct { |
| 705 | 705 | compression: Compression, |
| 706 | buffered_reader: std.io.BufferedReader, | |
| 706 | buffered_reader: std.io.Reader, | |
| 707 | 707 | |
| 708 | 708 | pub const Compression = union(enum) { |
| 709 | 709 | deflate: std.compress.flate.Decompressor, |
lib/std/http/Client.zig+2-2| ... | ... | @@ -232,7 +232,7 @@ pub const Connection = struct { |
| 232 | 232 | writer: std.io.BufferedWriter, |
| 233 | 233 | /// HTTP protocol from server to client. |
| 234 | 234 | /// This either comes directly from `stream_reader`, or from a TLS client. |
| 235 | reader: std.io.BufferedReader, | |
| 235 | reader: std.io.Reader, | |
| 236 | 236 | /// Entry in `ConnectionPool.used` or `ConnectionPool.free`. |
| 237 | 237 | pool_node: std.DoublyLinkedList.Node, |
| 238 | 238 | port: u16, |
| ... | ... | @@ -299,7 +299,7 @@ pub const Connection = struct { |
| 299 | 299 | /// Data from `client` to `Connection.stream`. |
| 300 | 300 | writer: std.io.BufferedWriter, |
| 301 | 301 | /// Data from `Connection.stream` to `client`. |
| 302 | reader: std.io.BufferedReader, | |
| 302 | reader: std.io.Reader, | |
| 303 | 303 | client: std.crypto.tls.Client, |
| 304 | 304 | connection: Connection, |
| 305 | 305 |
lib/std/http/Server.zig+2-2| ... | ... | @@ -20,7 +20,7 @@ reader: http.Reader, |
| 20 | 20 | /// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`. |
| 21 | 21 | /// |
| 22 | 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 | 24 | return .{ |
| 25 | 25 | .reader = .{ |
| 26 | 26 | .in = in, |
| ... | ... | @@ -610,7 +610,7 @@ pub const Request = struct { |
| 610 | 610 | /// See https://tools.ietf.org/html/rfc6455 |
| 611 | 611 | pub const WebSocket = struct { |
| 612 | 612 | key: []const u8, |
| 613 | input: *std.io.BufferedReader, | |
| 613 | input: *std.io.Reader, | |
| 614 | 614 | output: *std.io.BufferedWriter, |
| 615 | 615 | |
| 616 | 616 | pub const Header0 = packed struct(u8) { |
lib/std/io.zig+11-15| ... | ... | @@ -72,8 +72,6 @@ pub const Limit = enum(usize) { |
| 72 | 72 | pub const Reader = @import("io/Reader.zig"); |
| 73 | 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 | 75 | pub const AllocatingWriter = @import("io/AllocatingWriter.zig"); |
| 78 | 76 | |
| 79 | 77 | pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream; |
| ... | ... | @@ -131,7 +129,7 @@ pub fn Poller(comptime StreamEnum: type) type { |
| 131 | 129 | const PollFd = if (is_windows) void else posix.pollfd; |
| 132 | 130 | |
| 133 | 131 | gpa: Allocator, |
| 134 | readers: [enum_fields.len]BufferedReader, | |
| 132 | readers: [enum_fields.len]Reader, | |
| 135 | 133 | poll_fds: [enum_fields.len]PollFd, |
| 136 | 134 | windows: if (is_windows) struct { |
| 137 | 135 | first_read_done: bool, |
| ... | ... | @@ -163,7 +161,7 @@ pub fn Poller(comptime StreamEnum: type) type { |
| 163 | 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 | 165 | self.* = undefined; |
| 168 | 166 | } |
| 169 | 167 | |
| ... | ... | @@ -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 | 185 | return &self.readers[@intFromEnum(which)]; |
| 188 | 186 | } |
| 189 | 187 | |
| ... | ... | @@ -295,18 +293,18 @@ pub fn Poller(comptime StreamEnum: type) type { |
| 295 | 293 | } |
| 296 | 294 | |
| 297 | 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 | 297 | // Try reading whatever is available before checking the error |
| 300 | 298 | // conditions. |
| 301 | 299 | // It's still possible to read after a POLL.HUP is received, |
| 302 | 300 | // always check if there's some data waiting to be read first. |
| 303 | 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 | 303 | const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) { |
| 306 | 304 | error.BrokenPipe => 0, // Handle the same as EOF. |
| 307 | 305 | else => |e| return e, |
| 308 | 306 | }; |
| 309 | br.advanceBufferEnd(amt); | |
| 307 | r.advanceBufferEnd(amt); | |
| 310 | 308 | if (amt == 0) { |
| 311 | 309 | // Remove the fd when the EOF condition is met. |
| 312 | 310 | poll_fd.fd = -1; |
| ... | ... | @@ -337,14 +335,14 @@ var win_dummy_bytes_read: u32 = undefined; |
| 337 | 335 | fn windowsAsyncReadToFifoAndQueueSmallRead( |
| 338 | 336 | handle: windows.HANDLE, |
| 339 | 337 | overlapped: *windows.OVERLAPPED, |
| 340 | br: *BufferedReader, | |
| 338 | r: *Reader, | |
| 341 | 339 | small_buf: *[128]u8, |
| 342 | 340 | bump_amt: usize, |
| 343 | 341 | ) !enum { empty, populated, closed_populated, closed } { |
| 344 | 342 | var read_any_data = false; |
| 345 | 343 | while (true) { |
| 346 | 344 | const fifo_read_pending = while (true) { |
| 347 | const buf = try br.writableWithSize(bump_amt); | |
| 345 | const buf = try r.writableWithSize(bump_amt); | |
| 348 | 346 | const buf_len = math.cast(u32, buf.len) orelse math.maxInt(u32); |
| 349 | 347 | |
| 350 | 348 | if (0 == windows.kernel32.ReadFile( |
| ... | ... | @@ -366,7 +364,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead( |
| 366 | 364 | }; |
| 367 | 365 | |
| 368 | 366 | read_any_data = true; |
| 369 | br.update(num_bytes_read); | |
| 367 | r.update(num_bytes_read); | |
| 370 | 368 | |
| 371 | 369 | if (num_bytes_read == buf_len) { |
| 372 | 370 | // We filled the buffer, so there's probably more data available. |
| ... | ... | @@ -396,7 +394,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead( |
| 396 | 394 | .aborted => break :cancel_read, |
| 397 | 395 | }; |
| 398 | 396 | read_any_data = true; |
| 399 | br.update(num_bytes_read); | |
| 397 | r.update(num_bytes_read); | |
| 400 | 398 | } |
| 401 | 399 | |
| 402 | 400 | // Try to queue the 1-byte read. |
| ... | ... | @@ -421,7 +419,7 @@ fn windowsAsyncReadToFifoAndQueueSmallRead( |
| 421 | 419 | .closed => return if (read_any_data) .closed_populated else .closed, |
| 422 | 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 | 423 | read_any_data = true; |
| 426 | 424 | } |
| 427 | 425 | } |
| ... | ... | @@ -488,8 +486,6 @@ pub fn PollFiles(comptime StreamEnum: type) type { |
| 488 | 486 | |
| 489 | 487 | test { |
| 490 | 488 | _ = AllocatingWriter; |
| 491 | _ = BufferedReader; | |
| 492 | _ = BufferedWriter; | |
| 493 | 489 | _ = Reader; |
| 494 | 490 | _ = Writer; |
| 495 | 491 | _ = @import("io/test.zig"); |
lib/std/io/AllocatingWriter.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | //! `std.io.BufferedWriter` state such that it writes to the unused capacity of |
| 7 | 7 | //! an array list, filling it up completely before making a call through the |
| 8 | 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 | 10 | //! takes the hot paths when using this API. |
| 11 | 11 | |
| 12 | 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 | const std = @import("../std.zig"); | |
| 2 | 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 | 8 | const assert = std.debug.assert; |
| 4 | const BufferedWriter = std.io.BufferedWriter; | |
| 5 | const BufferedReader = std.io.BufferedReader; | |
| 9 | const testing = std.testing; | |
| 6 | 10 | const Allocator = std.mem.Allocator; |
| 7 | 11 | const ArrayList = std.ArrayListUnmanaged; |
| 8 | 12 | const Limit = std.io.Limit; |
| ... | ... | @@ -11,9 +15,14 @@ pub const Limited = @import("Reader/Limited.zig"); |
| 11 | 15 | |
| 12 | 16 | context: ?*anyopaque, |
| 13 | 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 | 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 | 27 | /// Returns the number of bytes written, which will be at minimum `0` and |
| 19 | 28 | /// at most `limit`. The number returned, including zero, does not indicate |
| ... | ... | @@ -26,7 +35,7 @@ pub const VTable = struct { |
| 26 | 35 | /// Implementations are encouraged to utilize mandatory minimum buffer |
| 27 | 36 | /// sizes combined with short reads (returning a value less than `limit`) |
| 28 | 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 | 40 | /// Consumes bytes from the internally tracked stream position without |
| 32 | 41 | /// providing access to them. |
| ... | ... | @@ -42,11 +51,10 @@ pub const VTable = struct { |
| 42 | 51 | /// sizes combined with short reads (returning a value less than `limit`) |
| 43 | 52 | /// in order to minimize complexity. |
| 44 | 53 | /// |
| 45 | /// If an implementation sets this to `null`, a default implementation is | |
| 46 | /// provided which is based on calling `read`, borrowing | |
| 47 | /// `BufferedReader.buffer` to construct a temporary `BufferedWriter` and | |
| 48 | /// ignoring the written data. | |
| 49 | discard: ?*const fn (context: ?*anyopaque, limit: Limit) Error!usize = null, | |
| 54 | /// The default implementation is is based on calling `read`, borrowing | |
| 55 | /// `buffer` to construct a temporary `Writer` and ignoring the written | |
| 56 | /// data. | |
| 57 | discard: *const fn (r: *Reader, limit: Limit) Error!usize = defaultDiscard, | |
| 50 | 58 | }; |
| 51 | 59 | |
| 52 | 60 | pub const StreamError = error{ |
| ... | ... | @@ -77,26 +85,97 @@ pub const ShortError = error{ |
| 77 | 85 | ReadFailed, |
| 78 | 86 | }; |
| 79 | 87 | |
| 80 | pub fn read(r: Reader, bw: *BufferedWriter, limit: Limit) StreamError!usize { | |
| 81 | const before = bw.count; | |
| 82 | const n = try r.vtable.read(r.context, bw, limit); | |
| 88 | pub const failing: Reader = .{ | |
| 89 | .context = undefined, | |
| 90 | .vtable = &.{ | |
| 91 | .read = failingRead, | |
| 92 | .discard = failingDiscard, | |
| 93 | }, | |
| 94 | .buffer = &.{}, | |
| 95 | .seek = 0, | |
| 96 | .end = 0, | |
| 97 | }; | |
| 98 | ||
| 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 | 131 | assert(n <= @intFromEnum(limit)); |
| 84 | assert(bw.count == before + n); | |
| 132 | assert(w.count == before + n); | |
| 85 | 133 | return n; |
| 86 | 134 | } |
| 87 | 135 | |
| 88 | pub fn discard(r: Reader, limit: Limit) Error!usize { | |
| 89 | const n = try r.vtable.discard(r.context, limit); | |
| 90 | assert(n <= @intFromEnum(limit)); | |
| 136 | pub fn discard(r: *Reader, limit: Limit) Error!usize { | |
| 137 | const buffered_len = r.end - r.seek; | |
| 138 | const remaining: Limit = if (limit.toInt()) |n| l: { | |
| 139 | if (buffered_len >= n) { | |
| 140 | r.seek += n; | |
| 141 | return n; | |
| 142 | } | |
| 143 | break :l .limited(n - buffered_len); | |
| 144 | } else .unlimited; | |
| 145 | r.seek = 0; | |
| 146 | r.end = 0; | |
| 147 | const n = r.vtable.discard(r, remaining); | |
| 148 | assert(n <= @intFromEnum(remaining)); | |
| 149 | return buffered_len + n; | |
| 150 | } | |
| 151 | ||
| 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 | 168 | return n; |
| 92 | 169 | } |
| 93 | 170 | |
| 94 | /// Returns total number of bytes written to `bw`. | |
| 95 | pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize { | |
| 96 | const readFn = r.vtable.read; | |
| 171 | /// "Pump" data from the reader to the writer, handling `error.EndOfStream` as | |
| 172 | /// a success case. | |
| 173 | /// | |
| 174 | /// Returns total number of bytes written to `w`. | |
| 175 | pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize { | |
| 97 | 176 | var offset: usize = 0; |
| 98 | 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 | 179 | error.EndOfStream => return offset, |
| 101 | 180 | else => |e| return e, |
| 102 | 181 | }; |
| ... | ... | @@ -105,11 +184,12 @@ pub fn readRemaining(r: Reader, bw: *BufferedWriter) StreamRemainingError!usize |
| 105 | 184 | |
| 106 | 185 | /// Consumes the stream until the end, ignoring all the data, returning the |
| 107 | 186 | /// number of bytes discarded. |
| 108 | pub fn discardRemaining(r: Reader) ShortError!usize { | |
| 109 | const discardFn = r.vtable.discard; | |
| 110 | var offset: usize = 0; | |
| 187 | pub fn discardRemaining(r: *Reader) ShortError!usize { | |
| 188 | var offset: usize = r.end; | |
| 189 | r.seek = 0; | |
| 190 | r.end = 0; | |
| 111 | 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 | 193 | error.EndOfStream => return offset, |
| 114 | 194 | else => |e| return e, |
| 115 | 195 | }; |
| ... | ... | @@ -121,112 +201,1133 @@ pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLo |
| 121 | 201 | /// Transfers all bytes from the current position to the end of the stream, up |
| 122 | 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 | |
| 125 | /// stream is advanced one byte beyond the limit, and the consumed data is | |
| 126 | /// unrecoverable. Other functions listed below do not have this caveat. | |
| 204 | /// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In | |
| 205 | /// such case, the next byte that would be read will be the first one to exceed | |
| 206 | /// `limit`, and all preceeding bytes have been discarded. | |
| 207 | /// | |
| 208 | /// Asserts `buffer` has nonzero capacity. | |
| 127 | 209 | /// |
| 128 | 210 | /// See also: |
| 129 | /// * `readRemainingArrayList` | |
| 130 | /// * `BufferedReader.readRemainingArrayList` | |
| 131 | pub fn readRemainingAlloc(r: Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 { | |
| 211 | /// * `appendRemaining` | |
| 212 | pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 { | |
| 132 | 213 | var buffer: ArrayList(u8) = .empty; |
| 133 | 214 | defer buffer.deinit(gpa); |
| 134 | try readRemainingArrayList(r, gpa, null, &buffer, limit, 1); | |
| 215 | try appendRemaining(r, gpa, null, &buffer, limit, 1); | |
| 135 | 216 | return buffer.toOwnedSlice(gpa); |
| 136 | 217 | } |
| 137 | 218 | |
| 138 | 219 | /// Transfers all bytes from the current position to the end of the stream, up |
| 139 | 220 | /// to `limit`, appending them to `list`. |
| 140 | 221 | /// |
| 141 | /// If `limit` is exceeded: | |
| 142 | /// * The array list's length is increased by exactly one byte past `limit`. | |
| 143 | /// * The stream seek position is advanced by exactly one byte past `limit`. | |
| 144 | /// * `error.StreamTooLong` is returned. | |
| 222 | /// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In | |
| 223 | /// such case, the next byte that would be read will be the first one to exceed | |
| 224 | /// `limit`, and all preceeding bytes have been appended to `list`. | |
| 145 | 225 | /// |
| 146 | /// The other function listed below has different semantics for an exceeded | |
| 147 | /// limit. | |
| 226 | /// Asserts `buffer` has nonzero capacity. | |
| 148 | 227 | /// |
| 149 | 228 | /// See also: |
| 150 | /// * `BufferedReader.readRemainingArrayList` | |
| 151 | pub fn readRemainingArrayList( | |
| 152 | r: Reader, | |
| 229 | /// * `allocRemaining` | |
| 230 | pub fn appendRemaining( | |
| 231 | r: *Reader, | |
| 153 | 232 | gpa: Allocator, |
| 154 | 233 | comptime alignment: ?std.mem.Alignment, |
| 155 | 234 | list: *std.ArrayListAlignedUnmanaged(u8, alignment), |
| 156 | 235 | limit: Limit, |
| 157 | minimum_buffer_size: usize, | |
| 158 | 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 | 249 | while (true) { |
| 161 | try list.ensureUnusedCapacity(gpa, minimum_buffer_size); | |
| 162 | const buffer = remaining.slice1(list.unusedCapacitySlice()); | |
| 163 | const n = r.vtable.readVec(r.context, &.{buffer}) catch |err| switch (err) { | |
| 164 | error.EndOfStream => return, | |
| 250 | try list.ensureUnusedCapacity(gpa, 1); | |
| 251 | const dest = remaining.slice(list.unusedCapacitySlice()); | |
| 252 | const additional_buffer = if (@intFromEnum(remaining) == dest.len) buffer else &.{}; | |
| 253 | const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) { | |
| 254 | error.EndOfStream => break, | |
| 165 | 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 | 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 = .{ | |
| 173 | .context = undefined, | |
| 174 | .vtable = &.{ | |
| 175 | .read = failingRead, | |
| 176 | .discard = failingDiscard, | |
| 177 | }, | |
| 268 | /// Writes bytes from the internally tracked stream position to `data`. | |
| 269 | /// | |
| 270 | /// Returns the number of bytes written, which will be at minimum `0` and | |
| 271 | /// at most the sum of each data slice length. The number of bytes read, | |
| 272 | /// including zero, does not indicate end of stream. | |
| 273 | /// | |
| 274 | /// The reader's internal logical seek position moves forward in accordance | |
| 275 | /// with the number of bytes returned from this function. | |
| 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 = .{ | |
| 181 | .context = undefined, | |
| 182 | .vtable = &.{ | |
| 183 | .read = endingRead, | |
| 184 | .discard = endingDiscard, | |
| 185 | }, | |
| 645 | /// Returns a slice of the next bytes of buffered data from the stream until | |
| 646 | /// `sentinel` is found, advancing the seek position. | |
| 647 | /// | |
| 648 | /// Returned slice has a sentinel. | |
| 649 | /// | |
| 650 | /// Invalidates previously returned values from `peek`. | |
| 651 | /// | |
| 652 | /// See also: | |
| 653 | /// * `peekSentinel` | |
| 654 | /// * `takeDelimiterExclusive` | |
| 655 | /// * `takeDelimiterInclusive` | |
| 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 { | |
| 189 | return buffered(r, &.{}); | |
| 815 | /// Appends to `bw` contents by reading from the stream until `delimiter` is found. | |
| 816 | /// Does not write the delimiter itself. | |
| 817 | /// | |
| 818 | /// Returns number of bytes streamed. | |
| 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 { | |
| 193 | return .{ | |
| 194 | .unbuffered_reader = r, | |
| 195 | .seek = 0, | |
| 196 | .buffer = buffer, | |
| 197 | .end = 0, | |
| 833 | fn readAny( | |
| 834 | r: *Reader, | |
| 835 | bw: *Writer, | |
| 836 | delimiter: ?u8, | |
| 837 | limit: Limit, | |
| 838 | ) StreamRemainingError!struct { usize, enum { delimiter, limit, end } } { | |
| 839 | var amount: usize = 0; | |
| 840 | var remaining = limit; | |
| 841 | while (remaining.nonzero()) { | |
| 842 | const available = remaining.slice(r.peekGreedy(1) catch |err| switch (err) { | |
| 843 | error.ReadFailed => |e| return e, | |
| 844 | error.EndOfStream => return .{ amount, .end }, | |
| 845 | }); | |
| 846 | if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| { | |
| 847 | try bw.writeAll(available[0..delimiter_index]); | |
| 848 | r.toss(delimiter_index + 1); | |
| 849 | return .{ amount + delimiter_index, .delimiter }; | |
| 850 | }; | |
| 851 | try bw.writeAll(available); | |
| 852 | r.toss(available.len); | |
| 853 | amount += available.len; | |
| 854 | remaining = remaining.subtract(available.len).?; | |
| 855 | } | |
| 856 | return .{ amount, .limit }; | |
| 857 | } | |
| 858 | ||
| 859 | /// Reads from the stream until specified byte is found, discarding all data, | |
| 860 | /// including the delimiter. | |
| 861 | /// | |
| 862 | /// If end of stream is found, this function succeeds. | |
| 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 { | |
| 202 | return .{ | |
| 203 | .unlimited_reader = r, | |
| 204 | .remaining = limit, | |
| 1019 | pub const TakeLeb128Error = Error || error{Overflow}; | |
| 1020 | ||
| 1021 | /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. | |
| 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 { | |
| 209 | _ = context; | |
| 210 | _ = bw; | |
| 1118 | /// Ensures `capacity` more data can be buffered without rebasing, by rebasing | |
| 1119 | /// if necessary. | |
| 1120 | /// | |
| 1121 | /// Asserts `capacity` is within the buffer capacity. | |
| 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 | 1312 | _ = limit; |
| 212 | 1313 | return error.EndOfStream; |
| 213 | 1314 | } |
| 214 | 1315 | |
| 215 | fn endingDiscard(context: ?*anyopaque, limit: Limit) Error!usize { | |
| 216 | _ = context; | |
| 1316 | fn endingDiscard(r: *Reader, limit: Limit) Error!usize { | |
| 1317 | _ = r; | |
| 217 | 1318 | _ = limit; |
| 218 | 1319 | return error.EndOfStream; |
| 219 | 1320 | } |
| 220 | 1321 | |
| 221 | fn failingRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) StreamError!usize { | |
| 222 | _ = context; | |
| 223 | _ = bw; | |
| 1322 | fn failingRead(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | |
| 1323 | _ = r; | |
| 1324 | _ = w; | |
| 224 | 1325 | _ = limit; |
| 225 | 1326 | return error.ReadFailed; |
| 226 | 1327 | } |
| 227 | 1328 | |
| 228 | fn failingDiscard(context: ?*anyopaque, limit: Limit) Error!usize { | |
| 229 | _ = context; | |
| 1329 | fn failingDiscard(r: *Reader, limit: Limit) Error!usize { | |
| 1330 | _ = r; | |
| 230 | 1331 | _ = limit; |
| 231 | 1332 | return error.ReadFailed; |
| 232 | 1333 | } |
| ... | ... | @@ -270,46 +1371,31 @@ test "readAlloc when the backing reader provides one byte at a time" { |
| 270 | 1371 | /// implementation details. |
| 271 | 1372 | pub fn Hashed(comptime Hasher: type) type { |
| 272 | 1373 | return struct { |
| 273 | in: *BufferedReader, | |
| 1374 | in: *Reader, | |
| 274 | 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 | 1379 | return .{ |
| 278 | .unbuffered_reader = .{ | |
| 279 | .context = this, | |
| 1380 | .in = in, | |
| 1381 | .hasher = hasher, | |
| 1382 | .interface = .{ | |
| 280 | 1383 | .vtable = &.{ |
| 281 | 1384 | .read = @This().read, |
| 282 | 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 { | |
| 311 | const this: *@This() = @alignCast(@ptrCast(context)); | |
| 1394 | fn read(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | |
| 1395 | const this: *@This() = @alignCast(@fieldParentPtr("interface", r)); | |
| 1396 | const data = w.writableVector(limit); | |
| 312 | 1397 | const n = try this.in.readVec(data); |
| 1398 | w.advanceVector(n); | |
| 313 | 1399 | var remaining: usize = n; |
| 314 | 1400 | for (data) |slice| { |
| 315 | 1401 | if (remaining < slice.len) { |
| ... | ... | @@ -323,5 +1409,15 @@ pub fn Hashed(comptime Hasher: type) type { |
| 323 | 1409 | assert(remaining == 0); |
| 324 | 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 | 5 | const BufferedWriter = std.io.BufferedWriter; |
| 6 | 6 | const Limit = std.io.Limit; |
| 7 | 7 | |
| 8 | unlimited_reader: Reader, | |
| 8 | unlimited: *Reader, | |
| 9 | 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 | 13 | return .{ |
| 13 | .context = l, | |
| 14 | .vtable = &.{ | |
| 15 | .read = passthruRead, | |
| 16 | .readVec = passthruReadVec, | |
| 17 | .discard = passthruDiscard, | |
| 14 | .unlimited = reader, | |
| 15 | .remaining = limit, | |
| 16 | .interface = .{ | |
| 17 | .vtable = &.{ | |
| 18 | .stream = stream, | |
| 19 | .discard = discard, | |
| 20 | }, | |
| 21 | .buffer = buffer, | |
| 22 | .seek = 0, | |
| 23 | .end = 0, | |
| 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 | 29 | const l: *Limited = @alignCast(@ptrCast(context)); |
| 24 | 30 | const combined_limit = limit.min(l.remaining); |
| 25 | 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 | 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 | 37 | const l: *Limited = @alignCast(@ptrCast(context)); |
| 32 | 38 | const combined_limit = limit.min(l.remaining); |
| 33 | 39 | const n = try l.unlimited_reader.discard(combined_limit); |
| 34 | 40 | l.remaining = l.remaining.subtract(n).?; |
| 35 | 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 | 114 | } |
| 115 | 115 | |
| 116 | 116 | fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T { |
| 117 | var br: std.io.BufferedReader = undefined; | |
| 118 | br.initFixed(encoded); | |
| 117 | var br: std.io.Reader = .fixed(encoded); | |
| 119 | 118 | return br.takeIleb128(T); |
| 120 | 119 | } |
| 121 | 120 | |
| 122 | 121 | fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T { |
| 123 | var br: std.io.BufferedReader = undefined; | |
| 124 | br.initFixed(encoded); | |
| 122 | var br: std.io.Reader = .fixed(encoded); | |
| 125 | 123 | return br.takeUleb128(T); |
| 126 | 124 | } |
| 127 | 125 | |
| 128 | 126 | fn test_read_ileb128(comptime T: type, encoded: []const u8) !T { |
| 129 | var br: std.io.BufferedReader = undefined; | |
| 130 | br.initFixed(encoded); | |
| 127 | var br: std.io.Reader = .fixed(encoded); | |
| 131 | 128 | return br.readIleb128(T); |
| 132 | 129 | } |
| 133 | 130 | |
| 134 | 131 | fn test_read_uleb128(comptime T: type, encoded: []const u8) !T { |
| 135 | var br: std.io.BufferedReader = undefined; | |
| 136 | br.initFixed(encoded); | |
| 132 | var br: std.io.Reader = .fixed(encoded); | |
| 137 | 133 | return br.readUleb128(T); |
| 138 | 134 | } |
| 139 | 135 | |
| 140 | 136 | fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void { |
| 141 | var br: std.io.BufferedReader = undefined; | |
| 142 | br.initFixed(encoded); | |
| 137 | var br: std.io.Reader = .fixed(encoded); | |
| 143 | 138 | var i: usize = 0; |
| 144 | 139 | while (i < N) : (i += 1) { |
| 145 | 140 | _ = try br.readIleb128(T); |
| ... | ... | @@ -147,8 +142,7 @@ fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u |
| 147 | 142 | } |
| 148 | 143 | |
| 149 | 144 | fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) !void { |
| 150 | var br: std.io.BufferedReader = undefined; | |
| 151 | br.initFixed(encoded); | |
| 145 | var br: std.io.Reader = .fixed(encoded); | |
| 152 | 146 | var i: usize = 0; |
| 153 | 147 | while (i < N) : (i += 1) { |
| 154 | 148 | _ = try br.readUleb128(T); |
| ... | ... | @@ -248,7 +242,7 @@ fn test_write_leb128(value: anytype) !void { |
| 248 | 242 | const t_signed = signedness == .signed; |
| 249 | 243 | |
| 250 | 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 | 247 | // decode to a larger bit size too, to ensure sign extension |
| 254 | 248 | // is working as expected |
| ... | ... | @@ -275,8 +269,7 @@ fn test_write_leb128(value: anytype) !void { |
| 275 | 269 | try testing.expect(bw.buffer.items.len == bytes_needed); |
| 276 | 270 | |
| 277 | 271 | // stream read |
| 278 | var br: std.io.BufferedReader = undefined; | |
| 279 | br.initFixed(&buf); | |
| 272 | var br: std.io.Reader = .fixed(&buf); | |
| 280 | 273 | const sr = try readStream(&br, T); |
| 281 | 274 | try testing.expect(br.seek == bytes_needed); |
| 282 | 275 | try testing.expect(sr == value); |
lib/std/net.zig+2-2| ... | ... | @@ -1378,7 +1378,7 @@ fn parseHosts( |
| 1378 | 1378 | name: []const u8, |
| 1379 | 1379 | family: posix.sa_family_t, |
| 1380 | 1380 | port: u16, |
| 1381 | br: *std.io.BufferedReader, | |
| 1381 | br: *std.io.Reader, | |
| 1382 | 1382 | ) error{ OutOfMemory, ReadFailed }!void { |
| 1383 | 1383 | while (true) { |
| 1384 | 1384 | const line = br.takeDelimiterExclusive('\n') catch |err| switch (err) { |
| ... | ... | @@ -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 | 1596 | const gpa = rc.gpa; |
| 1597 | 1597 | while (br.takeSentinel('\n')) |line_with_comment| { |
| 1598 | 1598 | const line = line: { |
lib/std/process/Child.zig+5-5| ... | ... | @@ -348,15 +348,15 @@ pub const RunResult = struct { |
| 348 | 348 | stderr: []u8, |
| 349 | 349 | }; |
| 350 | 350 | |
| 351 | fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), br: *std.io.BufferedReader) !void { | |
| 352 | assert(br.seek == 0); | |
| 351 | fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), r: *std.io.Reader) !void { | |
| 352 | assert(r.seek == 0); | |
| 353 | 353 | if (list.capacity == 0) { |
| 354 | 354 | list.* = .{ |
| 355 | .items = br.bufferContents(), | |
| 356 | .capacity = br.buffer.len, | |
| 355 | .items = r.bufferContents(), | |
| 356 | .capacity = r.buffer.len, | |
| 357 | 357 | }; |
| 358 | 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 | 302 | |
| 303 | 303 | /// Iterator over entries in the tar file represented by reader. |
| 304 | 304 | pub const Iterator = struct { |
| 305 | reader: *std.io.BufferedReader, | |
| 305 | reader: *std.io.Reader, | |
| 306 | 306 | diagnostics: ?*Diagnostics = null, |
| 307 | 307 | |
| 308 | 308 | // buffers for heeader and file attributes |
| ... | ... | @@ -328,7 +328,7 @@ pub const Iterator = struct { |
| 328 | 328 | |
| 329 | 329 | /// Iterates over files in tar archive. |
| 330 | 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 | 332 | return .{ |
| 333 | 333 | .reader = reader, |
| 334 | 334 | .diagnostics = options.diagnostics, |
| ... | ... | @@ -345,7 +345,7 @@ pub const Iterator = struct { |
| 345 | 345 | kind: FileKind = .file, |
| 346 | 346 | |
| 347 | 347 | unread_bytes: *u64, |
| 348 | parent_reader: *std.io.BufferedReader, | |
| 348 | parent_reader: *std.io.Reader, | |
| 349 | 349 | |
| 350 | 350 | pub fn reader(self: *File) std.io.Reader { |
| 351 | 351 | return .{ |
| ... | ... | @@ -537,14 +537,14 @@ const pax_max_size_attr_len = 64; |
| 537 | 537 | |
| 538 | 538 | pub const PaxIterator = struct { |
| 539 | 539 | size: usize, // cumulative size of all pax attributes |
| 540 | reader: *std.io.BufferedReader, | |
| 540 | reader: *std.io.Reader, | |
| 541 | 541 | |
| 542 | 542 | const Self = @This(); |
| 543 | 543 | |
| 544 | 544 | const Attribute = struct { |
| 545 | 545 | kind: PaxAttributeKind, |
| 546 | 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 | 549 | // Copies pax attribute value into destination buffer. |
| 550 | 550 | // Must be called with destination buffer of size at least Attribute.len. |
| ... | ... | @@ -611,13 +611,13 @@ pub const PaxIterator = struct { |
| 611 | 611 | } |
| 612 | 612 | |
| 613 | 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 | 615 | if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd; |
| 616 | 616 | } |
| 617 | 617 | }; |
| 618 | 618 | |
| 619 | 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 | 621 | var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 622 | 622 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 623 | 623 | var iter: Iterator = .init(reader, .{ |
| ... | ... | @@ -818,7 +818,7 @@ test PaxIterator { |
| 818 | 818 | var buffer: [1024]u8 = undefined; |
| 819 | 819 | |
| 820 | 820 | outer: for (cases) |case| { |
| 821 | var br: std.io.BufferedReader = undefined; | |
| 821 | var br: std.io.Reader = undefined; | |
| 822 | 822 | br.initFixed(case.data); |
| 823 | 823 | var iter: PaxIterator = .init(&br, case.data.len); |
| 824 | 824 | |
| ... | ... | @@ -955,7 +955,7 @@ test Iterator { |
| 955 | 955 | // example/empty/ |
| 956 | 956 | |
| 957 | 957 | const data = @embedFile("tar/testdata/example.tar"); |
| 958 | var br: std.io.BufferedReader = undefined; | |
| 958 | var br: std.io.Reader = undefined; | |
| 959 | 959 | br.initFixed(data); |
| 960 | 960 | |
| 961 | 961 | // User provided buffers to the iterator |
| ... | ... | @@ -1015,7 +1015,7 @@ test pipeToFileSystem { |
| 1015 | 1015 | // example/empty/ |
| 1016 | 1016 | |
| 1017 | 1017 | const data = @embedFile("tar/testdata/example.tar"); |
| 1018 | var br: std.io.BufferedReader = undefined; | |
| 1018 | var br: std.io.Reader = undefined; | |
| 1019 | 1019 | br.initFixed(data); |
| 1020 | 1020 | |
| 1021 | 1021 | var tmp = testing.tmpDir(.{ .no_follow = true }); |
| ... | ... | @@ -1047,7 +1047,7 @@ test pipeToFileSystem { |
| 1047 | 1047 | |
| 1048 | 1048 | test "pipeToFileSystem root_dir" { |
| 1049 | 1049 | const data = @embedFile("tar/testdata/example.tar"); |
| 1050 | var br: std.io.BufferedReader = undefined; | |
| 1050 | var br: std.io.Reader = undefined; | |
| 1051 | 1051 | br.initFixed(data); |
| 1052 | 1052 | |
| 1053 | 1053 | // with strip_components = 1 |
| ... | ... | @@ -1096,7 +1096,7 @@ test "pipeToFileSystem root_dir" { |
| 1096 | 1096 | |
| 1097 | 1097 | test "findRoot with single file archive" { |
| 1098 | 1098 | const data = @embedFile("tar/testdata/22752.tar"); |
| 1099 | var br: std.io.BufferedReader = undefined; | |
| 1099 | var br: std.io.Reader = undefined; | |
| 1100 | 1100 | br.initFixed(data); |
| 1101 | 1101 | |
| 1102 | 1102 | var tmp = testing.tmpDir(.{}); |
| ... | ... | @@ -1111,7 +1111,7 @@ test "findRoot with single file archive" { |
| 1111 | 1111 | |
| 1112 | 1112 | test "findRoot without explicit root dir" { |
| 1113 | 1113 | const data = @embedFile("tar/testdata/19820.tar"); |
| 1114 | var br: std.io.BufferedReader = undefined; | |
| 1114 | var br: std.io.Reader = undefined; | |
| 1115 | 1115 | br.initFixed(data); |
| 1116 | 1116 | |
| 1117 | 1117 | var tmp = testing.tmpDir(.{}); |
| ... | ... | @@ -1126,7 +1126,7 @@ test "findRoot without explicit root dir" { |
| 1126 | 1126 | |
| 1127 | 1127 | test "pipeToFileSystem strip_components" { |
| 1128 | 1128 | const data = @embedFile("tar/testdata/example.tar"); |
| 1129 | var br: std.io.BufferedReader = undefined; | |
| 1129 | var br: std.io.Reader = undefined; | |
| 1130 | 1130 | br.initFixed(data); |
| 1131 | 1131 | |
| 1132 | 1132 | var tmp = testing.tmpDir(.{ .no_follow = true }); |
| ... | ... | @@ -1188,7 +1188,7 @@ test "executable bit" { |
| 1188 | 1188 | const data = @embedFile("tar/testdata/example.tar"); |
| 1189 | 1189 | |
| 1190 | 1190 | for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| { |
| 1191 | var br: std.io.BufferedReader = undefined; | |
| 1191 | var br: std.io.Reader = undefined; | |
| 1192 | 1192 | br.initFixed(data); |
| 1193 | 1193 | |
| 1194 | 1194 | var tmp = testing.tmpDir(.{ .no_follow = true }); |
lib/std/tar/Writer.zig+4-4| ... | ... | @@ -67,7 +67,7 @@ pub fn writeFileStream( |
| 67 | 67 | w: *Writer, |
| 68 | 68 | sub_path: []const u8, |
| 69 | 69 | size: usize, |
| 70 | reader: *std.io.BufferedReader, | |
| 70 | reader: *std.io.Reader, | |
| 71 | 71 | options: Options, |
| 72 | 72 | ) std.io.Reader.StreamError!void { |
| 73 | 73 | try w.writeHeader(.regular, sub_path, "", @intCast(size), options); |
| ... | ... | @@ -441,7 +441,7 @@ test "write files" { |
| 441 | 441 | for (files) |file| |
| 442 | 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 | 445 | input.initFixed(output.getWritten()); |
| 446 | 446 | var iter = std.tar.iterator(&input, .{ |
| 447 | 447 | .file_name_buffer = &file_name_buffer, |
| ... | ... | @@ -476,12 +476,12 @@ test "write files" { |
| 476 | 476 | var wrt: Writer = .{ .underlying_writer = &output.buffered_writer }; |
| 477 | 477 | defer output.deinit(); |
| 478 | 478 | for (files) |file| { |
| 479 | var content: std.io.BufferedReader = undefined; | |
| 479 | var content: std.io.Reader = undefined; | |
| 480 | 480 | content.initFixed(file.content); |
| 481 | 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 | 485 | input.initFixed(output.getWritten()); |
| 486 | 486 | var iter = std.tar.iterator(&input, .{ |
| 487 | 487 | .file_name_buffer = &file_name_buffer, |
lib/std/tar/test.zig+9-14| ... | ... | @@ -346,8 +346,7 @@ test "run test cases" { |
| 346 | 346 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 347 | 347 | |
| 348 | 348 | for (cases) |case| { |
| 349 | var br: std.io.BufferedReader = undefined; | |
| 350 | br.initFixed(case.data); | |
| 349 | var br: std.io.Reader = .fixed(case.data); | |
| 351 | 350 | var iter = tar.iterator(&br, .{ |
| 352 | 351 | .file_name_buffer = &file_name_buffer, |
| 353 | 352 | .link_name_buffer = &link_name_buffer, |
| ... | ... | @@ -391,8 +390,7 @@ test "pax/gnu long names with small buffer" { |
| 391 | 390 | const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] }; |
| 392 | 391 | |
| 393 | 392 | for (long_name_cases) |case| { |
| 394 | var br: std.io.BufferedReader = undefined; | |
| 395 | br.initFixed(case.data); | |
| 393 | var br: std.io.Reader = .fixed(case.data); | |
| 396 | 394 | var iter = tar.iterator(&br, .{ |
| 397 | 395 | .file_name_buffer = &min_file_name_buffer, |
| 398 | 396 | .link_name_buffer = &min_link_name_buffer, |
| ... | ... | @@ -413,8 +411,7 @@ test "insufficient buffer in Header name filed" { |
| 413 | 411 | var min_file_name_buffer: [9]u8 = undefined; |
| 414 | 412 | var min_link_name_buffer: [100]u8 = undefined; |
| 415 | 413 | |
| 416 | var br: std.io.BufferedReader = undefined; | |
| 417 | br.initFixed(cases[0].data); | |
| 414 | var br: std.io.Reader = .fixed(cases[0].data); | |
| 418 | 415 | var iter = tar.iterator(&br, .{ |
| 419 | 416 | .file_name_buffer = &min_file_name_buffer, |
| 420 | 417 | .link_name_buffer = &min_link_name_buffer, |
| ... | ... | @@ -469,22 +466,21 @@ test "should not overwrite existing file" { |
| 469 | 466 | // This ensures that file is not overwritten. |
| 470 | 467 | // |
| 471 | 468 | const data = @embedFile("testdata/overwrite_file.tar"); |
| 472 | var br: std.io.BufferedReader = undefined; | |
| 473 | br.initFixed(data); | |
| 469 | var r: std.io.Reader = .fixed(data); | |
| 474 | 470 | |
| 475 | 471 | // Unpack with strip_components = 1 should fail |
| 476 | 472 | var root = std.testing.tmpDir(.{}); |
| 477 | 473 | defer root.cleanup(); |
| 478 | 474 | try testing.expectError( |
| 479 | 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 | 479 | // Unpack with strip_components = 0 should pass |
| 484 | br.initFixed(data); | |
| 480 | r = .fixed(data); | |
| 485 | 481 | var root2 = std.testing.tmpDir(.{}); |
| 486 | 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 | 486 | test "case sensitivity" { |
| ... | ... | @@ -498,13 +494,12 @@ test "case sensitivity" { |
| 498 | 494 | // 18089/alacritty/Darkermatrix.yml |
| 499 | 495 | // |
| 500 | 496 | const data = @embedFile("testdata/18089.tar"); |
| 501 | var br: std.io.BufferedReader = undefined; | |
| 502 | br.initFixed(data); | |
| 497 | var r: std.io.Reader = .fixed(data); | |
| 503 | 498 | |
| 504 | 499 | var root = std.testing.tmpDir(.{}); |
| 505 | 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 | 503 | // on case insensitive fs we fail on overwrite existing file |
| 509 | 504 | try testing.expectEqual(error.PathAlreadyExists, err); |
| 510 | 505 | return; |
lib/std/tz.zig+4-4| ... | ... | @@ -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 | 58 | var legacy_header = try reader.takeStruct(Header); |
| 59 | 59 | if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader; |
| 60 | 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 | 215 | |
| 216 | 216 | test "slim" { |
| 217 | 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 | 219 | in_stream.initFixed(data); |
| 220 | 220 | |
| 221 | 221 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); |
| ... | ... | @@ -229,7 +229,7 @@ test "slim" { |
| 229 | 229 | |
| 230 | 230 | test "fat" { |
| 231 | 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 | 233 | in_stream.initFixed(data); |
| 234 | 234 | |
| 235 | 235 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); |
| ... | ... | @@ -243,7 +243,7 @@ test "fat" { |
| 243 | 243 | test "legacy" { |
| 244 | 244 | // Taken from Slackware 8.0, from 2001 |
| 245 | 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 | 247 | in_stream.initFixed(data); |
| 248 | 248 | |
| 249 | 249 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); |
lib/std/zig/Server.zig+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | in: *std.io.BufferedReader, | |
| 1 | in: *std.io.Reader, | |
| 2 | 2 | out: *std.io.BufferedWriter, |
| 3 | 3 | |
| 4 | 4 | pub const Message = struct { |
| ... | ... | @@ -93,7 +93,7 @@ pub const Message = struct { |
| 93 | 93 | }; |
| 94 | 94 | |
| 95 | 95 | pub const Options = struct { |
| 96 | in: *std.io.BufferedReader, | |
| 96 | in: *std.io.Reader, | |
| 97 | 97 | out: *std.io.BufferedWriter, |
| 98 | 98 | zig_version: []const u8, |
| 99 | 99 | }; |
lib/std/zig/llvm/BitcodeReader.zig+7-7| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | allocator: std.mem.Allocator, |
| 2 | 2 | record_arena: std.heap.ArenaAllocator.State, |
| 3 | br: *std.io.BufferedReader, | |
| 3 | reader: *std.io.Reader, | |
| 4 | 4 | keep_names: bool, |
| 5 | 5 | bit_buffer: u32, |
| 6 | 6 | bit_offset: u5, |
| ... | ... | @@ -93,14 +93,14 @@ pub const Record = struct { |
| 93 | 93 | }; |
| 94 | 94 | |
| 95 | 95 | pub const InitOptions = struct { |
| 96 | br: *std.io.BufferedReader, | |
| 96 | reader: *std.io.Reader, | |
| 97 | 97 | keep_names: bool = false, |
| 98 | 98 | }; |
| 99 | 99 | pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader { |
| 100 | 100 | return .{ |
| 101 | 101 | .allocator = allocator, |
| 102 | 102 | .record_arena = .{}, |
| 103 | .br = options.br, | |
| 103 | .reader = options.reader, | |
| 104 | 104 | .keep_names = options.keep_names, |
| 105 | 105 | .bit_buffer = 0, |
| 106 | 106 | .bit_offset = 0, |
| ... | ... | @@ -172,7 +172,7 @@ pub fn next(bc: *BitcodeReader) !?Item { |
| 172 | 172 | |
| 173 | 173 | pub fn skipBlock(bc: *BitcodeReader, block: Block) !void { |
| 174 | 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 | 176 | try bc.endBlock(); |
| 177 | 177 | } |
| 178 | 178 | |
| ... | ... | @@ -371,17 +371,17 @@ fn align32Bits(bc: *BitcodeReader) void { |
| 371 | 371 | |
| 372 | 372 | fn read32Bits(bc: *BitcodeReader) !u32 { |
| 373 | 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 | 377 | fn readBytes(bc: *BitcodeReader, bytes: []u8) !void { |
| 378 | 378 | assert(bc.bit_offset == 0); |
| 379 | try bc.br.read(bytes); | |
| 379 | try bc.reader.read(bytes); | |
| 380 | 380 | |
| 381 | 381 | const trailing_bytes = bytes.len % 4; |
| 382 | 382 | if (trailing_bytes > 0) { |
| 383 | 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 | 385 | bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little); |
| 386 | 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 | 342 | expected_model: *const Target.Cpu.Model, |
| 343 | 343 | input: []const u8, |
| 344 | 344 | ) !void { |
| 345 | var br: std.io.BufferedReader = undefined; | |
| 346 | br.initFixed(@constCast(input)); | |
| 347 | const result = try parser.parse(arch, &br); | |
| 345 | var r: std.io.Reader = .fixed(input); | |
| 346 | const result = try parser.parse(arch, &r); | |
| 348 | 347 | try testing.expectEqual(expected_model, result.?.model); |
| 349 | 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 | 161 | |
| 162 | 162 | pub const Decompress = union { |
| 163 | 163 | inflate: std.compress.flate.Decompress, |
| 164 | store: *std.io.BufferedReader, | |
| 164 | store: *std.io.Reader, | |
| 165 | 165 | |
| 166 | 166 | fn readable( |
| 167 | 167 | d: *Decompress, |
| 168 | reader: *std.io.BufferedReader, | |
| 168 | reader: *std.io.Reader, | |
| 169 | 169 | method: CompressionMethod, |
| 170 | 170 | buffer: []u8, |
| 171 | ) std.io.BufferedReader { | |
| 171 | ) std.io.Reader { | |
| 172 | 172 | switch (method) { |
| 173 | 173 | .store => { |
| 174 | 174 | d.* = .{ .store = reader }; |
lib/std/zip/test.zig+2-2| ... | ... | @@ -51,7 +51,7 @@ const FileStore = struct { |
| 51 | 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 | 55 | const store = try std.testing.allocator.alloc(FileStore, files.len); |
| 56 | 56 | defer std.testing.allocator.free(store); |
| 57 | 57 | return makeZipWithStore(file_writer, files, options, store); |
| ... | ... | @@ -198,7 +198,7 @@ const Zipper = struct { |
| 198 | 198 | }, |
| 199 | 199 | .deflate => { |
| 200 | 200 | const offset = writer.count; |
| 201 | var br: std.io.BufferedReader = undefined; | |
| 201 | var br: std.io.Reader = undefined; | |
| 202 | 202 | br.initFixed(@constCast(opt.content)); |
| 203 | 203 | var compress: std.compress.flate.Compress = .init(&br, .{}); |
| 204 | 204 | var compress_br = compress.readable(&.{}); |
src/Compilation.zig+2-3| ... | ... | @@ -1076,9 +1076,8 @@ pub const CObject = struct { |
| 1076 | 1076 | var buffer: [1024]u8 = undefined; |
| 1077 | 1077 | const file = try std.fs.cwd().openFile(path, .{}); |
| 1078 | 1078 | defer file.close(); |
| 1079 | var br: std.io.BufferedReader = undefined; | |
| 1080 | br.init(file.reader(), &buffer); | |
| 1081 | var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .br = &br }); | |
| 1079 | var file_reader = file.reader(&buffer); | |
| 1080 | var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface }); | |
| 1082 | 1081 | defer bc.deinit(); |
| 1083 | 1082 | |
| 1084 | 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 | 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 | 83 | return switch (oid_format) { |
| 84 | 84 | .sha1 => { |
| 85 | 85 | var result: Oid = .{ .sha1 = undefined }; |
| ... | ... | @@ -593,7 +593,7 @@ const Packet = union(enum) { |
| 593 | 593 | const max_data_length = 65516; |
| 594 | 594 | |
| 595 | 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 | 597 | const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket; |
| 598 | 598 | switch (length) { |
| 599 | 599 | 0 => return .flush, |
| ... | ... | @@ -1107,7 +1107,7 @@ const PackHeader = struct { |
| 1107 | 1107 | const signature = "PACK"; |
| 1108 | 1108 | const supported_version = 2; |
| 1109 | 1109 | |
| 1110 | fn read(reader: *std.io.BufferedReader) !PackHeader { | |
| 1110 | fn read(reader: *std.io.Reader) !PackHeader { | |
| 1111 | 1111 | const actual_signature = try reader.take(4); |
| 1112 | 1112 | if (!mem.eql(u8, actual_signature, signature)) return error.InvalidHeader; |
| 1113 | 1113 | const version = try reader.takeInt(u32, .big); |
| ... | ... | @@ -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 | 1165 | const InitialByte = packed struct { len: u4, type: u3, has_next: bool }; |
| 1166 | 1166 | const initial: InitialByte = @bitCast(try reader.takeByte()); |
| 1167 | 1167 | const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0; |
| ... | ... | @@ -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 | 1191 | const Byte = packed struct { value: u7, has_next: bool }; |
| 1192 | 1192 | var b: Byte = @bitCast(try r.takeByte()); |
| 1193 | 1193 | var value: u64 = b.value; |
| ... | ... | @@ -1200,7 +1200,7 @@ fn readSizeVarInt(r: *std.io.BufferedReader) !u64 { |
| 1200 | 1200 | return value; |
| 1201 | 1201 | } |
| 1202 | 1202 | |
| 1203 | fn readOffsetVarInt(r: *std.io.BufferedReader) !u64 { | |
| 1203 | fn readOffsetVarInt(r: *std.io.Reader) !u64 { | |
| 1204 | 1204 | const Byte = packed struct { value: u7, has_next: bool }; |
| 1205 | 1205 | var b: Byte = @bitCast(try r.takeByte()); |
| 1206 | 1206 | var value: u64 = b.value; |
| ... | ... | @@ -1219,7 +1219,7 @@ const IndexHeader = struct { |
| 1219 | 1219 | const supported_version = 2; |
| 1220 | 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 | 1223 | const sig = try br.take(4); |
| 1224 | 1224 | if (!mem.eql(u8, sig, signature)) return error.InvalidHeader; |
| 1225 | 1225 | const version = try br.takeInt(u32, .big); |
| ... | ... | @@ -1493,7 +1493,7 @@ fn resolveDeltaChain( |
| 1493 | 1493 | } |
| 1494 | 1494 | |
| 1495 | 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 | 1497 | const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge; |
| 1498 | 1498 | var decompress: zlib.Decompressor = .init(reader); |
| 1499 | 1499 | var buffer: std.ArrayListUnmanaged(u8) = .empty; |
| ... | ... | @@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u |
| 1505 | 1505 | |
| 1506 | 1506 | /// The format of the delta data is documented in |
| 1507 | 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 | 1509 | var base_offset: u32 = 0; |
| 1510 | 1510 | while (true) { |
| 1511 | 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 | 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 | 2832 | var instructions: std.MultiArrayList(Zir.Inst) = .{}; |
| 2833 | 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 | 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 | 2951 | var zoir: Zoir = .{ |
| 2952 | 2952 | .nodes = .empty, |
| 2953 | 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 | 372 | } |
| 373 | 373 | |
| 374 | 374 | fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate { |
| 375 | var br: std.io.BufferedReader = undefined; | |
| 375 | var br: std.io.Reader = undefined; | |
| 376 | 376 | br.initFixed(dis.code[dis.pos..]); |
| 377 | 377 | defer dis.pos += br.seek; |
| 378 | 378 | return switch (kind) { |
| ... | ... | @@ -388,7 +388,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate { |
| 388 | 388 | } |
| 389 | 389 | |
| 390 | 390 | fn parseOffset(dis: *Disassembler) !u64 { |
| 391 | var br: std.io.BufferedReader = undefined; | |
| 391 | var br: std.io.Reader = undefined; | |
| 392 | 392 | br.initFixed(dis.code[dis.pos..]); |
| 393 | 393 | defer dis.pos += br.seek; |
| 394 | 394 | return br.takeInt(u64, .little); |
| ... | ... | @@ -464,8 +464,7 @@ fn parseSibByte(dis: *Disassembler) !Sib { |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | 466 | fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 { |
| 467 | var br: std.io.BufferedReader = undefined; | |
| 468 | br.initFixed(dis.code[dis.pos..]); | |
| 467 | var br: std.io.Reader = .fixed(dis.code[dis.pos..]); | |
| 469 | 468 | defer dis.pos += br.seek; |
| 470 | 469 | if (sib) |info| { |
| 471 | 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 | 793 | // twice, which causes a "duplicate symbol" assembler error. |
| 794 | 794 | var versions_written = std.AutoArrayHashMap(Version, void).init(arena); |
| 795 | 795 | |
| 796 | var inc_br: std.io.BufferedReader = undefined; | |
| 797 | inc_br.initFixed(metadata.inclusions); | |
| 796 | var inc_br: std.io.Reader = .fixed(metadata.inclusions); | |
| 798 | 797 | |
| 799 | 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 | 142 | &abbrev_code_buf, |
| 143 | 143 | debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, |
| 144 | 144 | ) != abbrev_code_buf.len) return error.InputOutput; |
| 145 | var abbrev_code_br: std.io.BufferedReader = undefined; | |
| 146 | abbrev_code_br.initFixed(&abbrev_code_buf); | |
| 145 | var abbrev_code_br: std.io.Reader = .fixed(&abbrev_code_buf); | |
| 147 | 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 | 2756 | try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); |
| 2758 | 2757 | } else { |
| 2759 | 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 | 2760 | abbrev_code_br.initFixed(abbrev_code_buf); |
| 2762 | 2761 | const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable); |
| 2763 | 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 | 1192 | const atom_ptr = self.atom(atom_index).?; |
| 1193 | 1193 | const shdr = atom_ptr.inputShdr(elf_file); |
| 1194 | 1194 | const handle = elf_file.fileHandle(self.file_handle); |
| 1195 | var br: std.io.BufferedReader = undefined; | |
| 1196 | br.initFixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index)); | |
| 1197 | defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(br.storageBuffer()); | |
| 1195 | var r: std.io.Reader = .fixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index)); | |
| 1196 | defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(r.storageBuffer()); | |
| 1198 | 1197 | |
| 1199 | 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 | 1200 | switch (chdr.ch_type) { |
| 1202 | 1201 | .ZLIB => { |
| 1203 | 1202 | var bw: std.io.BufferedWriter = undefined; |
| 1204 | 1203 | bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow)); |
| 1205 | 1204 | errdefer gpa.free(bw.buffer); |
| 1206 | try std.compress.zlib.decompress(&br, &bw); | |
| 1205 | try std.compress.zlib.decompress(&r, &bw); | |
| 1207 | 1206 | if (bw.end != bw.buffer.len) return error.InputOutput; |
| 1208 | 1207 | return bw.buffer; |
| 1209 | 1208 | }, |
| ... | ... | @@ -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 | 1216 | fn locals(self: *Object) []Symbol { |
src/link/Elf/eh_frame.zig+6-6| ... | ... | @@ -187,7 +187,7 @@ pub const Cie = struct { |
| 187 | 187 | }; |
| 188 | 188 | |
| 189 | 189 | pub const Iterator = struct { |
| 190 | br: std.io.BufferedReader, | |
| 190 | reader: std.io.Reader, | |
| 191 | 191 | |
| 192 | 192 | pub const Record = struct { |
| 193 | 193 | tag: enum { fde, cie }, |
| ... | ... | @@ -196,18 +196,18 @@ pub const Iterator = struct { |
| 196 | 196 | }; |
| 197 | 197 | |
| 198 | 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 | 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 | 205 | const record: Record = .{ |
| 206 | 206 | .tag = if (id == 0) .cie else .fde, |
| 207 | .offset = it.br.seek, | |
| 207 | .offset = it.reader.seek, | |
| 208 | 208 | .size = size, |
| 209 | 209 | }; |
| 210 | try it.br.discard(size); | |
| 210 | try it.reader.discard(size); | |
| 211 | 211 | |
| 212 | 212 | return record; |
| 213 | 213 | } |
src/link/MachO/Dwarf.zig+6-8| ... | ... | @@ -273,10 +273,9 @@ pub const InfoReader = struct { |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | 275 | pub fn readLeb128(p: *InfoReader, comptime Type: type) !Type { |
| 276 | var br: std.io.BufferedReader = undefined; | |
| 277 | br.initFixed(p.bytes()[p.pos..]); | |
| 278 | defer p.pos += br.seek; | |
| 279 | return br.takeLeb128(Type); | |
| 276 | var r: std.io.Reader = .fixed(p.bytes()[p.pos..]); | |
| 277 | defer p.pos += r.seek; | |
| 278 | return r.takeLeb128(Type); | |
| 280 | 279 | } |
| 281 | 280 | |
| 282 | 281 | pub fn seekTo(p: *InfoReader, off: u64) !void { |
| ... | ... | @@ -331,10 +330,9 @@ pub const AbbrevReader = struct { |
| 331 | 330 | } |
| 332 | 331 | |
| 333 | 332 | pub fn readLeb128(p: *AbbrevReader, comptime Type: type) !Type { |
| 334 | var br: std.io.BufferedReader = undefined; | |
| 335 | br.initFixed(p.bytes()[p.pos..]); | |
| 336 | defer p.pos += br.seek; | |
| 337 | return br.takeLeb128(Type); | |
| 333 | var r: std.io.Reader = .fixed(p.bytes()[p.pos..]); | |
| 334 | defer p.pos += r.seek; | |
| 335 | return r.takeLeb128(Type); | |
| 338 | 336 | } |
| 339 | 337 | |
| 340 | 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 | 167 | |
| 168 | 168 | fn parseTrieNode( |
| 169 | 169 | self: *Dylib, |
| 170 | br: *std.io.BufferedReader, | |
| 170 | br: *std.io.Reader, | |
| 171 | 171 | allocator: Allocator, |
| 172 | 172 | arena: Allocator, |
| 173 | 173 | prefix: []const u8, |
| ... | ... | @@ -216,9 +216,8 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void { |
| 216 | 216 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 217 | 217 | defer arena.deinit(); |
| 218 | 218 | |
| 219 | var br: std.io.BufferedReader = undefined; | |
| 220 | br.initFixed(data); | |
| 221 | try self.parseTrieNode(&br, gpa, arena.allocator(), ""); | |
| 219 | var r: std.io.Reader = .fixed(data); | |
| 220 | try self.parseTrieNode(&r, gpa, arena.allocator(), ""); | |
| 222 | 221 | } |
| 223 | 222 | |
| 224 | 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 | 12 | const tracy = trace(@src()); |
| 13 | 13 | defer tracy.end(); |
| 14 | 14 | |
| 15 | var br: std.io.BufferedReader = undefined; | |
| 16 | br.initFixed(cie.getData(macho_file)); | |
| 15 | var r: std.io.Reader = .fixed(cie.getData(macho_file)); | |
| 17 | 16 | |
| 18 | try br.discard(9); | |
| 19 | const aug = try br.takeSentinel(0); | |
| 17 | try r.discard(9); | |
| 18 | const aug = try r.takeSentinel(0); | |
| 20 | 19 | if (aug[0] != 'z') return; // TODO should we error out? |
| 21 | 20 | |
| 22 | _ = try br.takeLeb128(u64); // code alignment factor | |
| 23 | _ = try br.takeLeb128(u64); // data alignment factor | |
| 24 | _ = try br.takeLeb128(u64); // return address register | |
| 25 | _ = try br.takeLeb128(u64); // augmentation data length | |
| 21 | _ = try r.takeLeb128(u64); // code alignment factor | |
| 22 | _ = try r.takeLeb128(u64); // data alignment factor | |
| 23 | _ = try r.takeLeb128(u64); // return address register | |
| 24 | _ = try r.takeLeb128(u64); // augmentation data length | |
| 26 | 25 | |
| 27 | 26 | for (aug[1..]) |ch| switch (ch) { |
| 28 | 27 | 'R' => { |
| 29 | const enc = try br.takeByte(); | |
| 28 | const enc = try r.takeByte(); | |
| 30 | 29 | if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) { |
| 31 | 30 | @panic("unexpected pointer encoding"); // TODO error |
| 32 | 31 | } |
| 33 | 32 | }, |
| 34 | 33 | 'P' => { |
| 35 | const enc = try br.takeByte(); | |
| 34 | const enc = try r.takeByte(); | |
| 36 | 35 | if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) { |
| 37 | 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 | 40 | 'L' => { |
| 42 | const enc = try br.takeByte(); | |
| 41 | const enc = try r.takeByte(); | |
| 43 | 42 | switch (enc & DW_EH_PE.type_mask) { |
| 44 | 43 | DW_EH_PE.sdata4 => cie.lsda_size = .p32, |
| 45 | 44 | DW_EH_PE.absptr => cie.lsda_size = .p64, |
| ... | ... | @@ -143,7 +142,7 @@ pub const Fde = struct { |
| 143 | 142 | const object = fde.getObject(macho_file); |
| 144 | 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 | 146 | br.initFixed(fde.getData(macho_file)); |
| 148 | 147 | |
| 149 | 148 | try br.discard(4); |
| ... | ... | @@ -267,7 +266,7 @@ pub const Fde = struct { |
| 267 | 266 | }; |
| 268 | 267 | |
| 269 | 268 | pub const Iterator = struct { |
| 270 | br: std.io.BufferedReader, | |
| 269 | br: std.io.Reader, | |
| 271 | 270 | |
| 272 | 271 | pub const Record = struct { |
| 273 | 272 | tag: enum { fde, cie }, |
src/link/Wasm.zig+4-5| ... | ... | @@ -2087,10 +2087,9 @@ pub const Expr = enum(u32) { |
| 2087 | 2087 | pub const end = @intFromEnum(std.wasm.Opcode.end); |
| 2088 | 2088 | |
| 2089 | 2089 | pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 { |
| 2090 | var br: std.io.BufferedReader = undefined; | |
| 2091 | br.initFixed(wasm.string_bytes.items[@intFromEnum(index)..]); | |
| 2092 | Object.skipInit(&br) catch unreachable; | |
| 2093 | return br.storageBuffer()[0 .. br.seek - 1 :end]; | |
| 2090 | var r: std.io.Reader = .fixed(wasm.string_bytes.items[@intFromEnum(index)..]); | |
| 2091 | Object.skipInit(&r) catch unreachable; | |
| 2092 | return r.storageBuffer()[0 .. r.seek - 1 :end]; | |
| 2094 | 2093 | } |
| 2095 | 2094 | }; |
| 2096 | 2095 | |
| ... | ... | @@ -3038,7 +3037,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { |
| 3038 | 3037 | const stat = try obj.file.stat(); |
| 3039 | 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 | 3041 | br.initFixed(try gpa.alloc(u8, size)); |
| 3043 | 3042 | defer gpa.free(br.storageBuffer()); |
| 3044 | 3043 |
src/link/Wasm/Archive.zig+2-4| ... | ... | @@ -167,10 +167,8 @@ pub fn parseObject( |
| 167 | 167 | }; |
| 168 | 168 | |
| 169 | 169 | const object_file_size = try header.parsedSize(); |
| 170 | var br: std.io.BufferedReader = undefined; | |
| 171 | br.initFixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]); | |
| 172 | ||
| 173 | return Object.parse(wasm, &br, path, object_name, host_name, scratch_space, must_link, gc_sections); | |
| 170 | var r: std.io.Reader = .fixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]); | |
| 171 | return Object.parse(wasm, &r, path, object_name, host_name, scratch_space, must_link, gc_sections); | |
| 174 | 172 | } |
| 175 | 173 | |
| 176 | 174 | const Archive = @This(); |
src/link/Wasm/Object.zig+5-5| ... | ... | @@ -252,7 +252,7 @@ pub const ScratchSpace = struct { |
| 252 | 252 | |
| 253 | 253 | pub fn parse( |
| 254 | 254 | wasm: *Wasm, |
| 255 | br: *std.io.BufferedReader, | |
| 255 | br: *std.io.Reader, | |
| 256 | 256 | path: Path, |
| 257 | 257 | archive_member_name: ?[]const u8, |
| 258 | 258 | host_name: Wasm.OptionalString, |
| ... | ... | @@ -1402,7 +1402,7 @@ pub fn parse( |
| 1402 | 1402 | /// Based on the "features" custom section, parses it into a list of |
| 1403 | 1403 | /// features that tell the linker what features were enabled and may be mandatory |
| 1404 | 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 | 1406 | const gpa = wasm.base.comp.gpa; |
| 1407 | 1407 | const diags = &wasm.base.comp.link_diags; |
| 1408 | 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 | 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 | 1434 | const flags: std.wasm.Limits.Flags = @bitCast(try br.takeByte()); |
| 1435 | 1435 | const min = try br.takeLeb128(u32); |
| 1436 | 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 | 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 | 1445 | const start = br.seek; |
| 1446 | 1446 | try skipInit(br); // one after the end opcode |
| 1447 | 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 | 1451 | switch (try br.takeEnum(std.wasm.Opcode, .little)) { |
| 1452 | 1452 | .i32_const => _ = try br.takeLeb128(i32), |
| 1453 | 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 | 13 | switch (op) { |
| 14 | 14 | .set => try overwriteUleb(@intCast(addend), bw), |
| 15 | 15 | .sub => { |
| 16 | var br: std.io.BufferedReader = undefined; | |
| 17 | br.initFixed(try bw.writableArray(1)); | |
| 18 | const old_value = try br.takeLeb128(u64); | |
| 16 | var r: std.io.Reader = .fixed(try bw.writableArray(1)); | |
| 17 | const old_value = try r.takeLeb128(u64); | |
| 19 | 18 | try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw); |
| 20 | 19 | }, |
| 21 | 20 | } |