2020-11-15 23:54:47 +03:00
|
|
|
module io
|
|
|
|
|
2022-08-08 02:33:25 +03:00
|
|
|
/// Eof error means that we reach the end of the stream.
|
|
|
|
pub struct Eof {
|
|
|
|
Error
|
|
|
|
}
|
|
|
|
|
|
|
|
// NotExpected is a generic error that means that we receave a not expecte error.
|
|
|
|
pub struct NotExpected {
|
|
|
|
cause string
|
|
|
|
code int
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (err NotExpected) msg() string {
|
|
|
|
return err.cause
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (err NotExpected) code() int {
|
|
|
|
return err.code
|
|
|
|
}
|
|
|
|
|
2020-11-15 23:54:47 +03:00
|
|
|
// Reader represents a stream of data that can be read
|
|
|
|
pub interface Reader {
|
|
|
|
// read reads up to buf.len bytes and places
|
|
|
|
// them into buf.
|
2020-12-16 20:22:26 +03:00
|
|
|
// A type that implements this should return
|
2022-08-08 02:33:25 +03:00
|
|
|
// `io.Eof` on end of stream (EOF) instead of just returning 0
|
2021-10-11 15:41:31 +03:00
|
|
|
mut:
|
2022-08-08 02:33:25 +03:00
|
|
|
read(mut buf []u8) !int
|
2020-11-15 23:54:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
read_all_len = 10 * 1024
|
|
|
|
read_all_grow_len = 1024
|
|
|
|
)
|
|
|
|
|
2020-12-16 20:22:26 +03:00
|
|
|
// ReadAllConfig allows options to be passed for the behaviour
|
|
|
|
// of read_all
|
|
|
|
pub struct ReadAllConfig {
|
|
|
|
read_to_end_of_stream bool
|
2021-10-11 15:41:31 +03:00
|
|
|
mut:
|
|
|
|
reader Reader
|
2020-12-16 20:22:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// read_all reads all bytes from a reader until either a 0 length read
|
|
|
|
// or if read_to_end_of_stream is true then the end of the stream (`none`)
|
2022-10-16 09:28:57 +03:00
|
|
|
pub fn read_all(config ReadAllConfig) ![]u8 {
|
2021-10-11 15:41:31 +03:00
|
|
|
mut r := config.reader
|
2020-12-16 20:22:26 +03:00
|
|
|
read_till_eof := config.read_to_end_of_stream
|
|
|
|
|
2022-04-15 15:35:35 +03:00
|
|
|
mut b := []u8{len: io.read_all_len}
|
2020-12-16 20:22:26 +03:00
|
|
|
mut read := 0
|
|
|
|
for {
|
2021-03-24 13:39:09 +03:00
|
|
|
new_read := r.read(mut b[read..]) or { break }
|
2020-12-16 20:22:26 +03:00
|
|
|
read += new_read
|
|
|
|
if !read_till_eof && read == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if b.len == read {
|
2021-03-24 13:39:09 +03:00
|
|
|
unsafe { b.grow_len(io.read_all_grow_len) }
|
2020-12-16 20:22:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return b[..read]
|
|
|
|
}
|
|
|
|
|
|
|
|
// read_any reads any available bytes from a reader
|
|
|
|
// (until the reader returns a read of 0 length)
|
2022-10-16 09:28:57 +03:00
|
|
|
pub fn read_any(mut r Reader) ![]u8 {
|
2022-04-15 15:35:35 +03:00
|
|
|
mut b := []u8{len: io.read_all_len}
|
2020-11-15 23:54:47 +03:00
|
|
|
mut read := 0
|
|
|
|
for {
|
2022-10-16 09:28:57 +03:00
|
|
|
new_read := r.read(mut b[read..]) or { return error('none') }
|
2020-11-15 23:54:47 +03:00
|
|
|
read += new_read
|
|
|
|
if new_read == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if b.len == read {
|
2021-03-24 13:39:09 +03:00
|
|
|
unsafe { b.grow_len(io.read_all_grow_len) }
|
2020-11-15 23:54:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return b[..read]
|
|
|
|
}
|
|
|
|
|
|
|
|
// RandomReader represents a stream of data that can be read from at a random location
|
2021-10-18 10:51:36 +03:00
|
|
|
pub interface RandomReader {
|
2022-10-16 09:28:57 +03:00
|
|
|
read_from(pos u64, mut buf []u8) !int
|
2020-11-15 23:54:47 +03:00
|
|
|
}
|