1const std = @import("std");
2const builtin = @import("builtin");
3const sys_linux = @import("sys-linux");
4
5const sys = switch (builtin.target.os.tag) {
6 .linux => sys_linux,
7 .freebsd => @import("sys-freebsd"),
8 .netbsd => @import("sys-netbsd"),
9 .openbsd => @import("sys-openbsd"),
10 else => unreachable,
11};
12
13const nio = @import("./nio.zig");
14const AnyWritable = @This();
15
16vtable: *const struct {
17 write: *const fn (*allowzero anyopaque, []const u8) anyerror!usize,
18},
19state: *allowzero anyopaque,
20
21const W = nio.Writable(@This(), ._const);
22pub const writeAll = W.writeAll;
23pub const writevAll = W.writevAll;
24pub const writeByteNTimes = W.writeByteNTimes;
25pub const writeNTimes = W.writeNTimes;
26pub const writeInt = W.writeInt;
27pub const writeStruct = W.writeStruct;
28pub const writeIntPretty = W.writeIntPretty;
29pub const print = W.print;
30
31pub const WriteError = anyerror;
32pub fn write(r: AnyWritable, buffer: []const u8) !usize {
33 return r.vtable.write(r.state, buffer);
34}
35pub fn writev(w: AnyWritable, iovec: []const sys.struct_iovec) WriteError!usize {
36 var total: usize = 0;
37 for (iovec) |vec| {
38 const len = try write(w, vec.base[0..vec.len]);
39 total += len;
40 if (len != vec.len) break;
41 }
42 return total;
43}
44pub fn anyWritable(r: AnyWritable) AnyWritable {
45 return r;
46}
47
48pub fn fromStd(writer_ptr: *std.Io.Writer) AnyWritable {
49 const S = struct {
50 fn _write(s: *allowzero anyopaque, buffer: []const u8) !usize {
51 const r: @TypeOf(writer_ptr) = @ptrCast(@alignCast(s));
52 return r.write(buffer);
53 }
54 };
55 return .{
56 .vtable = &.{ .write = &S._write },
57 .state = @ptrCast(@constCast(writer_ptr)),
58 };
59}
60
61pub fn toStd(r: AnyWritable, buf: []u8) StdWriter {
62 const S = struct {
63 fn drain(sw: *std.Io.Writer, data: []const []const u8, splat: usize) error{WriteFailed}!usize {
64 const w: *StdWriter = @alignCast(@fieldParentPtr("sw", sw));
65 while (true) {
66 const rem = w.sw.buffered();
67 const n = w.aw.write(rem) catch return error.WriteFailed;
68 const l = w.sw.consume(n);
69 if (l == 0) break;
70 }
71 var n: usize = 0;
72 const slice = data[0 .. data.len - 1];
73 w.aw.writevAll(slice) catch return error.WriteFailed;
74 for (slice) |x| n += x.len;
75 const pattern = data[slice.len];
76 w.aw.writeNTimes(pattern, splat) catch return error.WriteFailed;
77 n += pattern.len * splat;
78 return n;
79 }
80 fn flush(sw: *std.Io.Writer) error{WriteFailed}!void {
81 const w: *StdWriter = @alignCast(@fieldParentPtr("sw", sw));
82 return w.aw.writeAll(w.sw.buffered()) catch return error.WriteFailed;
83 }
84 };
85 return .{
86 .aw = r,
87 .sw = .{
88 .vtable = &.{
89 .drain = S.drain,
90 .flush = S.flush,
91 },
92 .buffer = buf,
93 },
94 };
95}
96const StdWriter = struct {
97 aw: AnyWritable,
98 sw: std.Io.Writer,
99};