struct Stream [src]

Fields

handle: posix.socket_tUnderlying platform-defined type which may or may not be interchangeable with a file system file descriptor.

Members

Source

pub const Stream = struct { /// Underlying platform-defined type which may or may not be /// interchangeable with a file system file descriptor. handle: posix.socket_t, pub fn close(s: Stream) void { switch (native_os) { .windows => windows.closesocket(s.handle) catch unreachable, else => posix.close(s.handle), } } pub const ReadError = posix.ReadError; pub const WriteError = posix.WriteError; pub const Reader = io.Reader(Stream, ReadError, read); pub const Writer = io.Writer(Stream, WriteError, write); pub fn reader(self: Stream) Reader { return .{ .context = self }; } pub fn writer(self: Stream) Writer { return .{ .context = self }; } pub fn read(self: Stream, buffer: []u8) ReadError!usize { if (native_os == .windows) { return windows.ReadFile(self.handle, buffer, null); } return posix.read(self.handle, buffer); } pub fn readv(s: Stream, iovecs: []const posix.iovec) ReadError!usize { if (native_os == .windows) { // TODO improve this to use ReadFileScatter if (iovecs.len == 0) return @as(usize, 0); const first = iovecs[0]; return windows.ReadFile(s.handle, first.base[0..first.len], null); } return posix.readv(s.handle, iovecs); } /// Returns the number of bytes read. If the number read is smaller than /// `buffer.len`, it means the stream reached the end. Reaching the end of /// a stream is not an error condition. pub fn readAll(s: Stream, buffer: []u8) ReadError!usize { return readAtLeast(s, buffer, buffer.len); } /// Returns the number of bytes read, calling the underlying read function /// the minimal number of times until the buffer has at least `len` bytes /// filled. If the number read is less than `len` it means the stream /// reached the end. Reaching the end of the stream is not an error /// condition. pub fn readAtLeast(s: Stream, buffer: []u8, len: usize) ReadError!usize { assert(len <= buffer.len); var index: usize = 0; while (index < len) { const amt = try s.read(buffer[index..]); if (amt == 0) break; index += amt; } return index; } /// TODO in evented I/O mode, this implementation incorrectly uses the event loop's /// file system thread instead of non-blocking. It needs to be reworked to properly /// use non-blocking I/O. pub fn write(self: Stream, buffer: []const u8) WriteError!usize { if (native_os == .windows) { return windows.WriteFile(self.handle, buffer, null); } return posix.write(self.handle, buffer); } pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void { var index: usize = 0; while (index < bytes.len) { index += try self.write(bytes[index..]); } } /// See https://github.com/ziglang/zig/issues/7699 /// See equivalent function: `std.fs.File.writev`. pub fn writev(self: Stream, iovecs: []const posix.iovec_const) WriteError!usize { return posix.writev(self.handle, iovecs); } /// The `iovecs` parameter is mutable because this function needs to mutate the fields in /// order to handle partial writes from the underlying OS layer. /// See https://github.com/ziglang/zig/issues/7699 /// See equivalent function: `std.fs.File.writevAll`. pub fn writevAll(self: Stream, iovecs: []posix.iovec_const) WriteError!void { if (iovecs.len == 0) return; var i: usize = 0; while (true) { var amt = try self.writev(iovecs[i..]); while (amt >= iovecs[i].len) { amt -= iovecs[i].len; i += 1; if (i >= iovecs.len) return; } iovecs[i].base += amt; iovecs[i].len -= amt; } } }