diff --git a/lib/std/io.zig b/lib/std/io.zig index 7baa383001..018c863bbd 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -196,7 +196,7 @@ test "io.BufferedInStream" { /// Creates a stream which supports 'un-reading' data, so that it can be read again. /// This makes look-ahead style parsing much easier. -pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { +pub fn PeekStream(comptime buffer_type: usize, comptime InStreamError: type) type { return struct { const Self = @This(); pub const Error = InStreamError; @@ -207,55 +207,35 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ // Right now the look-ahead space is statically allocated, but a version with dynamic allocation // is not too difficult to derive from this. - buffer: [buffer_size]u8, - index: usize, - at_end: bool, + const FifoType = std.fifo.LinearFifo(u8, .{ .Static = buffer_size }); + fifo: FifoType, pub fn init(base: *Stream) Self { - return Self{ + return .{ .base = base, - .buffer = undefined, - .index = 0, - .at_end = false, + .fifo = FifoType.init(), .stream = Stream{ .readFn = readFn }, }; } - pub fn putBackByte(self: *Self, byte: u8) void { - self.buffer[self.index] = byte; - self.index += 1; + pub fn putBackByte(self: *Self, byte: u8) !void { + try self.putBack(@ptrCast([*]const u8, &byte)[0..1]); } - pub fn putBack(self: *Self, bytes: []const u8) void { - var pos = bytes.len; - while (pos != 0) { - pos -= 1; - self.putBackByte(bytes[pos]); - } + pub fn putBack(self: *Self, bytes: []const u8) !void { + try self.fifo.unget(bytes); } fn readFn(in_stream: *Stream, dest: []u8) Error!usize { const self = @fieldParentPtr(Self, "stream", in_stream); // copy over anything putBack()'d - var pos: usize = 0; - while (pos < dest.len and self.index != 0) { - dest[pos] = self.buffer[self.index - 1]; - self.index -= 1; - pos += 1; - } - - if (pos == dest.len or self.at_end) { - return pos; - } + var dest_index = self.fifo.read(dest); + if (dest_index == dest.len) return dest_index; // ask the backing stream for more - const left = dest.len - pos; - const read = try self.base.read(dest[pos..]); - assert(read <= left); - - self.at_end = (read < left); - return pos + read; + dest_index += try self.base.read(dest[dest_index..]); + return dest_index; } }; } diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index c4e9a1fc06..b2f8307310 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -97,8 +97,8 @@ test "PeekStream" { var dest: [4]u8 = undefined; - ps.putBackByte(9); - ps.putBackByte(10); + try ps.putBackByte(9); + try ps.putBackByte(10); var read = try ps.stream.read(dest[0..4]); expect(read == 4); @@ -114,8 +114,8 @@ test "PeekStream" { expect(read == 2); expect(mem.eql(u8, dest[0..2], bytes[6..8])); - ps.putBackByte(11); - ps.putBackByte(12); + try ps.putBackByte(11); + try ps.putBackByte(12); read = try ps.stream.read(dest[0..4]); expect(read == 2);