authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-02-04 18:11:56 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-02-04 18:11:56 -08:00
log9cbad3ea650abdab1215f1e44819c41b1dc99275
treeeab0441e935b453fec4c627ff915bc49d8e54782
parenta9594e18817f09de3aa7ef9ccaa6e8a48a8e41b5

add BufferedReader


2 files changed, 63 insertions(+), 0 deletions(-)

buffered_reader.zig created+61
......@@ -0,0 +1,61 @@
1const std = @import("std");
2const nio = @import("./nio.zig");
3
4pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) type {
5 return struct {
6 unbuffered_reader: ReaderType,
7 buf: [buffer_size]u8,
8 start: usize,
9 end: usize,
10
11 const Self = @This();
12
13 pub fn init(unbuffered_reader: ReaderType) Self {
14 return .{
15 .unbuffered_reader = unbuffered_reader,
16 .buf = undefined,
17 .start = 0,
18 .end = 0,
19 };
20 }
21
22 pub const ReadError = ReaderType.ReadError;
23 pub usingnamespace nio.Readable(@This(), ._var);
24 pub fn read(self: *Self, dest: []u8) ReadError!usize {
25 // First try reading from the already buffered data onto the destination.
26 const current = self.buf[self.start..self.end];
27 if (current.len != 0) {
28 const to_transfer = @min(current.len, dest.len);
29 @memcpy(dest[0..to_transfer], current[0..to_transfer]);
30 self.start += to_transfer;
31 return to_transfer;
32 }
33
34 // If dest is large, read from the unbuffered reader directly into the destination.
35 if (dest.len >= buffer_size) {
36 return self.unbuffered_reader.read(dest);
37 }
38
39 // If dest is small, read from the unbuffered reader into our own internal buffer,
40 // and then transfer to destination.
41 self.end = try self.unbuffered_reader.read(&self.buf);
42 const to_transfer = @min(self.end, dest.len);
43 @memcpy(dest[0..to_transfer], self.buf[0..to_transfer]);
44 self.start = to_transfer;
45 return to_transfer;
46 }
47
48 pub fn anyReadable(self: *Self) nio.AnyReadable {
49 const S = struct {
50 fn read(s: *allowzero anyopaque, buffer: []u8) anyerror!usize {
51 const br: *Self = @ptrCast(@alignCast(s));
52 return br.read(buffer);
53 }
54 };
55 return .{
56 .vtable = &.{ .read = S.read },
57 .state = @ptrCast(self),
58 };
59 }
60 };
61}
nio.zig+2
......@@ -139,3 +139,5 @@ pub const AnyReadable = @import("./AnyReadable.zig");
139139pub const AnyWritable = @import("./AnyWritable.zig");
140140
141141pub const FixedBufferStream = @import("./fixed_buffer_stream.zig").FixedBufferStream;
142
143pub const BufferedReader = @import("./buffered_reader.zig").BufferedReader;