authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:52:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:52:29-07:00
log483c057a771aca3b045ec8148fa5fb1a5e28fa17
tree7ee84cd567bac20ed769845b0e469fe39e1c2f6c
parent3468872d8376602fdbfdb5b0d6d582c278ad1990
parentd68adc5382a29687d2e24e27d9877473346a25e1

Merge branch 'clean up writeFileAllUnseekable by using readers'

closes #7156

5 files changed, 66 insertions(+), 20 deletions(-)

CMakeLists.txt+2-1
...@@ -375,10 +375,11 @@ set(ZIG_STAGE2_SOURCES...@@ -375,10 +375,11 @@ set(ZIG_STAGE2_SOURCES
375 "${CMAKE_SOURCE_DIR}/lib/std/io/buffered_atomic_file.zig"375 "${CMAKE_SOURCE_DIR}/lib/std/io/buffered_atomic_file.zig"
376 "${CMAKE_SOURCE_DIR}/lib/std/io/buffered_writer.zig"376 "${CMAKE_SOURCE_DIR}/lib/std/io/buffered_writer.zig"
377 "${CMAKE_SOURCE_DIR}/lib/std/io/change_detection_stream.zig"377 "${CMAKE_SOURCE_DIR}/lib/std/io/change_detection_stream.zig"
378 "${CMAKE_SOURCE_DIR}/lib/std/io/counting_writer.zig"
379 "${CMAKE_SOURCE_DIR}/lib/std/io/counting_reader.zig"378 "${CMAKE_SOURCE_DIR}/lib/std/io/counting_reader.zig"
379 "${CMAKE_SOURCE_DIR}/lib/std/io/counting_writer.zig"
380 "${CMAKE_SOURCE_DIR}/lib/std/io/find_byte_writer.zig"380 "${CMAKE_SOURCE_DIR}/lib/std/io/find_byte_writer.zig"
381 "${CMAKE_SOURCE_DIR}/lib/std/io/fixed_buffer_stream.zig"381 "${CMAKE_SOURCE_DIR}/lib/std/io/fixed_buffer_stream.zig"
382 "${CMAKE_SOURCE_DIR}/lib/std/io/limited_reader.zig"
382 "${CMAKE_SOURCE_DIR}/lib/std/io/reader.zig"383 "${CMAKE_SOURCE_DIR}/lib/std/io/reader.zig"
383 "${CMAKE_SOURCE_DIR}/lib/std/io/seekable_stream.zig"384 "${CMAKE_SOURCE_DIR}/lib/std/io/seekable_stream.zig"
384 "${CMAKE_SOURCE_DIR}/lib/std/io/writer.zig"385 "${CMAKE_SOURCE_DIR}/lib/std/io/writer.zig"
lib/std/fs/file.zig+9-18
...@@ -698,7 +698,7 @@ pub const File = struct {...@@ -698,7 +698,7 @@ pub const File = struct {
698 header_count: usize = 0,698 header_count: usize = 0,
699 };699 };
700700
701 pub const WriteFileError = ReadError || WriteError;701 pub const WriteFileError = ReadError || error{EndOfStream} || WriteError;
702702
703 pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {703 pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
704 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {704 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {
...@@ -722,23 +722,14 @@ pub const File = struct {...@@ -722,23 +722,14 @@ pub const File = struct {
722722
723 try self.writevAll(headers);723 try self.writevAll(headers);
724724
725 var buffer: [4096]u8 = undefined;725 try in_file.reader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
726 {726
727 var index: usize = 0;727 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
728 // Skip in_offset bytes.728 if (args.in_len) |len| {
729 while (index < args.in_offset) {729 var stream = std.io.limitedReader(in_file.reader(), len);
730 const ask = math.min(buffer.len, args.in_offset - index);730 try fifo.pump(stream.reader(), self.writer());
731 const amt = try in_file.read(buffer[0..ask]);731 } else {
732 index += amt;732 try fifo.pump(in_file.reader(), self.writer());
733 }
734 }
735 const in_len = args.in_len orelse math.maxInt(u64);
736 var index: usize = 0;
737 while (index < in_len) {
738 const ask = math.min(buffer.len, in_len - index);
739 const amt = try in_file.read(buffer[0..ask]);
740 if (amt == 0) break;
741 index += try self.write(buffer[0..amt]);
742 }733 }
743734
744 try self.writevAll(trailers);735 try self.writevAll(trailers);
lib/std/io.zig+3
...@@ -125,6 +125,9 @@ pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferS...@@ -125,6 +125,9 @@ pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferS
125pub const CWriter = @import("io/c_writer.zig").CWriter;125pub const CWriter = @import("io/c_writer.zig").CWriter;
126pub const cWriter = @import("io/c_writer.zig").cWriter;126pub const cWriter = @import("io/c_writer.zig").cWriter;
127127
128pub const LimitedReader = @import("io/limited_reader.zig").LimitedReader;
129pub const limitedReader = @import("io/limited_reader.zig").limitedReader;
130
128pub const CountingWriter = @import("io/counting_writer.zig").CountingWriter;131pub const CountingWriter = @import("io/counting_writer.zig").CountingWriter;
129pub const countingWriter = @import("io/counting_writer.zig").countingWriter;132pub const countingWriter = @import("io/counting_writer.zig").countingWriter;
130pub const CountingReader = @import("io/counting_reader.zig").CountingReader;133pub const CountingReader = @import("io/counting_reader.zig").CountingReader;
lib/std/io/limited_reader.zig created+50
...@@ -0,0 +1,50 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6const std = @import("../std.zig");
7const io = std.io;
8const assert = std.debug.assert;
9const testing = std.testing;
10
11pub fn LimitedReader(comptime ReaderType: type) type {
12 return struct {
13 inner_reader: ReaderType,
14 bytes_left: u64,
15
16 pub const Error = ReaderType.Error;
17 pub const Reader = io.Reader(*Self, Error, read);
18
19 const Self = @This();
20
21 pub fn read(self: *Self, dest: []u8) Error!usize {
22 const max_read = std.math.min(self.bytes_left, dest.len);
23 const n = try self.inner_reader.read(dest[0..max_read]);
24 self.bytes_left -= n;
25 return n;
26 }
27
28 pub fn reader(self: *Self) Reader {
29 return .{ .context = self };
30 }
31 };
32}
33
34/// Returns an initialised `LimitedReader`
35/// `bytes_left` is a `u64` to be able to take 64 bit file offsets
36pub fn limitedReader(inner_reader: anytype, bytes_left: u64) LimitedReader(@TypeOf(inner_reader)) {
37 return .{ .inner_reader = inner_reader, .bytes_left = bytes_left };
38}
39
40test "basic usage" {
41 const data = "hello world";
42 var fbs = std.io.fixedBufferStream(data);
43 var early_stream = limitedReader(fbs.reader(), 3);
44
45 var buf: [5]u8 = undefined;
46 testing.expectEqual(@as(usize, 3), try early_stream.reader().read(&buf));
47 testing.expectEqualSlices(u8, data[0..3], buf[0..3]);
48 testing.expectEqual(@as(usize, 0), try early_stream.reader().read(&buf));
49 testing.expectError(error.EndOfStream, early_stream.reader().skipBytes(10, .{}));
50}
lib/std/io/reader.zig+2-1
...@@ -271,8 +271,9 @@ pub fn Reader(...@@ -271,8 +271,9 @@ pub fn Reader(
271 buf_size: usize = 512,271 buf_size: usize = 512,
272 };272 };
273273
274 // `num_bytes` is a `u64` to match `off_t`
274 /// Reads `num_bytes` bytes from the stream and discards them275 /// Reads `num_bytes` bytes from the stream and discards them
275 pub fn skipBytes(self: Self, num_bytes: usize, comptime options: SkipBytesOptions) !void {276 pub fn skipBytes(self: Self, num_bytes: u64, comptime options: SkipBytesOptions) !void {
276 var buf: [options.buf_size]u8 = undefined;277 var buf: [options.buf_size]u8 = undefined;
277 var remaining = num_bytes;278 var remaining = num_bytes;
278279