bufio: preserve partial flush progress
This commit is contained in:
@@ -36,6 +36,71 @@ fn closesource() io.stream = {
|
||||
return &closevt;
|
||||
};
|
||||
|
||||
type failstream = struct {
|
||||
vt: io.vtable,
|
||||
out: [16]u8,
|
||||
pos: i32,
|
||||
calls: i32,
|
||||
zero: bool,
|
||||
};
|
||||
|
||||
fn failwrite(s: io.stream, buf: []u8) (size | io.error) = {
|
||||
let f: *failstream = s: *failstream;
|
||||
f.calls += 1;
|
||||
if (f.calls == 2) {
|
||||
if (f.zero) { return 0: size; };
|
||||
let nm: nomem;
|
||||
let e: io.error = nm;
|
||||
return e;
|
||||
};
|
||||
let n: i32 = buf.len;
|
||||
if (f.calls == 1 && n > 2) { n = 2; };
|
||||
let i: i32 = 0;
|
||||
for (i < n) {
|
||||
f.out[f.pos + i] = buf[i];
|
||||
i += 1;
|
||||
};
|
||||
f.pos += n;
|
||||
return n: size;
|
||||
};
|
||||
|
||||
fn checkpartialflush(zero: bool) void = {
|
||||
let sink: failstream;
|
||||
sink.vt.writer = (&failwrite): *io.writer;
|
||||
sink.pos = 0;
|
||||
sink.calls = 0;
|
||||
sink.zero = zero;
|
||||
let rb: [1]u8;
|
||||
let wb: [4]u8;
|
||||
let b: bufio.stream = bufio.init(&sink.vt, rb[0:1], wb[0:4]);
|
||||
let src: [4]u8;
|
||||
let _: i32 = sputstr("ABCD", src[0:4], 0);
|
||||
let wr: (size | io.error) = io.write(&b.vt, src[0:4]);
|
||||
match (wr) { case let n: size => {}; case let e: io.error => abort(); };
|
||||
let first: (void | io.error) = bufio.flush(&b);
|
||||
match (first) {
|
||||
case void => abort();
|
||||
case let e: io.error => assert(e is nomem);
|
||||
};
|
||||
assert(sink.pos == 2);
|
||||
assert(b.wend == 2);
|
||||
assert(wb[0] == 'C' && wb[1] == 'D');
|
||||
let second: (void | io.error) = bufio.flush(&b);
|
||||
match (second) { case void => {}; case let e: io.error => abort(); };
|
||||
assert(b.wend == 0);
|
||||
assert(sink.pos == 4);
|
||||
assert(sink.out[0] == 'A' && sink.out[1] == 'B');
|
||||
assert(sink.out[2] == 'C' && sink.out[3] == 'D');
|
||||
};
|
||||
|
||||
@test fn streampartialflusherror() void = {
|
||||
checkpartialflush(false);
|
||||
};
|
||||
|
||||
@test fn streampartialflushzero() void = {
|
||||
checkpartialflush(true);
|
||||
};
|
||||
|
||||
@test fn streamsmallwrite() void = {
|
||||
let raw: [16]u8;
|
||||
let mem: memio.stream = memio.fixed(raw[0:16]);
|
||||
@@ -313,6 +378,24 @@ fn closesource() io.stream = {
|
||||
assert(!(out[3] != 71u8)); // 'G'
|
||||
};
|
||||
|
||||
@test fn streamunreadoverlap() void = {
|
||||
let raw: [1]u8;
|
||||
let mem: memio.stream = memio.fixed(raw[0:0]);
|
||||
let rb: [4]u8;
|
||||
let _: i32 = sputstr("ABCD", rb[0:4], 0);
|
||||
let wb: [1]u8;
|
||||
let b: bufio.stream = bufio.init(&mem.vt, rb[0:4], wb[0:1]);
|
||||
bufio.unread(&b, rb[0:3]);
|
||||
let out: [3]u8;
|
||||
let r: (size | io.eof | io.error) = io.read(&b.vt, out[0:3]);
|
||||
match (r) {
|
||||
case let n: size => assert(n: i32 == 3);
|
||||
case io.eof => abort();
|
||||
case let e: io.error => abort();
|
||||
};
|
||||
assert(out[0] == 'A' && out[1] == 'B' && out[2] == 'C');
|
||||
};
|
||||
|
||||
@test fn streamscannerunread() void = {
|
||||
let raw: [16]u8;
|
||||
let n: i32 = sputstr("hello\n", raw[0:16], 0);
|
||||
|
||||
Reference in New Issue
Block a user