| author | |
| committer | |
| log | f612d5ae96c9f327e9cb5e53d8e47db7ba206418 |
| tree | 6431826dcf2a83d44ee6059de783ca926f39b983 |
| parent | 46b5eb6ec3fed3c97512c05c13aa6f3dd9b71b87 |
and make reading file streaming allowed to return 0 byte reads.
According to Microsoft documentation, on Windows it is possible to get
0-byte reads from pipes when 0-byte writes are made.6 files changed, 62 insertions(+), 75 deletions(-)
lib/std/Io.zig+4-7| ... | @@ -264,10 +264,7 @@ pub fn Poller(comptime StreamEnum: type) type { | ... | @@ -264,10 +264,7 @@ pub fn Poller(comptime StreamEnum: type) type { |
| 264 | // always check if there's some data waiting to be read first. | 264 | // always check if there's some data waiting to be read first. |
| 265 | if (poll_fd.revents & posix.POLL.IN != 0) { | 265 | if (poll_fd.revents & posix.POLL.IN != 0) { |
| 266 | const buf = try writableSliceGreedyAlloc(r, gpa, bump_amt); | 266 | const buf = try writableSliceGreedyAlloc(r, gpa, bump_amt); |
| 267 | const amt = posix.read(poll_fd.fd, buf) catch |err| switch (err) { | 267 | const amt = try posix.read(poll_fd.fd, buf); |
| 268 | error.BrokenPipe => 0, // Handle the same as EOF. | ||
| 269 | else => |e| return e, | ||
| 270 | }; | ||
| 271 | advanceBufferEnd(r, amt); | 268 | advanceBufferEnd(r, amt); |
| 272 | if (amt == 0) { | 269 | if (amt == 0) { |
| 273 | // Remove the fd when the EOF condition is met. | 270 | // Remove the fd when the EOF condition is met. |
| ... | @@ -633,9 +630,9 @@ pub const VTable = struct { | ... | @@ -633,9 +630,9 @@ pub const VTable = struct { |
| 633 | fileWritePositional: *const fn (?*anyopaque, File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) File.WritePositionalError!usize, | 630 | fileWritePositional: *const fn (?*anyopaque, File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) File.WritePositionalError!usize, |
| 634 | fileWriteFileStreaming: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit) File.Writer.WriteFileError!usize, | 631 | fileWriteFileStreaming: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit) File.Writer.WriteFileError!usize, |
| 635 | fileWriteFilePositional: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit, offset: u64) File.WriteFilePositionalError!usize, | 632 | fileWriteFilePositional: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit, offset: u64) File.WriteFilePositionalError!usize, |
| 636 | /// Returns 0 on end of stream. | 633 | /// May return 0 reads which is different than `error.EndOfStream`. |
| 637 | fileReadStreaming: *const fn (?*anyopaque, File, data: []const []u8) File.Reader.Error!usize, | 634 | fileReadStreaming: *const fn (?*anyopaque, File, data: []const []u8) File.ReadStreamingError!usize, |
| 638 | /// Returns 0 on end of stream. | 635 | /// Returns 0 if reading at or past the end. |
| 639 | fileReadPositional: *const fn (?*anyopaque, File, data: []const []u8, offset: u64) File.ReadPositionalError!usize, | 636 | fileReadPositional: *const fn (?*anyopaque, File, data: []const []u8, offset: u64) File.ReadPositionalError!usize, |
| 640 | fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void, | 637 | fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void, |
| 641 | fileSeekTo: *const fn (?*anyopaque, File, absolute_offset: u64) File.SeekError!void, | 638 | fileSeekTo: *const fn (?*anyopaque, File, absolute_offset: u64) File.SeekError!void, |
lib/std/Io/File.zig+3-2| ... | @@ -550,11 +550,13 @@ pub fn setTimestampsNow(file: File, io: Io) SetTimestampsError!void { | ... | @@ -550,11 +550,13 @@ pub fn setTimestampsNow(file: File, io: Io) SetTimestampsError!void { |
| 550 | }); | 550 | }); |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | pub const ReadStreamingError = error{EndOfStream} || Reader.Error; | ||
| 554 | |||
| 553 | /// Returns 0 on stream end or if `buffer` has no space available for data. | 555 | /// Returns 0 on stream end or if `buffer` has no space available for data. |
| 554 | /// | 556 | /// |
| 555 | /// See also: | 557 | /// See also: |
| 556 | /// * `reader` | 558 | /// * `reader` |
| 557 | pub fn readStreaming(file: File, io: Io, buffer: []const []u8) Reader.Error!usize { | 559 | pub fn readStreaming(file: File, io: Io, buffer: []const []u8) ReadStreamingError!usize { |
| 558 | return io.vtable.fileReadStreaming(io.userdata, file, buffer); | 560 | return io.vtable.fileReadStreaming(io.userdata, file, buffer); |
| 559 | } | 561 | } |
| 560 | 562 | ||
| ... | @@ -563,7 +565,6 @@ pub const ReadPositionalError = error{ | ... | @@ -563,7 +565,6 @@ pub const ReadPositionalError = error{ |
| 563 | SystemResources, | 565 | SystemResources, |
| 564 | /// Trying to read a directory file descriptor as if it were a file. | 566 | /// Trying to read a directory file descriptor as if it were a file. |
| 565 | IsDir, | 567 | IsDir, |
| 566 | BrokenPipe, | ||
| 567 | /// Non-blocking has been enabled, and reading from the file descriptor | 568 | /// Non-blocking has been enabled, and reading from the file descriptor |
| 568 | /// would block. | 569 | /// would block. |
| 569 | WouldBlock, | 570 | WouldBlock, |
lib/std/Io/File/Reader.zig+18-15| ... | @@ -31,7 +31,6 @@ pub const Error = error{ | ... | @@ -31,7 +31,6 @@ pub const Error = error{ |
| 31 | SystemResources, | 31 | SystemResources, |
| 32 | /// Trying to read a directory file descriptor as if it were a file. | 32 | /// Trying to read a directory file descriptor as if it were a file. |
| 33 | IsDir, | 33 | IsDir, |
| 34 | BrokenPipe, | ||
| 35 | ConnectionResetByPeer, | 34 | ConnectionResetByPeer, |
| 36 | /// File was not opened with read capability. | 35 | /// File was not opened with read capability. |
| 37 | NotOpenForReading, | 36 | NotOpenForReading, |
| ... | @@ -300,14 +299,16 @@ fn readVecStreaming(r: *Reader, data: [][]u8) Io.Reader.Error!usize { | ... | @@ -300,14 +299,16 @@ fn readVecStreaming(r: *Reader, data: [][]u8) Io.Reader.Error!usize { |
| 300 | const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); | 299 | const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); |
| 301 | const dest = iovecs_buffer[0..dest_n]; | 300 | const dest = iovecs_buffer[0..dest_n]; |
| 302 | assert(dest[0].len > 0); | 301 | assert(dest[0].len > 0); |
| 303 | const n = io.vtable.fileReadStreaming(io.userdata, r.file, dest) catch |err| { | 302 | const n = io.vtable.fileReadStreaming(io.userdata, r.file, dest) catch |err| switch (err) { |
| 304 | r.err = err; | 303 | error.EndOfStream => { |
| 305 | return error.ReadFailed; | 304 | r.size = r.pos; |
| 305 | return error.EndOfStream; | ||
| 306 | }, | ||
| 307 | else => |e| { | ||
| 308 | r.err = e; | ||
| 309 | return error.ReadFailed; | ||
| 310 | }, | ||
| 306 | }; | 311 | }; |
| 307 | if (n == 0) { | ||
| 308 | r.size = r.pos; | ||
| 309 | return error.EndOfStream; | ||
| 310 | } | ||
| 311 | r.pos += n; | 312 | r.pos += n; |
| 312 | if (n > data_size) { | 313 | if (n > data_size) { |
| 313 | r.interface.end += n - data_size; | 314 | r.interface.end += n - data_size; |
| ... | @@ -355,14 +356,16 @@ fn discard(io_reader: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize { | ... | @@ -355,14 +356,16 @@ fn discard(io_reader: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize { |
| 355 | const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, &data); | 356 | const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, &data); |
| 356 | const dest = iovecs_buffer[0..dest_n]; | 357 | const dest = iovecs_buffer[0..dest_n]; |
| 357 | assert(dest[0].len > 0); | 358 | assert(dest[0].len > 0); |
| 358 | const n = io.vtable.fileReadStreaming(io.userdata, file, dest) catch |err| { | 359 | const n = io.vtable.fileReadStreaming(io.userdata, file, dest) catch |err| switch (err) { |
| 359 | r.err = err; | 360 | error.EndOfStream => { |
| 360 | return error.ReadFailed; | 361 | r.size = r.pos; |
| 362 | return error.EndOfStream; | ||
| 363 | }, | ||
| 364 | else => |e| { | ||
| 365 | r.err = e; | ||
| 366 | return error.ReadFailed; | ||
| 367 | }, | ||
| 361 | }; | 368 | }; |
| 362 | if (n == 0) { | ||
| 363 | r.size = r.pos; | ||
| 364 | return error.EndOfStream; | ||
| 365 | } | ||
| 366 | r.pos += n; | 369 | r.pos += n; |
| 367 | if (n > data_size) { | 370 | if (n > data_size) { |
| 368 | r.interface.end += n - data_size; | 371 | r.interface.end += n - data_size; |
lib/std/Io/Threaded.zig+36-48| ... | @@ -8139,14 +8139,14 @@ fn fileClose(userdata: ?*anyopaque, files: []const File) void { | ... | @@ -8139,14 +8139,14 @@ fn fileClose(userdata: ?*anyopaque, files: []const File) void { |
| 8139 | for (files) |file| posix.close(file.handle); | 8139 | for (files) |file| posix.close(file.handle); |
| 8140 | } | 8140 | } |
| 8141 | 8141 | ||
| 8142 | fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { | 8142 | fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: []const []u8) File.ReadStreamingError!usize { |
| 8143 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 8143 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 8144 | _ = t; | 8144 | _ = t; |
| 8145 | if (is_windows) return fileReadStreamingWindows(file, data); | 8145 | if (is_windows) return fileReadStreamingWindows(file, data); |
| 8146 | return fileReadStreamingPosix(file, data); | 8146 | return fileReadStreamingPosix(file, data); |
| 8147 | } | 8147 | } |
| 8148 | 8148 | ||
| 8149 | fn fileReadStreamingPosix(file: File, data: []const []u8) File.Reader.Error!usize { | 8149 | fn fileReadStreamingPosix(file: File, data: []const []u8) File.ReadStreamingError!usize { |
| 8150 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; | 8150 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; |
| 8151 | var i: usize = 0; | 8151 | var i: usize = 0; |
| 8152 | for (data) |buf| { | 8152 | for (data) |buf| { |
| ... | @@ -8167,28 +8167,24 @@ fn fileReadStreamingPosix(file: File, data: []const []u8) File.Reader.Error!usiz | ... | @@ -8167,28 +8167,24 @@ fn fileReadStreamingPosix(file: File, data: []const []u8) File.Reader.Error!usiz |
| 8167 | switch (std.os.wasi.fd_read(file.handle, dest.ptr, dest.len, &nread)) { | 8167 | switch (std.os.wasi.fd_read(file.handle, dest.ptr, dest.len, &nread)) { |
| 8168 | .SUCCESS => { | 8168 | .SUCCESS => { |
| 8169 | syscall.finish(); | 8169 | syscall.finish(); |
| 8170 | if (nread == 0) return error.EndOfStream; | ||
| 8170 | return nread; | 8171 | return nread; |
| 8171 | }, | 8172 | }, |
| 8172 | .INTR, .TIMEDOUT => { | 8173 | .INTR, .TIMEDOUT => { |
| 8173 | try syscall.checkCancel(); | 8174 | try syscall.checkCancel(); |
| 8174 | continue; | 8175 | continue; |
| 8175 | }, | 8176 | }, |
| 8176 | else => |e| { | 8177 | .BADF => return syscall.fail(error.IsDir), // File operation on directory. |
| 8177 | syscall.finish(); | 8178 | .IO => return syscall.fail(error.InputOutput), |
| 8178 | switch (e) { | 8179 | .ISDIR => return syscall.fail(error.IsDir), |
| 8179 | .INVAL => |err| return errnoBug(err), | 8180 | .NOBUFS => return syscall.fail(error.SystemResources), |
| 8180 | .FAULT => |err| return errnoBug(err), | 8181 | .NOMEM => return syscall.fail(error.SystemResources), |
| 8181 | .BADF => return error.IsDir, // File operation on directory. | 8182 | .NOTCONN => return syscall.fail(error.SocketUnconnected), |
| 8182 | .IO => return error.InputOutput, | 8183 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), |
| 8183 | .ISDIR => return error.IsDir, | 8184 | .NOTCAPABLE => return syscall.fail(error.AccessDenied), |
| 8184 | .NOBUFS => return error.SystemResources, | 8185 | .INVAL => |err| return syscall.errnoBug(err), |
| 8185 | .NOMEM => return error.SystemResources, | 8186 | .FAULT => |err| return syscall.errnoBug(err), |
| 8186 | .NOTCONN => return error.SocketUnconnected, | 8187 | else => |err| return syscall.unexpectedErrno(err), |
| 8187 | .CONNRESET => return error.ConnectionResetByPeer, | ||
| 8188 | .NOTCAPABLE => return error.AccessDenied, | ||
| 8189 | else => |err| return posix.unexpectedErrno(err), | ||
| 8190 | } | ||
| 8191 | }, | ||
| 8192 | } | 8188 | } |
| 8193 | } | 8189 | } |
| 8194 | } | 8190 | } |
| ... | @@ -8199,36 +8195,33 @@ fn fileReadStreamingPosix(file: File, data: []const []u8) File.Reader.Error!usiz | ... | @@ -8199,36 +8195,33 @@ fn fileReadStreamingPosix(file: File, data: []const []u8) File.Reader.Error!usiz |
| 8199 | switch (posix.errno(rc)) { | 8195 | switch (posix.errno(rc)) { |
| 8200 | .SUCCESS => { | 8196 | .SUCCESS => { |
| 8201 | syscall.finish(); | 8197 | syscall.finish(); |
| 8198 | if (rc == 0) return error.EndOfStream; | ||
| 8202 | return @intCast(rc); | 8199 | return @intCast(rc); |
| 8203 | }, | 8200 | }, |
| 8204 | .INTR, .TIMEDOUT => { | 8201 | .INTR, .TIMEDOUT => { |
| 8205 | try syscall.checkCancel(); | 8202 | try syscall.checkCancel(); |
| 8206 | continue; | 8203 | continue; |
| 8207 | }, | 8204 | }, |
| 8208 | else => |e| { | 8205 | .BADF => { |
| 8209 | syscall.finish(); | 8206 | syscall.finish(); |
| 8210 | switch (e) { | 8207 | if (native_os == .wasi) return error.IsDir; // File operation on directory. |
| 8211 | .INVAL => |err| return errnoBug(err), | 8208 | return error.NotOpenForReading; |
| 8212 | .FAULT => |err| return errnoBug(err), | ||
| 8213 | .AGAIN => return error.WouldBlock, | ||
| 8214 | .BADF => { | ||
| 8215 | if (native_os == .wasi) return error.IsDir; // File operation on directory. | ||
| 8216 | return error.NotOpenForReading; | ||
| 8217 | }, | ||
| 8218 | .IO => return error.InputOutput, | ||
| 8219 | .ISDIR => return error.IsDir, | ||
| 8220 | .NOBUFS => return error.SystemResources, | ||
| 8221 | .NOMEM => return error.SystemResources, | ||
| 8222 | .NOTCONN => return error.SocketUnconnected, | ||
| 8223 | .CONNRESET => return error.ConnectionResetByPeer, | ||
| 8224 | else => |err| return posix.unexpectedErrno(err), | ||
| 8225 | } | ||
| 8226 | }, | 8209 | }, |
| 8210 | .AGAIN => return syscall.fail(error.WouldBlock), | ||
| 8211 | .IO => return syscall.fail(error.InputOutput), | ||
| 8212 | .ISDIR => return syscall.fail(error.IsDir), | ||
| 8213 | .NOBUFS => return syscall.fail(error.SystemResources), | ||
| 8214 | .NOMEM => return syscall.fail(error.SystemResources), | ||
| 8215 | .NOTCONN => return syscall.fail(error.SocketUnconnected), | ||
| 8216 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), | ||
| 8217 | .INVAL => |err| return syscall.errnoBug(err), | ||
| 8218 | .FAULT => |err| return syscall.errnoBug(err), | ||
| 8219 | else => |err| return syscall.unexpectedErrno(err), | ||
| 8227 | } | 8220 | } |
| 8228 | } | 8221 | } |
| 8229 | } | 8222 | } |
| 8230 | 8223 | ||
| 8231 | fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!usize { | 8224 | fn fileReadStreamingWindows(file: File, data: []const []u8) File.ReadStreamingError!usize { |
| 8232 | var index: usize = 0; | 8225 | var index: usize = 0; |
| 8233 | while (index < data.len and data[index].len == 0) index += 1; | 8226 | while (index < data.len and data[index].len == 0) index += 1; |
| 8234 | if (index == data.len) return 0; | 8227 | if (index == data.len) return 0; |
| ... | @@ -8250,25 +8243,18 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8250,25 +8243,18 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8250 | null, // key | 8243 | null, // key |
| 8251 | )) { | 8244 | )) { |
| 8252 | .SUCCESS => { | 8245 | .SUCCESS => { |
| 8253 | // Only END_OF_FILE is the true end. | 8246 | syscall.finish(); |
| 8254 | if (io_status_block.Information == 0) { | 8247 | return io_status_block.Information; |
| 8255 | try syscall.checkCancel(); | ||
| 8256 | continue; | ||
| 8257 | } else { | ||
| 8258 | syscall.finish(); | ||
| 8259 | io_status_block.u.Status = .SUCCESS; | ||
| 8260 | return io_status_block.Information; | ||
| 8261 | } | ||
| 8262 | }, | 8248 | }, |
| 8263 | .END_OF_FILE, .PIPE_BROKEN => { | 8249 | .END_OF_FILE, .PIPE_BROKEN => { |
| 8264 | syscall.finish(); | 8250 | syscall.finish(); |
| 8265 | return io_status_block.Information; | 8251 | return error.EndOfStream; |
| 8266 | }, | 8252 | }, |
| 8267 | .PENDING => break, | ||
| 8268 | .CANCELLED => { | 8253 | .CANCELLED => { |
| 8269 | try syscall.checkCancel(); | 8254 | try syscall.checkCancel(); |
| 8270 | continue; | 8255 | continue; |
| 8271 | }, | 8256 | }, |
| 8257 | .PENDING => break, | ||
| 8272 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), | 8258 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8273 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), | 8259 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8274 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), | 8260 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| ... | @@ -8302,7 +8288,9 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8302,7 +8288,9 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8302 | alertable_syscall.finish(); | 8288 | alertable_syscall.finish(); |
| 8303 | } | 8289 | } |
| 8304 | switch (io_status_block.u.Status) { | 8290 | switch (io_status_block.u.Status) { |
| 8305 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, | 8291 | .SUCCESS => return io_status_block.Information, |
| 8292 | .END_OF_FILE => return error.EndOfStream, | ||
| 8293 | .PIPE_BROKEN => return error.EndOfStream, | ||
| 8306 | .PENDING => unreachable, // cannot return until the operation completes | 8294 | .PENDING => unreachable, // cannot return until the operation completes |
| 8307 | .INVALID_DEVICE_REQUEST => return error.IsDir, | 8295 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8308 | .LOCK_NOT_GRANTED => return error.LockViolation, | 8296 | .LOCK_NOT_GRANTED => return error.LockViolation, |
lib/std/Progress.zig+1-2| ... | @@ -984,7 +984,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff | ... | @@ -984,7 +984,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff |
| 984 | var bytes_read: usize = 0; | 984 | var bytes_read: usize = 0; |
| 985 | while (true) { | 985 | while (true) { |
| 986 | const n = file.readStreaming(io, &.{pipe_buf[bytes_read..]}) catch |err| switch (err) { | 986 | const n = file.readStreaming(io, &.{pipe_buf[bytes_read..]}) catch |err| switch (err) { |
| 987 | error.WouldBlock => break, | 987 | error.WouldBlock, error.EndOfStream => break, |
| 988 | else => |e| { | 988 | else => |e| { |
| 989 | std.log.debug("failed to read child progress data: {t}", .{e}); | 989 | std.log.debug("failed to read child progress data: {t}", .{e}); |
| 990 | main_storage.completed_count = 0; | 990 | main_storage.completed_count = 0; |
| ... | @@ -992,7 +992,6 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff | ... | @@ -992,7 +992,6 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff |
| 992 | continue :main_loop; | 992 | continue :main_loop; |
| 993 | }, | 993 | }, |
| 994 | }; | 994 | }; |
| 995 | if (n == 0) break; | ||
| 996 | if (opt_saved_metadata) |m| { | 995 | if (opt_saved_metadata) |m| { |
| 997 | if (m.remaining_read_trash_bytes > 0) { | 996 | if (m.remaining_read_trash_bytes > 0) { |
| 998 | assert(bytes_read == 0); | 997 | assert(bytes_read == 0); |
lib/std/zig/system.zig-1| ... | @@ -418,7 +418,6 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { | ... | @@ -418,7 +418,6 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { |
| 418 | error.Canceled => |e| return e, | 418 | error.Canceled => |e| return e, |
| 419 | error.Unexpected => |e| return e, | 419 | error.Unexpected => |e| return e, |
| 420 | error.WouldBlock => return error.Unexpected, | 420 | error.WouldBlock => return error.Unexpected, |
| 421 | error.BrokenPipe => return error.Unexpected, | ||
| 422 | error.ConnectionResetByPeer => return error.Unexpected, | 421 | error.ConnectionResetByPeer => return error.Unexpected, |
| 423 | error.NotOpenForReading => return error.Unexpected, | 422 | error.NotOpenForReading => return error.Unexpected, |
| 424 | error.SocketUnconnected => return error.Unexpected, | 423 | error.SocketUnconnected => return error.Unexpected, |