| 1 | module io |
| 2 | |
| 3 | // Eof error means that we reach the end of the stream. |
| 4 | pub struct Eof { |
| 5 | Error |
| 6 | } |
| 7 | |
| 8 | // NotExpected is a generic error that means that we receave a not expected error. |
| 9 | pub struct NotExpected { |
| 10 | cause string |
| 11 | code int |
| 12 | } |
| 13 | |
| 14 | fn (err NotExpected) msg() string { |
| 15 | return err.cause |
| 16 | } |
| 17 | |
| 18 | fn (err NotExpected) code() int { |
| 19 | return err.code |
| 20 | } |
| 21 | |
| 22 | // Reader represents a stream of data that can be read. |
| 23 | pub interface Reader { |
| 24 | // read reads up to buf.len bytes and places |
| 25 | // them into buf. |
| 26 | // A type that implements this should return |
| 27 | // `io.Eof` on end of stream (EOF) instead of just returning 0 |
| 28 | mut: |
| 29 | read(mut buf []u8) !int |
| 30 | } |
| 31 | |
| 32 | pub const read_all_len = 10 * 1024 |
| 33 | pub const read_all_grow_len = 1024 |
| 34 | |
| 35 | // ReadAllConfig allows options to be passed for the behaviour |
| 36 | // of read_all. |
| 37 | pub struct ReadAllConfig { |
| 38 | pub: |
| 39 | read_to_end_of_stream bool |
| 40 | reader Reader |
| 41 | } |
| 42 | |
| 43 | // read_all reads all bytes from a reader until either a 0 length read |
| 44 | // or if read_to_end_of_stream is true then the end of the stream (`none`). |
| 45 | pub fn read_all(config ReadAllConfig) ![]u8 { |
| 46 | mut r := config.reader |
| 47 | read_till_eof := config.read_to_end_of_stream |
| 48 | |
| 49 | mut b := []u8{len: read_all_len} |
| 50 | mut read := 0 |
| 51 | for { |
| 52 | new_read := r.read(mut b[read..]) or { break } |
| 53 | if new_read < 0 { |
| 54 | return error('io.read_all: reader returned a negative read count (${new_read})') |
| 55 | } |
| 56 | read += new_read |
| 57 | if !read_till_eof && new_read == 0 { |
| 58 | break |
| 59 | } |
| 60 | if b.len == read { |
| 61 | unsafe { b.grow_len(read_all_grow_len) } |
| 62 | } |
| 63 | } |
| 64 | return b[..read] |
| 65 | } |
| 66 | |
| 67 | // read_any reads any available bytes from a reader |
| 68 | // (until the reader returns a read of 0 length). |
| 69 | pub fn read_any(mut r Reader) ![]u8 { |
| 70 | mut b := []u8{len: read_all_len} |
| 71 | mut read := 0 |
| 72 | for { |
| 73 | new_read := r.read(mut b[read..]) or { return error('none') } |
| 74 | if new_read < 0 { |
| 75 | return error('io.read_any: reader returned a negative read count (${new_read})') |
| 76 | } |
| 77 | read += new_read |
| 78 | if new_read == 0 { |
| 79 | break |
| 80 | } |
| 81 | if b.len == read { |
| 82 | unsafe { b.grow_len(read_all_grow_len) } |
| 83 | } |
| 84 | } |
| 85 | return b[..read] |
| 86 | } |
| 87 | |
| 88 | // RandomReader represents a stream of readable data from at a random location. |
| 89 | pub interface RandomReader { |
| 90 | read_from(pos u64, mut buf []u8) !int |
| 91 | } |
| 92 | |