Type Reader [src]

Members

Source

pub const Reader = switch (native_os) { .windows => struct { /// Use `interface` for portable code. interface_state: Io.Reader, /// Use `getStream` for portable code. net_stream: Stream, /// Use `getError` for portable code. error_state: ?Error, pub const Error = ReadError; pub fn getStream(r: *const Reader) Stream { return r.net_stream; } pub fn getError(r: *const Reader) ?Error { return r.error_state; } pub fn interface(r: *Reader) *Io.Reader { return &r.interface_state; } pub fn init(net_stream: Stream, buffer: []u8) Reader { return .{ .interface_state = .{ .vtable = &.{ .stream = stream, .readVec = readVec, }, .buffer = buffer, .seek = 0, .end = 0, }, .net_stream = net_stream, .error_state = null, }; } fn stream(io_r: *Io.Reader, io_w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize { const dest = limit.slice(try io_w.writableSliceGreedy(1)); var bufs: [1][]u8 = .{dest}; const n = try readVec(io_r, &bufs); io_w.advance(n); return n; } fn readVec(io_r: *std.Io.Reader, data: [][]u8) Io.Reader.Error!usize { const r: *Reader = @alignCast(@fieldParentPtr("interface_state", io_r)); var iovecs: [max_buffers_len]windows.ws2_32.WSABUF = undefined; const bufs_n, const data_size = try io_r.writableVectorWsa(&iovecs, data); const bufs = iovecs[0..bufs_n]; assert(bufs[0].len != 0); const n = streamBufs(r, bufs) catch |err| { r.error_state = err; return error.ReadFailed; }; if (n == 0) return error.EndOfStream; if (n > data_size) { io_r.end += n - data_size; return data_size; } return n; } fn handleRecvError(winsock_error: windows.ws2_32.WinsockError) Error!void { switch (winsock_error) { .WSAECONNRESET => return error.ConnectionResetByPeer, .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space. .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2 .WSAEINVAL => return error.SocketNotBound, .WSAEMSGSIZE => return error.MessageTooBig, .WSAENETDOWN => return error.NetworkSubsystemFailed, .WSAENETRESET => return error.ConnectionResetByPeer, .WSAENOTCONN => return error.SocketNotConnected, .WSAEWOULDBLOCK => return error.WouldBlock, .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function .WSA_IO_PENDING => unreachable, .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O else => |err| return windows.unexpectedWSAError(err), } } fn streamBufs(r: *Reader, bufs: []windows.ws2_32.WSABUF) Error!u32 { var flags: u32 = 0; var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); var n: u32 = undefined; if (windows.ws2_32.WSARecv( r.net_stream.handle, bufs.ptr, @intCast(bufs.len), &n, &flags, &overlapped, null, ) == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) { .WSA_IO_PENDING => { var result_flags: u32 = undefined; if (windows.ws2_32.WSAGetOverlappedResult( r.net_stream.handle, &overlapped, &n, windows.TRUE, &result_flags, ) == windows.FALSE) try handleRecvError(windows.ws2_32.WSAGetLastError()); }, else => |winsock_error| try handleRecvError(winsock_error), }; return n; } }, else => struct { /// Use `getStream`, `interface`, and `getError` for portable code. file_reader: File.Reader, pub const Error = ReadError; pub fn interface(r: *Reader) *Io.Reader { return &r.file_reader.interface; } pub fn init(net_stream: Stream, buffer: []u8) Reader { return .{ .file_reader = .{ .interface = File.Reader.initInterface(buffer), .file = .{ .handle = net_stream.handle }, .mode = .streaming, .seek_err = error.Unseekable, .size_err = error.Streaming, }, }; } pub fn getStream(r: *const Reader) Stream { return .{ .handle = r.file_reader.file.handle }; } pub fn getError(r: *const Reader) ?Error { return r.file_reader.err; } }, }