1const std = @import("std");
2const nio = @import("./nio.zig");
3const builtin = @import("builtin");
4const extras = @import("extras");
5const sys_linux = @import("sys-linux");
6
7const sys = switch (builtin.target.os.tag) {
8 .linux => sys_linux,
9 .freebsd => @import("sys-freebsd"),
10 .netbsd => @import("sys-netbsd"),
11 .openbsd => @import("sys-openbsd"),
12 else => unreachable,
13};
14
15pub fn BufferedWriter(comptime buffer_size: usize, comptime WriterType: type) type {
16 return struct {
17 unbuffered_writer: WriterType,
18 buf: [buffer_size]u8,
19 end: usize,
20
21 const Self = @This();
22
23 pub fn init(unbuffered_writer: WriterType) Self {
24 return .{
25 .unbuffered_writer = unbuffered_writer,
26 .buf = undefined,
27 .end = 0,
28 };
29 }
30
31 const W = nio.Writable(@This(), ._var);
32 pub const writeAll = W.writeAll;
33 pub const writevAll = W.writevAll;
34 pub const writeByteNTimes = W.writeByteNTimes;
35 pub const writeNTimes = W.writeNTimes;
36 pub const writeInt = W.writeInt;
37 pub const writeStruct = W.writeStruct;
38 pub const writeIntPretty = W.writeIntPretty;
39 pub const print = W.print;
40
41 pub const WriteError = extras.Pointee(WriterType).WriteError;
42 pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
43 if (self.end + bytes.len > self.buf.len) {
44 try self.flush();
45 if (bytes.len > self.buf.len) return self.unbuffered_writer.write(bytes);
46 }
47 const new_end = self.end + bytes.len;
48 @memcpy(self.buf[self.end..new_end], bytes);
49 self.end = new_end;
50 return bytes.len;
51 }
52 pub fn writev(self: *Self, iovec: []const sys.struct_iovec) WriteError!usize {
53 var total: usize = 0;
54 for (iovec) |vec| {
55 const len = try write(self, vec.base[0..vec.len]);
56 total += len;
57 if (len != vec.len) break;
58 }
59 return total;
60 }
61
62 pub fn anyWritable(self: *Self) nio.AnyWritable {
63 const S = struct {
64 fn write(s: *allowzero anyopaque, buffer: []const u8) anyerror!usize {
65 const bw: *Self = @ptrCast(@alignCast(s));
66 return bw.write(buffer);
67 }
68 };
69 return .{
70 .vtable = &.{ .write = S.write },
71 .state = @ptrCast(self),
72 };
73 }
74
75 pub fn flush(self: *Self) !void {
76 try self.unbuffered_writer.writeAll(self.buf[0..self.end]);
77 self.end = 0;
78 }
79 };
80}