| author | |
| committer | |
| log | c27ab8b45d767388eba5c3e69fc4b4764ae5e1c4 |
| tree | 2e9e42a25fbf0aed4c683ea61723ff82aba769c1 |
| parent | 743326f8e929238a843697397d21361c4081fead |
5 files changed, 59 insertions(+), 41 deletions(-)
lib/std/compress/zstd.zig+6-4| ... | ... | @@ -81,10 +81,11 @@ pub const table_size_max = struct { |
| 81 | 81 | 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 | try out.ensureUnusedCapacity(gpa, default_window_len); | |
| 84 | 85 | |
| 85 | 86 | var in: std.io.Reader = .fixed(compressed); |
| 86 | var zstd_stream: Decompress = .init(&in, .{}); | |
| 87 | try zstd_stream.reader().readRemainingArrayList(gpa, null, &out, .unlimited, default_window_len); | |
| 87 | var zstd_stream: Decompress = .init(&in, &.{}, .{}); | |
| 88 | try zstd_stream.interface.appendRemaining(gpa, null, &out, .unlimited); | |
| 88 | 89 | |
| 89 | 90 | return out.toOwnedSlice(gpa); |
| 90 | 91 | } |
| ... | ... | @@ -101,12 +102,13 @@ fn testExpectDecompressError(err: anyerror, compressed: []const u8) !void { |
| 101 | 102 | |
| 102 | 103 | var out: std.ArrayListUnmanaged(u8) = .empty; |
| 103 | 104 | defer out.deinit(gpa); |
| 105 | try out.ensureUnusedCapacity(gpa, default_window_len); | |
| 104 | 106 | |
| 105 | 107 | var in: std.io.Reader = .fixed(compressed); |
| 106 | var zstd_stream: Decompress = .init(&in, .{}); | |
| 108 | var zstd_stream: Decompress = .init(&in, &.{}, .{}); | |
| 107 | 109 | try std.testing.expectError( |
| 108 | 110 | error.ReadFailed, |
| 109 | zstd_stream.reader().readRemainingArrayList(gpa, null, &out, .unlimited, default_window_len), | |
| 111 | zstd_stream.interface.appendRemaining(gpa, null, &out, .unlimited), | |
| 110 | 112 | ); |
| 111 | 113 | try std.testing.expectError(err, zstd_stream.err orelse {}); |
| 112 | 114 | } |
lib/std/compress/zstd/Decompress.zig+13-13| ... | ... | @@ -7,6 +7,7 @@ const zstd = @import("../zstd.zig"); |
| 7 | 7 | const Writer = std.io.Writer; |
| 8 | 8 | |
| 9 | 9 | input: *Reader, |
| 10 | interface: Reader, | |
| 10 | 11 | state: State, |
| 11 | 12 | verify_checksum: bool, |
| 12 | 13 | err: ?Error = null, |
| ... | ... | @@ -62,34 +63,33 @@ pub const Error = error{ |
| 62 | 63 | WindowSizeUnknown, |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | pub fn init(input: *Reader, options: Options) Decompress { | |
| 66 | pub fn init(input: *Reader, buffer: []u8, options: Options) Decompress { | |
| 66 | 67 | return .{ |
| 67 | 68 | .input = input, |
| 68 | 69 | .state = .new_frame, |
| 69 | 70 | .verify_checksum = options.verify_checksum, |
| 71 | .interface = .{ | |
| 72 | .vtable = &.{ .stream = stream }, | |
| 73 | .buffer = buffer, | |
| 74 | .seek = 0, | |
| 75 | .end = 0, | |
| 76 | }, | |
| 70 | 77 | }; |
| 71 | 78 | } |
| 72 | 79 | |
| 73 | pub fn reader(self: *Decompress) Reader { | |
| 74 | return .{ | |
| 75 | .context = self, | |
| 76 | .vtable = &.{ .read = read }, | |
| 77 | }; | |
| 78 | } | |
| 79 | ||
| 80 | fn read(context: ?*anyopaque, bw: *Writer, limit: Limit) Reader.StreamError!usize { | |
| 81 | const d: *Decompress = @ptrCast(@alignCast(context)); | |
| 80 | fn stream(r: *Reader, w: *Writer, limit: Limit) Reader.StreamError!usize { | |
| 81 | const d: *Decompress = @alignCast(@fieldParentPtr("interface", r)); | |
| 82 | 82 | const in = d.input; |
| 83 | 83 | |
| 84 | 84 | switch (d.state) { |
| 85 | 85 | .new_frame => { |
| 86 | 86 | // Allow error.EndOfStream only on the frame magic. |
| 87 | 87 | const magic = try in.takeEnumNonexhaustive(Frame.Magic, .little); |
| 88 | initFrame(d, bw.buffer.len, magic) catch |err| { | |
| 88 | initFrame(d, w.buffer.len, magic) catch |err| { | |
| 89 | 89 | d.err = err; |
| 90 | 90 | return error.ReadFailed; |
| 91 | 91 | }; |
| 92 | return readInFrame(d, bw, limit, &d.state.in_frame) catch |err| switch (err) { | |
| 92 | return readInFrame(d, w, limit, &d.state.in_frame) catch |err| switch (err) { | |
| 93 | 93 | error.ReadFailed => return error.ReadFailed, |
| 94 | 94 | error.WriteFailed => return error.WriteFailed, |
| 95 | 95 | else => |e| { |
| ... | ... | @@ -99,7 +99,7 @@ fn read(context: ?*anyopaque, bw: *Writer, limit: Limit) Reader.StreamError!usiz |
| 99 | 99 | }; |
| 100 | 100 | }, |
| 101 | 101 | .in_frame => |*in_frame| { |
| 102 | return readInFrame(d, bw, limit, in_frame) catch |err| switch (err) { | |
| 102 | return readInFrame(d, w, limit, in_frame) catch |err| switch (err) { | |
| 103 | 103 | error.ReadFailed => return error.ReadFailed, |
| 104 | 104 | error.WriteFailed => return error.WriteFailed, |
| 105 | 105 | else => |e| { |
lib/std/fs/File.zig+10-3| ... | ... | @@ -1047,12 +1047,11 @@ pub const Reader = struct { |
| 1047 | 1047 | const r: *Reader = @fieldParentPtr("interface", io_reader); |
| 1048 | 1048 | switch (r.mode) { |
| 1049 | 1049 | .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) { |
| 1050 | error.ReadFailed => return error.ReadFailed, | |
| 1051 | error.WriteFailed => return error.WriteFailed, | |
| 1052 | 1050 | error.Unimplemented => { |
| 1053 | 1051 | r.mode = r.mode.toReading(); |
| 1054 | 1052 | return 0; |
| 1055 | 1053 | }, |
| 1054 | else => |e| return e, | |
| 1056 | 1055 | }, |
| 1057 | 1056 | .positional_reading => { |
| 1058 | 1057 | if (is_windows) { |
| ... | ... | @@ -1239,7 +1238,7 @@ pub const Reader = struct { |
| 1239 | 1238 | |
| 1240 | 1239 | pub fn atEnd(r: *Reader) bool { |
| 1241 | 1240 | // Even if stat fails, size is set when end is encountered. |
| 1242 | const size = r.getSize() orelse return false; | |
| 1241 | const size = r.size orelse return false; | |
| 1243 | 1242 | return size - r.pos == 0; |
| 1244 | 1243 | } |
| 1245 | 1244 | }; |
| ... | ... | @@ -1460,6 +1459,10 @@ pub const Writer = struct { |
| 1460 | 1459 | return 0; |
| 1461 | 1460 | }, |
| 1462 | 1461 | }; |
| 1462 | if (n == 0) { | |
| 1463 | file_reader.size = file_reader.pos; | |
| 1464 | return error.EndOfStream; | |
| 1465 | } | |
| 1463 | 1466 | file_reader.pos += n; |
| 1464 | 1467 | w.pos += n; |
| 1465 | 1468 | return n; |
| ... | ... | @@ -1497,6 +1500,10 @@ pub const Writer = struct { |
| 1497 | 1500 | w.copy_file_range_err = err; |
| 1498 | 1501 | return 0; |
| 1499 | 1502 | }; |
| 1503 | if (n == 0) { | |
| 1504 | file_reader.size = file_reader.pos; | |
| 1505 | return error.EndOfStream; | |
| 1506 | } | |
| 1500 | 1507 | file_reader.pos += n; |
| 1501 | 1508 | w.pos += n; |
| 1502 | 1509 | return n; |
lib/std/io/Reader.zig+3-3| ... | ... | @@ -146,7 +146,7 @@ pub fn discard(r: *Reader, limit: Limit) Error!usize { |
| 146 | 146 | } else .unlimited; |
| 147 | 147 | r.seek = 0; |
| 148 | 148 | r.end = 0; |
| 149 | const n = r.vtable.discard(r, remaining); | |
| 149 | const n = try r.vtable.discard(r, remaining); | |
| 150 | 150 | assert(n <= @intFromEnum(remaining)); |
| 151 | 151 | return buffered_len + n; |
| 152 | 152 | } |
| ... | ... | @@ -386,7 +386,7 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { |
| 386 | 386 | pub fn readAll(r: *Reader, w: *Writer, limit: Limit) StreamError!void { |
| 387 | 387 | var remaining = limit; |
| 388 | 388 | while (remaining.nonzero()) { |
| 389 | const n = try r.read(w, remaining); | |
| 389 | const n = try r.stream(w, remaining); | |
| 390 | 390 | remaining = remaining.subtract(n).?; |
| 391 | 391 | } |
| 392 | 392 | } |
| ... | ... | @@ -1472,7 +1472,7 @@ pub fn Hashed(comptime Hasher: type) type { |
| 1472 | 1472 | fn discard(r: *Reader, limit: Limit) Error!usize { |
| 1473 | 1473 | const this: *@This() = @alignCast(@fieldParentPtr("interface", r)); |
| 1474 | 1474 | var w = this.hasher.writer(&.{}); |
| 1475 | const n = this.in.read(&w, limit) catch |err| switch (err) { | |
| 1475 | const n = this.in.stream(&w, limit) catch |err| switch (err) { | |
| 1476 | 1476 | error.WriteFailed => unreachable, |
| 1477 | 1477 | else => |e| return e, |
| 1478 | 1478 | }; |
lib/std/io/Writer.zig+27-18| ... | ... | @@ -84,18 +84,29 @@ pub const Error = error{ |
| 84 | 84 | WriteFailed, |
| 85 | 85 | }; |
| 86 | 86 | |
| 87 | pub const ReadingFileError = error{ | |
| 87 | pub const FileAllError = error{ | |
| 88 | 88 | /// Detailed diagnostics are found on the `File.Reader` struct. |
| 89 | 89 | ReadFailed, |
| 90 | 90 | /// See the `Writer` implementation for detailed diagnostics. |
| 91 | 91 | WriteFailed, |
| 92 | 92 | }; |
| 93 | 93 | |
| 94 | pub const FileReadingError = error{ | |
| 95 | /// Detailed diagnostics are found on the `File.Reader` struct. | |
| 96 | ReadFailed, | |
| 97 | /// See the `Writer` implementation for detailed diagnostics. | |
| 98 | WriteFailed, | |
| 99 | /// Reached the end of the file being read. | |
| 100 | EndOfStream, | |
| 101 | }; | |
| 102 | ||
| 94 | 103 | pub const FileError = error{ |
| 95 | 104 | /// Detailed diagnostics are found on the `File.Reader` struct. |
| 96 | 105 | ReadFailed, |
| 97 | 106 | /// See the `Writer` implementation for detailed diagnostics. |
| 98 | 107 | WriteFailed, |
| 108 | /// Reached the end of the file being read. | |
| 109 | EndOfStream, | |
| 99 | 110 | /// Indicates the caller should do its own file reading; the callee cannot |
| 100 | 111 | /// offer a more efficient implementation. |
| 101 | 112 | Unimplemented, |
| ... | ... | @@ -642,28 +653,24 @@ pub fn sendFileTo(w: *Writer, other: *Writer, file_reader: *File.Reader, limit: |
| 642 | 653 | } |
| 643 | 654 | |
| 644 | 655 | /// Asserts nonzero buffer capacity. |
| 645 | pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!usize { | |
| 656 | pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) FileReadingError!usize { | |
| 646 | 657 | const dest = limit.slice(try w.writableSliceGreedy(1)); |
| 647 | const n = file_reader.read(dest) catch |err| switch (err) { | |
| 648 | error.EndOfStream => 0, | |
| 649 | error.ReadFailed => return error.ReadFailed, | |
| 650 | }; | |
| 658 | const n = try file_reader.read(dest); | |
| 651 | 659 | w.advance(n); |
| 652 | 660 | return n; |
| 653 | 661 | } |
| 654 | 662 | |
| 655 | pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!usize { | |
| 663 | pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize { | |
| 656 | 664 | var remaining = @intFromEnum(limit); |
| 657 | 665 | while (remaining > 0) { |
| 658 | 666 | const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) { |
| 659 | error.EndOfStream => return 0, | |
| 660 | error.ReadFailed => return error.ReadFailed, | |
| 661 | error.WriteFailed => return error.WriteFailed, | |
| 667 | error.EndOfStream => break, | |
| 662 | 668 | error.Unimplemented => { |
| 663 | 669 | file_reader.mode = file_reader.mode.toReading(); |
| 664 | try w.sendFileReadingAll(file_reader, remaining); | |
| 665 | return; | |
| 670 | remaining -= try w.sendFileReadingAll(file_reader, .limited(remaining)); | |
| 671 | break; | |
| 666 | 672 | }, |
| 673 | else => |e| return e, | |
| 667 | 674 | }; |
| 668 | 675 | remaining -= n; |
| 669 | 676 | } |
| ... | ... | @@ -676,13 +683,15 @@ pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingF |
| 676 | 683 | /// that error code does not appear in this function's error set. |
| 677 | 684 | /// |
| 678 | 685 | /// Asserts nonzero buffer capacity. |
| 679 | pub fn sendFileReadingAll(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!void { | |
| 680 | var remaining = limit; | |
| 681 | while (remaining.nonzero()) { | |
| 682 | const n = try sendFileReading(w, file_reader, remaining); | |
| 683 | if (n == 0) return; | |
| 684 | remaining = remaining.subtract(n).?; | |
| 686 | pub fn sendFileReadingAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize { | |
| 687 | var remaining = @intFromEnum(limit); | |
| 688 | while (remaining > 0) { | |
| 689 | remaining -= sendFileReading(w, file_reader, .limited(remaining)) catch |err| switch (err) { | |
| 690 | error.EndOfStream => break, | |
| 691 | else => |e| return e, | |
| 692 | }; | |
| 685 | 693 | } |
| 694 | return @intFromEnum(limit) - remaining; | |
| 686 | 695 | } |
| 687 | 696 | |
| 688 | 697 | pub fn alignBuffer( |