hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 3b4410e5e63327b941e2fc0e3a4339ca75009b16
parent 6b851eaed490274d17c5cd7eb375a8bd064fad7f
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 31 Jan 2021 11:32:41 -0500

io: add initial stream abstraction

Diffstat:
Aio/stream.ha | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Aio/types.ha | 39+++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/io/stream.ha b/io/stream.ha @@ -0,0 +1,53 @@ +// A stream of bytes which supports some subset of read, write, close, or seek +// operations. To create a custom stream, embed this type as the first member of +// a struct with user-specific data and fill out these fields as appropriate. +// +// type my_stream = struct { +// io::stream, +// fd: int, +// }; +// +// fn open(path: str) *io::stream = { +// let fd = // ... +// let stream = alloc(*my_stream, my_stream { +// name: strings::dup(path), +// reader: &my_stream_read, +// writer: &my_stream_write, +// closer: &my_stream_close, +// fd: fd, +// ... +// }); +// return &stream.stream; +// }; +export type stream = struct { + name: str, + reader: nullable *reader, + writer: nullable *writer, + closer: nullable *closer, +}; + +// Reads up to len(buf) bytes from the reader into the given buffer, returning +// the number of bytes read. +export fn read(s: *stream, buf: []u8) (size | error) = { + return match (s.reader) { + null => unsupported: error, + r: *reader => r(s, buf), + }; +}; + +// Writes up to len(buf) bytes to the stream from the given buffer, returning +// the number of bytes written. +export fn write(s: *stream, buf: const []u8) (size | error) = { + return match (s.writer) { + null => unsupported: error, + w: *writer => w(s, buf), + }; +}; + +// Closes the stream. +export fn close(s: *stream, buf: []u8) (error | void) = { + return match (s.closer) { + null => unsupported: error, + c: *closer => c(s), + }; +}; diff --git a/io/types.ha b/io/types.ha @@ -0,0 +1,39 @@ +// An error produced by the underlying source. +export type os_error = struct { + string: *fn(data: *void) str, + data: *void, +}; + +// An error indicating that the underlying stream has been closed. +export type closed = void; + +// An error indicating that the requested operation is not supported. +export type unsupported = void; + +// Any error which may be returned from an I/O function. +export type error = (os_error | closed | unsupported); + +// Converts an I/O error into a user-friendly string. +export fn errstr(err: error) str = { + return match (err) { + err: os_error => err.string(err.data), + closed => "This stream has been closed", + unsupported => "The requested operation is not supported", + }; +}; + +// The interface for a stream which can be read from. Reads up to len(buf) +// bytes from the reader into the given buffer, returning the number of bytes +// read or an error. +export type reader = fn(s: *stream, buf: []u8) (size | error); + +// The interface for a stream which can be written to. Writes up to len(buf) +// bytes to the writer from the given buffer, returning the number of bytes +// written or an error. +export type writer = fn(s: *stream, buf: const []u8) (size | error); + +// The interface for a stream which can be closed. This function should close +// the underlying resources and free everything except for the stream pointer +// itself. The other stream functions may be called after close is called; it is +// their responsibility to return [io::closed] in this case. +export type closer = fn(s: *stream) void;