From 9cbad3ea650abdab1215f1e44819c41b1dc99275 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Wed, 4 Feb 2026 18:11:56 -0800 Subject: [PATCH] add BufferedReader --- buffered_reader.zig | 61 +++++++++++++++++++++++++++++++++++++++++++++ nio.zig | 2 ++ 2 files changed, 63 insertions(+) create mode 100644 buffered_reader.zig diff --git a/buffered_reader.zig b/buffered_reader.zig new file mode 100644 index 0000000000000000000000000000000000000000..cf346fba5a1b4a41958948276563d2383ca07196 --- /dev/null +++ b/buffered_reader.zig @@ -0,0 +1,61 @@ +const std = @import("std"); +const nio = @import("./nio.zig"); + +pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) type { + return struct { + unbuffered_reader: ReaderType, + buf: [buffer_size]u8, + start: usize, + end: usize, + + const Self = @This(); + + pub fn init(unbuffered_reader: ReaderType) Self { + return .{ + .unbuffered_reader = unbuffered_reader, + .buf = undefined, + .start = 0, + .end = 0, + }; + } + + pub const ReadError = ReaderType.ReadError; + pub usingnamespace nio.Readable(@This(), ._var); + pub fn read(self: *Self, dest: []u8) ReadError!usize { + // First try reading from the already buffered data onto the destination. + const current = self.buf[self.start..self.end]; + if (current.len != 0) { + const to_transfer = @min(current.len, dest.len); + @memcpy(dest[0..to_transfer], current[0..to_transfer]); + self.start += to_transfer; + return to_transfer; + } + + // If dest is large, read from the unbuffered reader directly into the destination. + if (dest.len >= buffer_size) { + return self.unbuffered_reader.read(dest); + } + + // If dest is small, read from the unbuffered reader into our own internal buffer, + // and then transfer to destination. + self.end = try self.unbuffered_reader.read(&self.buf); + const to_transfer = @min(self.end, dest.len); + @memcpy(dest[0..to_transfer], self.buf[0..to_transfer]); + self.start = to_transfer; + return to_transfer; + } + + pub fn anyReadable(self: *Self) nio.AnyReadable { + const S = struct { + fn read(s: *allowzero anyopaque, buffer: []u8) anyerror!usize { + const br: *Self = @ptrCast(@alignCast(s)); + return br.read(buffer); + } + }; + return .{ + .vtable = &.{ .read = S.read }, + .state = @ptrCast(self), + }; + } + }; +} diff --git a/nio.zig b/nio.zig index 1a6e02d3059fcebd422be5c6d62e436187a822ff..b1c891a2855c8f87eb4d9af28faeddc0d3a44010 100644 --- a/nio.zig +++ b/nio.zig @@ -139,3 +139,5 @@ pub const AnyReadable = @import("./AnyReadable.zig"); pub const AnyWritable = @import("./AnyWritable.zig"); pub const FixedBufferStream = @import("./fixed_buffer_stream.zig").FixedBufferStream; + +pub const BufferedReader = @import("./buffered_reader.zig").BufferedReader; -- 2.54.0