
use io
use utils

+ fn stream(path: String, read: bool, write: bool, append: bool (false), auto_create: bool (false)) FileStream !err_open {
    let fd = open_extend(path, write, append, auto_create) ! throw err_open
    return FileStream{ path: path, fd: fd, can_read: read, can_write: write }
}

+ class FileStream {
    ~ path: String
    - fd: FD 
    - can_read: bool
    - can_write: bool
    ~ reading: bool (true)

    + fn read(bytes: uint (10240), output: utils:ByteBuffer) bool !read_err {
        if !this.can_read || !this.reading : return false

        output.minimum_free_space(bytes)
        let rcount = io:read(this.fd, output.data.offset(output.length), bytes) ! throw read_err
        output.length += rcount

        if rcount == 0 : this.close()
        return true
    }

    + fn write_bytes(from: ptr, len: uint) !write_err {
        let rcount : uint = 0
        while len - rcount > 0 {
            rcount += io:write_bytes(this.fd, from + rcount, len - rcount) ! throw write_err
        }
    }

    + fn close() {
        if this.reading {
            this.reading = false
            io:close(this.fd)
        }
    }

    fn gc_free() {
        this.close()
    }
}
