module io struct Buf { pub: bytes []byte mut: i int } fn (mut b Buf) read(mut buf []byte) ?int { if !(b.i < b.bytes.len) { return none } n := copy(buf, b.bytes[b.i..]) b.i += n return n } fn test_read_all() { buf := Buf{ bytes: '123'.repeat(10).bytes() } res := read_all(reader: buf) or { assert false ''.bytes() } assert res == '123'.repeat(10).bytes() } fn test_read_all_huge() { buf := Buf{ bytes: '123'.repeat(100000).bytes() } res := read_all(reader: buf) or { assert false ''.bytes() } assert res == '123'.repeat(100000).bytes() } struct StringReader { text string mut: place int } fn (mut s StringReader) read(mut buf []byte) ?int { if s.place >= s.text.len { return none } read := copy(buf, s.text[s.place..].bytes()) s.place += read return read } const ( newline_count = 100000 ) fn test_stringreader() { text := '12345\n'.repeat(newline_count) mut s := StringReader{ text: text } mut r := new_buffered_reader({ reader: make_reader(s) }) for i := 0; true; i++ { if _ := r.read_line() { } else { assert i == newline_count break } } if _ := r.read_line() { assert false } leftover := read_all(reader: r) or { assert false panic('bad') } if leftover.len > 0 { assert false } } fn test_stringreader2() { text := '12345\r\n'.repeat(newline_count) mut s := StringReader{ text: text } mut r := new_buffered_reader({ reader: make_reader(s) }) for i := 0; true; i++ { if _ := r.read_line() { } else { assert i == newline_count break } } if _ := r.read_line() { assert false } leftover := read_all(reader: io.make_reader(r)) or { assert false panic('bad') } if leftover.len > 0 { assert false } } fn test_leftover() { text := 'This is a test\r\nNice try!' mut s := StringReader{ text: text } mut r := new_buffered_reader({ reader: make_reader(s) }) _ := r.read_line() or { assert false panic('bad') } line2 := r.read_line() or { assert false panic('bad') } assert line2 == 'Nice try!' if _ := r.read_line() { assert false panic('bad') } assert r.end_of_stream() }