authorgravatar for sjdh@sjdh.ussjdh02 <sjdh@sjdh.us> 2019-01-25 03:02:06+00:00
committergravatar for sjdh@sjdh.ussjdh02 <sjdh@sjdh.us> 2019-02-16 21:19:49-06:00
logfd61a084e49037bc53dd5150bd27e28758b7aecf
treed96661dfe18dedd9947228cb72c9347c33bd9ea0
parentc3c92ca8b1ada4faed14a9770ab7ed6536edaa15

fix BufferedInStream not reading delayed input


1 files changed, 56 insertions(+), 14 deletions(-)

std/io.zig+56-14
......@@ -343,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
343343 const amt_buffered = self.end_index - self.start_index;
344344 if (amt_buffered == 0) {
345345 assert(self.end_index <= buffer_size);
346 if (self.end_index == buffer_size) {
347 // we can read more data from the unbuffered stream
348 if (dest_space < buffer_size) {
349 self.start_index = 0;
350 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
351 } else {
352 // asking for so much data that buffering is actually less efficient.
353 // forward the request directly to the unbuffered stream
354 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
355 return dest_index + amt_read;
356 }
357 } else {
358 // reading from the unbuffered stream returned less than we asked for
359 // so we cannot read any more data.
346 // Make sure the last read actually gave us some data
347 if (self.end_index == 0) {
348 // reading from the unbuffered stream returned nothing
349 // so we have nothing left to read.
360350 return dest_index;
361351 }
352 // we can read more data from the unbuffered stream
353 if (dest_space < buffer_size) {
354 self.start_index = 0;
355 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
356 } else {
357 // asking for so much data that buffering is actually less efficient.
358 // forward the request directly to the unbuffered stream
359 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
360 return dest_index + amt_read;
361 }
362362 }
363
363364 const copy_amount = math.min(dest_space, amt_buffered);
364365 const copy_end_index = self.start_index + copy_amount;
365366 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
......@@ -370,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
370371 };
371372}
372373
374test "io.BufferedInStream" {
375 const OneByteReadInStream = struct {
376 const Error = error{NoError};
377 const Stream = InStream(Error);
378
379 stream: Stream,
380 str: []const u8,
381 curr: usize,
382
383 fn init(str: []const u8) @This() {
384 return @This(){
385 .stream = Stream{ .readFn = readFn },
386 .str = str,
387 .curr = 0,
388 };
389 }
390
391 fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
392 const self = @fieldParentPtr(@This(), "stream", in_stream);
393 if (self.str.len <= self.curr or dest.len == 0)
394 return 0;
395
396 dest[0] = self.str[self.curr];
397 self.curr += 1;
398 return 1;
399 }
400 };
401
402 var buf: [100]u8 = undefined;
403 const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
404
405 const str = "This is a test";
406 var one_byte_stream = OneByteReadInStream.init(str);
407 var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream);
408 const stream = &buf_in_stream.stream;
409
410 const res = try stream.readAllAlloc(allocator, str.len + 1);
411 debug.assertOrPanic(mem.eql(u8, str, res));
412}
413
373414/// Creates a stream which supports 'un-reading' data, so that it can be read again.
374415/// This makes look-ahead style parsing much easier.
375416pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
......@@ -1411,3 +1452,4 @@ test "import io tests" {
14111452 _ = @import("io_test.zig");
14121453 }
14131454}
1455