zig/lib/std/io/out_stream.zig
Andrew Kelley c3d816a98e
std lib networking improvements, especially non-blocking I/O
* delete the std/event/net directory
 * `std.event.Loop.waitUntilFdReadable` and related functions
   no longer have possibility of failure. On Linux, they fall
   back to poll() and then fall back to sleep().
 * add some missing `noasync` decorations in `std.event.Loop`
 * redo the `std.net.Server` API. it's quite nice now, but
   shutdown does not work cleanly. There is a race condition with
   close() that I am actively working on.
 * move `std.io.OutStream` to its own file to match `std.io.InStream`.
   I started working on making `write` integrated with evented I/O,
   but it got tricky so I backed off and filed #3557. However
   I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O.
 * add `std.Target.stack_align`
 * move networking tests to `lib/std/net/test.zig`
 * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`.
 * rename `error.UnknownName` to `error.UnknownHostName` within the
   context of DNS resolution.
 * add `std.os.readv`, which is integrated with evented I/O.
 * `std.os.preadv`, is now integrated with evented I/O.
 * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never
    occur (misuse of API), instead of returning errors.
 * `std.os.connect` is now integrated with evented I/O.
   `std.os.connect_async` is gone. Just use `std.os.connect`.
 * fix false positive dependency loop regarding async function frames
 * add more compile notes to help when dependency loops occur
   in determining whether a function is async.
 * ir: change an assert to ir_assert to make it easier to find
   workarounds for when such an assert is triggered. In this case
   it was trying to parse an IPv4 address at comptime.
2019-10-29 22:59:30 -04:00

88 lines
3.3 KiB
Zig

const std = @import("../std.zig");
const builtin = @import("builtin");
const root = @import("root");
const mem = std.mem;
pub const default_stack_size = 1 * 1024 * 1024;
pub const stack_size: usize = if (@hasDecl(root, "stack_size_std_io_OutStream"))
root.stack_size_std_io_OutStream
else
default_stack_size;
/// TODO this is not integrated with evented I/O yet.
/// https://github.com/ziglang/zig/issues/3557
pub fn OutStream(comptime WriteError: type) type {
return struct {
const Self = @This();
pub const Error = WriteError;
// TODO https://github.com/ziglang/zig/issues/3557
pub const WriteFn = if (std.io.is_async and false)
async fn (self: *Self, bytes: []const u8) Error!void
else
fn (self: *Self, bytes: []const u8) Error!void;
writeFn: WriteFn,
pub fn write(self: *Self, bytes: []const u8) Error!void {
// TODO https://github.com/ziglang/zig/issues/3557
if (std.io.is_async and false) {
// Let's not be writing 0xaa in safe modes for upwards of 4 MiB for every stream write.
@setRuntimeSafety(false);
var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
return await @asyncCall(&stack_frame, {}, self.writeFn, self, bytes);
} else {
return self.writeFn(self, bytes);
}
}
pub fn print(self: *Self, comptime format: []const u8, args: ...) Error!void {
return std.fmt.format(self, Error, self.writeFn, format, args);
}
pub fn writeByte(self: *Self, byte: u8) Error!void {
const slice = (*const [1]u8)(&byte)[0..];
return self.writeFn(self, slice);
}
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
const slice = (*const [1]u8)(&byte)[0..];
var i: usize = 0;
while (i < n) : (i += 1) {
try self.writeFn(self, slice);
}
}
/// Write a native-endian integer.
pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntNative(T, &bytes, value);
return self.writeFn(self, bytes);
}
/// Write a foreign-endian integer.
pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntForeign(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntLittle(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntBig(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeInt(T, &bytes, value, endian);
return self.writeFn(self, bytes);
}
};
}