| author | |
| committer | |
| log | 2ed47f1ed813d786e4d7d4adf18bd95d81e8e931 |
| tree | 3bb6746f15df8406b70cd717e10a8b45fa7f4fda |
| parent | ba684a18ca264463a29eb5dcd0666c07a6188538 |
7 files changed, 36 insertions(+), 160 deletions(-)
lib/std/compress/flate/Decompress.zig+1-18| ... | ... | @@ -345,19 +345,6 @@ fn readInner( |
| 345 | 345 | } |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | fn readVec(context: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize { | |
| 349 | _ = context; | |
| 350 | _ = data; | |
| 351 | @panic("TODO remove readVec primitive"); | |
| 352 | } | |
| 353 | ||
| 354 | fn discard(context: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize { | |
| 355 | _ = context; | |
| 356 | _ = limit; | |
| 357 | // Problem here is we still need access to the output ring buffer. | |
| 358 | @panic("TODO allow discard to be null"); | |
| 359 | } | |
| 360 | ||
| 361 | 348 | /// Write match (back-reference to the same data slice) starting at `distance` |
| 362 | 349 | /// back from current write position, and `length` of bytes. |
| 363 | 350 | fn writeMatch(bw: *std.io.BufferedWriter, length: u16, distance: u16) !void { |
| ... | ... | @@ -370,11 +357,7 @@ fn writeMatch(bw: *std.io.BufferedWriter, length: u16, distance: u16) !void { |
| 370 | 357 | pub fn reader(self: *Decompress) std.io.Reader { |
| 371 | 358 | return .{ |
| 372 | 359 | .context = self, |
| 373 | .vtable = &.{ | |
| 374 | .read = read, | |
| 375 | .readVec = readVec, | |
| 376 | .discard = discard, | |
| 377 | }, | |
| 360 | .vtable = &.{ .read = read }, | |
| 378 | 361 | }; |
| 379 | 362 | } |
| 380 | 363 |
lib/std/fs/AtomicFile.zig+13-13| ... | ... | @@ -1,4 +1,12 @@ |
| 1 | file: File, | |
| 1 | const AtomicFile = @This(); | |
| 2 | const std = @import("../std.zig"); | |
| 3 | const File = std.fs.File; | |
| 4 | const Dir = std.fs.Dir; | |
| 5 | const fs = std.fs; | |
| 6 | const assert = std.debug.assert; | |
| 7 | const posix = std.posix; | |
| 8 | ||
| 9 | file_writer: File.Writer, | |
| 2 | 10 | // TODO either replace this with rand_buf or use []u16 on Windows |
| 3 | 11 | tmp_path_buf: [tmp_path_len:0]u8, |
| 4 | 12 | dest_basename: []const u8, |
| ... | ... | @@ -35,8 +43,8 @@ pub fn init( |
| 35 | 43 | else => |e| return e, |
| 36 | 44 | }; |
| 37 | 45 | |
| 38 | return AtomicFile{ | |
| 39 | .file = file, | |
| 46 | return .{ | |
| 47 | .file_writer = file.writer(), | |
| 40 | 48 | .tmp_path_buf = tmp_path_buf, |
| 41 | 49 | .dest_basename = dest_basename, |
| 42 | 50 | .file_open = true, |
| ... | ... | @@ -50,7 +58,7 @@ pub fn init( |
| 50 | 58 | /// Always call deinit, even after a successful finish(). |
| 51 | 59 | pub fn deinit(self: *AtomicFile) void { |
| 52 | 60 | if (self.file_open) { |
| 53 | self.file.close(); | |
| 61 | self.file_writer.file.close(); | |
| 54 | 62 | self.file_open = false; |
| 55 | 63 | } |
| 56 | 64 | if (self.file_exists) { |
| ... | ... | @@ -72,17 +80,9 @@ pub const FinishError = posix.RenameError; |
| 72 | 80 | pub fn finish(self: *AtomicFile) FinishError!void { |
| 73 | 81 | assert(self.file_exists); |
| 74 | 82 | if (self.file_open) { |
| 75 | self.file.close(); | |
| 83 | self.file_writer.file.close(); | |
| 76 | 84 | self.file_open = false; |
| 77 | 85 | } |
| 78 | 86 | try posix.renameat(self.dir.fd, self.tmp_path_buf[0..], self.dir.fd, self.dest_basename); |
| 79 | 87 | self.file_exists = false; |
| 80 | 88 | } |
| 81 | ||
| 82 | const AtomicFile = @This(); | |
| 83 | const std = @import("../std.zig"); | |
| 84 | const File = std.fs.File; | |
| 85 | const Dir = std.fs.Dir; | |
| 86 | const fs = std.fs; | |
| 87 | const assert = std.debug.assert; | |
| 88 | const posix = std.posix; |
lib/std/fs/Dir.zig+12-5| ... | ... | @@ -2612,11 +2612,18 @@ pub fn updateFile( |
| 2612 | 2612 | var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = actual_mode }); |
| 2613 | 2613 | defer atomic_file.deinit(); |
| 2614 | 2614 | |
| 2615 | try atomic_file.file.writeFileAll(src_file, .{ | |
| 2616 | .offset = .zero, | |
| 2617 | .limit = .limited(src_stat.size), | |
| 2618 | }); | |
| 2619 | try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime); | |
| 2615 | var src_reader: File.Reader = .{ | |
| 2616 | .file = src_file, | |
| 2617 | .size = src_stat.size, | |
| 2618 | }; | |
| 2619 | var buffer: [2000]u8 = undefined; | |
| 2620 | var dest_writer = atomic_file.file_writer.writable(&buffer); | |
| 2621 | ||
| 2622 | dest_writer.writeFileAll(&src_reader, .{}) catch |err| switch (err) { | |
| 2623 | error.ReadFailed => return src_reader.err.?, | |
| 2624 | error.WriteFailed => return atomic_file.file_writer.err.?, | |
| 2625 | }; | |
| 2626 | try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime); | |
| 2620 | 2627 | try atomic_file.finish(); |
| 2621 | 2628 | return .stale; |
| 2622 | 2629 | } |
lib/std/fs/File.zig-12| ... | ... | @@ -887,18 +887,6 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError |
| 887 | 887 | return posix.pwritev(self.handle, iovecs, offset); |
| 888 | 888 | } |
| 889 | 889 | |
| 890 | pub const WriteFileError = PReadError || WriteError; | |
| 891 | ||
| 892 | pub fn writeFileAll(self: File, in_file: File, options: BufferedWriter.WriteFileOptions) WriteFileError!void { | |
| 893 | var file_writer = self.writer(); | |
| 894 | var buffer: [2000]u8 = undefined; | |
| 895 | var bw = file_writer.interface().buffered(&buffer); | |
| 896 | bw.writeFileAll(in_file, options) catch |err| switch (err) { | |
| 897 | error.WriteFailed => return file_writer.err.?, | |
| 898 | else => |e| return e, | |
| 899 | }; | |
| 900 | } | |
| 901 | ||
| 902 | 890 | /// Memoizes key information about a file handle such as: |
| 903 | 891 | /// * The size from calling stat, or the error that occurred therein. |
| 904 | 892 | /// * The current seek position. |
lib/std/http.zig+4-109| ... | ... | @@ -439,9 +439,8 @@ pub const Reader = struct { |
| 439 | 439 | return .{ |
| 440 | 440 | .context = reader, |
| 441 | 441 | .vtable = &.{ |
| 442 | .read = &chunkedRead, | |
| 443 | .readVec = &chunkedReadVec, | |
| 444 | .discard = &chunkedDiscard, | |
| 442 | .read = chunkedRead, | |
| 443 | .discard = chunkedDiscard, | |
| 445 | 444 | }, |
| 446 | 445 | }; |
| 447 | 446 | }, |
| ... | ... | @@ -451,9 +450,8 @@ pub const Reader = struct { |
| 451 | 450 | return .{ |
| 452 | 451 | .context = reader, |
| 453 | 452 | .vtable = &.{ |
| 454 | .read = &contentLengthRead, | |
| 455 | .readVec = &contentLengthReadVec, | |
| 456 | .discard = &contentLengthDiscard, | |
| 453 | .read = contentLengthRead, | |
| 454 | .discard = contentLengthDiscard, | |
| 457 | 455 | }, |
| 458 | 456 | }; |
| 459 | 457 | } else { |
| ... | ... | @@ -521,19 +519,6 @@ pub const Reader = struct { |
| 521 | 519 | return n; |
| 522 | 520 | } |
| 523 | 521 | |
| 524 | fn contentLengthReadVec(context: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize { | |
| 525 | const reader: *Reader = @alignCast(@ptrCast(context)); | |
| 526 | const remaining_content_length = &reader.state.body_remaining_content_length; | |
| 527 | const remaining = remaining_content_length.*; | |
| 528 | if (remaining == 0) { | |
| 529 | reader.state = .ready; | |
| 530 | return error.EndOfStream; | |
| 531 | } | |
| 532 | const n = try reader.in.readVecLimit(data, .limited(remaining)); | |
| 533 | remaining_content_length.* = remaining - n; | |
| 534 | return n; | |
| 535 | } | |
| 536 | ||
| 537 | 522 | fn contentLengthDiscard(ctx: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize { |
| 538 | 523 | const reader: *Reader = @alignCast(@ptrCast(ctx)); |
| 539 | 524 | const remaining_content_length = &reader.state.body_remaining_content_length; |
| ... | ... | @@ -621,96 +606,6 @@ pub const Reader = struct { |
| 621 | 606 | } |
| 622 | 607 | } |
| 623 | 608 | |
| 624 | fn chunkedReadVec(ctx: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize { | |
| 625 | const reader: *Reader = @alignCast(@ptrCast(ctx)); | |
| 626 | const chunk_len_ptr = switch (reader.state) { | |
| 627 | .ready => return error.EndOfStream, | |
| 628 | .body_remaining_chunk_len => |*x| x, | |
| 629 | else => unreachable, | |
| 630 | }; | |
| 631 | return chunkedReadVecEndless(reader, data, chunk_len_ptr) catch |err| switch (err) { | |
| 632 | error.ReadFailed => return error.ReadFailed, | |
| 633 | error.EndOfStream => { | |
| 634 | reader.body_err = error.HttpChunkTruncated; | |
| 635 | return error.ReadFailed; | |
| 636 | }, | |
| 637 | else => |e| { | |
| 638 | reader.body_err = e; | |
| 639 | return error.ReadFailed; | |
| 640 | }, | |
| 641 | }; | |
| 642 | } | |
| 643 | ||
| 644 | fn chunkedReadVecEndless( | |
| 645 | reader: *Reader, | |
| 646 | data: []const []u8, | |
| 647 | chunk_len_ptr: *RemainingChunkLen, | |
| 648 | ) (BodyError || std.io.Reader.Error)!usize { | |
| 649 | const in = reader.in; | |
| 650 | var already_requested_more = false; | |
| 651 | var amt_read: usize = 0; | |
| 652 | data: for (data) |d| { | |
| 653 | var d_i: usize = 0; | |
| 654 | len: switch (chunk_len_ptr.*) { | |
| 655 | .head => { | |
| 656 | var cp: ChunkParser = .init; | |
| 657 | while (true) { | |
| 658 | const i = cp.feed(in.bufferContents()); | |
| 659 | switch (cp.state) { | |
| 660 | .invalid => return error.HttpChunkInvalid, | |
| 661 | .data => { | |
| 662 | in.toss(i); | |
| 663 | break; | |
| 664 | }, | |
| 665 | else => { | |
| 666 | in.toss(i); | |
| 667 | already_requested_more = true; | |
| 668 | try in.fillMore(); | |
| 669 | continue; | |
| 670 | }, | |
| 671 | } | |
| 672 | } | |
| 673 | if (cp.chunk_len == 0) return parseTrailers(reader, amt_read); | |
| 674 | continue :len .init(cp.chunk_len + 2); | |
| 675 | }, | |
| 676 | .n => { | |
| 677 | if (in.bufferContents().len < 1) already_requested_more = true; | |
| 678 | if ((try in.takeByte()) != '\n') return error.HttpChunkInvalid; | |
| 679 | continue :len .head; | |
| 680 | }, | |
| 681 | .rn => { | |
| 682 | if (in.bufferContents().len < 2) already_requested_more = true; | |
| 683 | const rn = try in.takeArray(2); | |
| 684 | if (rn[0] != '\r' or rn[1] != '\n') return error.HttpChunkInvalid; | |
| 685 | continue :len .head; | |
| 686 | }, | |
| 687 | else => |remaining_chunk_len| { | |
| 688 | const available_buffer = in.bufferContents(); | |
| 689 | const copy_len = @min(available_buffer.len, d.len - d_i, remaining_chunk_len.int() - 2); | |
| 690 | @memcpy(d[d_i..][0..copy_len], available_buffer[0..copy_len]); | |
| 691 | d_i += copy_len; | |
| 692 | amt_read += copy_len; | |
| 693 | in.toss(copy_len); | |
| 694 | const next_chunk_len: RemainingChunkLen = .init(remaining_chunk_len.int() - copy_len); | |
| 695 | if (d.len - d_i == 0) { | |
| 696 | chunk_len_ptr.* = next_chunk_len; | |
| 697 | continue :data; | |
| 698 | } | |
| 699 | if (available_buffer.len - copy_len == 0) { | |
| 700 | if (already_requested_more) { | |
| 701 | chunk_len_ptr.* = next_chunk_len; | |
| 702 | return amt_read; | |
| 703 | } | |
| 704 | already_requested_more = true; | |
| 705 | try in.fillMore(); | |
| 706 | } | |
| 707 | continue :len next_chunk_len; | |
| 708 | }, | |
| 709 | } | |
| 710 | } | |
| 711 | return amt_read; | |
| 712 | } | |
| 713 | ||
| 714 | 609 | fn chunkedDiscard(ctx: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize { |
| 715 | 610 | const reader: *Reader = @alignCast(@ptrCast(ctx)); |
| 716 | 611 | const chunk_len_ptr = switch (reader.state) { |
lib/std/io/BufferedWriter.zig+5-2| ... | ... | @@ -561,7 +561,10 @@ pub fn writeFileReading( |
| 561 | 561 | limit: Limit, |
| 562 | 562 | ) Writer.ReadingFileError!usize { |
| 563 | 563 | const dest = limit.slice(try bw.writableSliceGreedy(1)); |
| 564 | const n = try file_reader.read(dest); | |
| 564 | const n = file_reader.read(dest) catch |err| switch (err) { | |
| 565 | error.EndOfStream => 0, | |
| 566 | error.ReadFailed => return error.ReadFailed, | |
| 567 | }; | |
| 565 | 568 | bw.advance(n); |
| 566 | 569 | return n; |
| 567 | 570 | } |
| ... | ... | @@ -663,7 +666,7 @@ pub fn writeFileAll( |
| 663 | 666 | bw: *BufferedWriter, |
| 664 | 667 | file_reader: *std.fs.File.Reader, |
| 665 | 668 | options: WriteFileOptions, |
| 666 | ) Writer.FileError!void { | |
| 669 | ) Writer.ReadingFileError!void { | |
| 667 | 670 | const headers_and_trailers = options.headers_and_trailers; |
| 668 | 671 | const headers = headers_and_trailers[0..options.headers_len]; |
| 669 | 672 | var remaining = options.limit; |
lib/std/io/Writer.zig+1-1| ... | ... | @@ -153,7 +153,7 @@ pub fn discardingWriteFile( |
| 153 | 153 | const seek_amt = limit.minInt(remaining); |
| 154 | 154 | // Error is observable on `file_reader` instance, and is safe to ignore |
| 155 | 155 | // depending on the caller's needs. Caller can make that decision. |
| 156 | file_reader.seekForward(seek_amt) catch {}; | |
| 156 | file_reader.seekBy(@intCast(seek_amt)) catch {}; | |
| 157 | 157 | var n: usize = seek_amt; |
| 158 | 158 | for (headers_and_trailers[0..headers_len]) |bytes| n += bytes.len; |
| 159 | 159 | if (seek_amt == remaining) { |