| ... | @@ -921,7 +921,8 @@ pub fn sendFileHeader( | ... | @@ -921,7 +921,8 @@ pub fn sendFileHeader( |
| 921 | /// Asserts nonzero buffer capacity. | 921 | /// Asserts nonzero buffer capacity. |
| 922 | pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) FileReadingError!usize { | 922 | pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) FileReadingError!usize { |
| 923 | const dest = limit.slice(try w.writableSliceGreedy(1)); | 923 | const dest = limit.slice(try w.writableSliceGreedy(1)); |
| 924 | const n = try file_reader.read(dest); | 924 | const n = try file_reader.interface.readSliceShort(dest); |
| | 925 | if (n == 0) return error.EndOfStream; |
| 925 | w.advance(n); | 926 | w.advance(n); |
| 926 | return n; | 927 | return n; |
| 927 | } | 928 | } |
| ... | @@ -934,17 +935,24 @@ pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) File | ... | @@ -934,17 +935,24 @@ pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) File |
| 934 | /// | 935 | /// |
| 935 | /// Asserts nonzero buffer capacity. | 936 | /// Asserts nonzero buffer capacity. |
| 936 | pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize { | 937 | pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize { |
| 937 | // The fallback sendFileReadingAll() path asserts non-zero buffer capacity. | 938 | // The fallback case uses `stream`. For `File.Reader`, this requires a minumum buffer size of |
| 938 | // Explicitly assert it here as well to ensure the assert is hit even if | 939 | // one since it uses `writableSliceGreedy(1)`. Asserting this here ensures that this will be |
| 939 | // the fallback path is not taken. | 940 | // hit even when the fallback is not needed. |
| 940 | assert(w.buffer.len > 0); | 941 | assert(w.buffer.len > 0); |
| | 942 | |
| 941 | var remaining = @intFromEnum(limit); | 943 | var remaining = @intFromEnum(limit); |
| 942 | while (remaining > 0) { | 944 | while (remaining > 0) { |
| 943 | const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) { | 945 | const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) { |
| 944 | error.EndOfStream => break, | 946 | error.EndOfStream => break, |
| 945 | error.Unimplemented => { | 947 | error.Unimplemented => { |
| 946 | file_reader.mode = file_reader.mode.toReading(); | 948 | file_reader.mode = file_reader.mode.toReading(); |
| 947 | remaining -= try w.sendFileReadingAll(file_reader, .limited(remaining)); | 949 | while (remaining > 0) { |
| | 950 | remaining -= file_reader.interface.stream(w, .limited(remaining)) catch |e| switch (e) { |
| | 951 | error.EndOfStream => break, |
| | 952 | error.ReadFailed => return error.ReadFailed, |
| | 953 | error.WriteFailed => return error.WriteFailed, |
| | 954 | }; |
| | 955 | } |
| 948 | break; | 956 | break; |
| 949 | }, | 957 | }, |
| 950 | else => |e| return e, | 958 | else => |e| return e, |
| ... | @@ -2276,6 +2284,12 @@ pub const Discarding = struct { | ... | @@ -2276,6 +2284,12 @@ pub const Discarding = struct { |
| 2276 | const d: *Discarding = @alignCast(@fieldParentPtr("writer", w)); | 2284 | const d: *Discarding = @alignCast(@fieldParentPtr("writer", w)); |
| 2277 | d.count += w.end; | 2285 | d.count += w.end; |
| 2278 | w.end = 0; | 2286 | w.end = 0; |
| | 2287 | const buffered_n = limit.minInt64(file_reader.interface.bufferedLen()); |
| | 2288 | if (buffered_n != 0) { |
| | 2289 | file_reader.interface.toss(buffered_n); |
| | 2290 | d.count += buffered_n; |
| | 2291 | return buffered_n; |
| | 2292 | } |
| 2279 | if (limit == .nothing) return 0; | 2293 | if (limit == .nothing) return 0; |
| 2280 | if (file_reader.getSize()) |size| { | 2294 | if (file_reader.getSize()) |size| { |
| 2281 | const n = limit.minInt64(size - file_reader.pos); | 2295 | const n = limit.minInt64(size - file_reader.pos); |
| ... | @@ -2767,7 +2781,9 @@ pub const Allocating = struct { | ... | @@ -2767,7 +2781,9 @@ pub const Allocating = struct { |
| 2767 | if (additional == 0) return error.EndOfStream; | 2781 | if (additional == 0) return error.EndOfStream; |
| 2768 | a.ensureUnusedCapacity(limit.minInt64(additional)) catch return error.WriteFailed; | 2782 | a.ensureUnusedCapacity(limit.minInt64(additional)) catch return error.WriteFailed; |
| 2769 | const dest = limit.slice(a.writer.buffer[a.writer.end..]); | 2783 | const dest = limit.slice(a.writer.buffer[a.writer.end..]); |
| 2770 | const n = try file_reader.read(dest); | 2784 | const n = try file_reader.interface.readSliceShort(dest); |
| | 2785 | // If it was a short read, then EOF has been reached and `file_reader.size` |
| | 2786 | // has been set and the EOF case will be hit on subsequent calls. |
| 2771 | a.writer.end += n; | 2787 | a.writer.end += n; |
| 2772 | return n; | 2788 | return n; |
| 2773 | } | 2789 | } |
| ... | @@ -2818,18 +2834,18 @@ test "discarding sendFile" { | ... | @@ -2818,18 +2834,18 @@ test "discarding sendFile" { |
| 2818 | | 2834 | |
| 2819 | const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); | 2835 | const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); |
| 2820 | defer file.close(); | 2836 | defer file.close(); |
| 2821 | var r_buffer: [256]u8 = undefined; | 2837 | var r_buffer: [2]u8 = undefined; |
| 2822 | var file_writer: std.fs.File.Writer = .init(file, &r_buffer); | 2838 | var file_writer: std.fs.File.Writer = .init(file, &r_buffer); |
| 2823 | try file_writer.interface.writeByte('h'); | 2839 | try file_writer.interface.writeAll("abcd"); |
| 2824 | try file_writer.interface.flush(); | 2840 | try file_writer.interface.flush(); |
| 2825 | | 2841 | |
| 2826 | var file_reader = file_writer.moveToReader(); | 2842 | var file_reader = file_writer.moveToReader(); |
| 2827 | try file_reader.seekTo(0); | 2843 | try file_reader.seekTo(0); |
| | 2844 | try file_reader.interface.fill(2); |
| 2828 | | 2845 | |
| 2829 | var w_buffer: [256]u8 = undefined; | 2846 | var w_buffer: [256]u8 = undefined; |
| 2830 | var discarding: Writer.Discarding = .init(&w_buffer); | 2847 | var discarding: Writer.Discarding = .init(&w_buffer); |
| 2831 | | 2848 | try testing.expectEqual(4, discarding.writer.sendFileAll(&file_reader, .unlimited)); |
| 2832 | _ = try file_reader.interface.streamRemaining(&discarding.writer); | | |
| 2833 | } | 2849 | } |
| 2834 | | 2850 | |
| 2835 | test "allocating sendFile" { | 2851 | test "allocating sendFile" { |
| ... | @@ -2838,18 +2854,40 @@ test "allocating sendFile" { | ... | @@ -2838,18 +2854,40 @@ test "allocating sendFile" { |
| 2838 | | 2854 | |
| 2839 | const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); | 2855 | const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); |
| 2840 | defer file.close(); | 2856 | defer file.close(); |
| 2841 | var r_buffer: [256]u8 = undefined; | 2857 | var r_buffer: [2]u8 = undefined; |
| 2842 | var file_writer: std.fs.File.Writer = .init(file, &r_buffer); | 2858 | var file_writer: std.fs.File.Writer = .init(file, &r_buffer); |
| 2843 | try file_writer.interface.writeByte('h'); | 2859 | try file_writer.interface.writeAll("abcd"); |
| 2844 | try file_writer.interface.flush(); | 2860 | try file_writer.interface.flush(); |
| 2845 | | 2861 | |
| 2846 | var file_reader = file_writer.moveToReader(); | 2862 | var file_reader = file_writer.moveToReader(); |
| 2847 | try file_reader.seekTo(0); | 2863 | try file_reader.seekTo(0); |
| | 2864 | try file_reader.interface.fill(2); |
| 2848 | | 2865 | |
| 2849 | var allocating: Writer.Allocating = .init(testing.allocator); | 2866 | var allocating: Writer.Allocating = .init(testing.allocator); |
| 2850 | defer allocating.deinit(); | 2867 | defer allocating.deinit(); |
| | 2868 | try allocating.ensureUnusedCapacity(1); |
| | 2869 | try testing.expectEqual(4, allocating.writer.sendFileAll(&file_reader, .unlimited)); |
| | 2870 | try testing.expectEqualStrings("abcd", allocating.writer.buffered()); |
| | 2871 | } |
| 2851 | | 2872 | |
| 2852 | _ = try file_reader.interface.streamRemaining(&allocating.writer); | 2873 | test sendFileReading { |
| | 2874 | var tmp_dir = testing.tmpDir(.{}); |
| | 2875 | defer tmp_dir.cleanup(); |
| | 2876 | |
| | 2877 | const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); |
| | 2878 | defer file.close(); |
| | 2879 | var r_buffer: [2]u8 = undefined; |
| | 2880 | var file_writer: std.fs.File.Writer = .init(file, &r_buffer); |
| | 2881 | try file_writer.interface.writeAll("abcd"); |
| | 2882 | try file_writer.interface.flush(); |
| | 2883 | |
| | 2884 | var file_reader = file_writer.moveToReader(); |
| | 2885 | try file_reader.seekTo(0); |
| | 2886 | try file_reader.interface.fill(2); |
| | 2887 | |
| | 2888 | var w_buffer: [1]u8 = undefined; |
| | 2889 | var discarding: Writer.Discarding = .init(&w_buffer); |
| | 2890 | try testing.expectEqual(4, discarding.writer.sendFileReadingAll(&file_reader, .unlimited)); |
| 2853 | } | 2891 | } |
| 2854 | | 2892 | |
| 2855 | test writeStruct { | 2893 | test writeStruct { |