diff --git a/lib/std/io.zig b/lib/std/io.zig index 16bfffdcad..7baa383001 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -121,76 +121,37 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) unbuffered_in_stream: *Stream, - buffer: [buffer_size]u8, - start_index: usize, - end_index: usize, + const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size }); + fifo: FifoType, pub fn init(unbuffered_in_stream: *Stream) Self { return Self{ .unbuffered_in_stream = unbuffered_in_stream, - .buffer = undefined, - - // Initialize these two fields to buffer_size so that - // in `readFn` we treat the state as being able to read - // more from the unbuffered stream. If we set them to 0 - // and 0, the code would think we already hit EOF. - .start_index = buffer_size, - .end_index = buffer_size, - + .fifo = FifoType.init(), .stream = Stream{ .readFn = readFn }, }; } fn readFn(in_stream: *Stream, dest: []u8) !usize { const self = @fieldParentPtr(Self, "stream", in_stream); - - // Hot path for one byte reads - if (dest.len == 1 and self.end_index > self.start_index) { - dest[0] = self.buffer[self.start_index]; - self.start_index += 1; - return 1; - } - var dest_index: usize = 0; - while (true) { - const dest_space = dest.len - dest_index; - if (dest_space == 0) { - return dest_index; - } - const amt_buffered = self.end_index - self.start_index; - if (amt_buffered == 0) { - assert(self.end_index <= buffer_size); - // Make sure the last read actually gave us some data - if (self.end_index == 0) { + while (dest_index < dest.len) { + const written = self.fifo.read(dest[dest_index..]); + if (written == 0) { + // fifo empty, fill it + const writable = self.fifo.writableSlice(0); + assert(writable.len > 0); + const n = try self.unbuffered_in_stream.read(writable); + if (n == 0) { // reading from the unbuffered stream returned nothing // so we have nothing left to read. return dest_index; } - // we can read more data from the unbuffered stream - if (dest_space < buffer_size) { - self.start_index = 0; - self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); - - // Shortcut - if (self.end_index >= dest_space) { - mem.copy(u8, dest[dest_index..], self.buffer[0..dest_space]); - self.start_index = dest_space; - return dest.len; - } - } else { - // asking for so much data that buffering is actually less efficient. - // forward the request directly to the unbuffered stream - const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); - return dest_index + amt_read; - } + self.fifo.update(n); } - - const copy_amount = math.min(dest_space, amt_buffered); - const copy_end_index = self.start_index + copy_amount; - mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]); - self.start_index = copy_end_index; - dest_index += copy_amount; + dest_index += written; } + return dest.len; } }; }