io
The io module provides input and output (I/O) functionality for Hare programs,
such as reading from or writing to files. The I/O module is not generally
responsible for provisioning the I/O objects themselves; see modules like os
and net for this purpose.
I/O operations such as read or write accept an I/O handle, handle,
to specify the object of the I/O operation. This type is a tagged union of
file and *stream. Most programmers should prefer to use handle
unless they specifically require the special semantics of one of its subtypes.
The file type provides access to an object, usually a file descriptor, which
is provided by the host operating system. It represents objects such as a file
on disk, an open network connection, and so on. The use of file is generally
required when working with host I/O, such as with unix::poll.
The stream type is an abstraction that allows Hare programs to implement
their own I/O objects by providing implementations of read, write, and
other functions, for an handle. Several standard library modules offer
implementations of stream for one reason or another, such as bufio.
Additionally, the io module provides some useful general-purpose I/O streams,
such as tee.
Index
Types
type EOF;
type closer;
type copier;
type file;
type handle;
type mflags;
type mode;
type off;
type prot;
type reader;
type seeker;
type stream;
type vtable;
type whence;
type writer;
type limitstream;
type teestream;
type vector;
Errors
type error;
type underread;
Globals
let empty: *stream;
let zero: *stream;
Functions
fn close(handle) (void | error);
fn copy(handle, handle) (error | size);
fn drain(handle) ([]u8 | error);
fn fdopen(int) file;
fn limitreader(handle, size) limitstream;
fn limitwriter(handle, size) limitstream;
fn mkvector([]u8) vector;
fn mmap(nullable *void, size, prot, mflags, file, size) (*void | errors::error);
fn munmap(*void, size) (void | errors::error);
fn read(handle, []u8) (size | EOF | error);
fn readall(handle, []u8) (size | EOF | error);
fn readitem(handle, *void, size) (size | error);
fn readitems(handle, []void, size) (size | error);
fn readv(file, vector...) (size | EOF | error);
fn seek(handle, off, whence) (off | error);
fn strerror(error) str;
fn tee(handle, handle) teestream;
fn tell(handle) (off | error);
fn write(handle, const []u8) (size | error);
fn writeall(handle, []u8) (size | error);
fn writeitem(handle, *const void, size) (size | error);
fn writeitems(handle, []const void, size) (size | error);
fn writev(file, vector...) (size | error);
Types
type EOF
type EOF = void;
Indicates an end-of-file condition.
type closer
type closer = fn(s: *stream) (void | error);
The interface for a stream which can be closed. This function should close
and free any underlying resources, and cannot be used again.
type copier
type copier = fn(to: *stream, from: *stream) (size | error);
The interface for a stream which has first-class support for copying data
from another stream. Often this only works if the second stream is of the
same underlying stream type. This is optional, copy still works even with
a stream which does not implement this (it falls back to calling read and
write in a loop).
Returns the number of bytes copied, or an error if one occured. Do not close
either stream. If the operation is unsupported for this particular pair of
streams, return errors::unsupported to have copy proceed with its
fallback implementation.
type file
type file = int;
This is an opaque type which encloses an OS-level file handle resource. It
can be used as a handle in most situations, but there are some APIs which
require a file with some OS-level handle backing it - this type is used
for such APIs.
On Linux, file is a file descriptor.
type handle
type handle = (file | *stream);
An I/O handle is a resource which I/O operations may be performed on. It is
either a stream, which is a userspace I/O abstraction, or a file,
which is backed by a resource on the host OS, such as a file descriptor.
type mflags
type mflags = enum uint {
SHARED = rt::MAP_SHARED,
PRIVATE = rt::MAP_PRIVATE,
SHARED_VALIDATE = rt::MAP_SHARED_VALIDATE,
FIXED = rt::MAP_FIXED,
ANON = rt::MAP_ANON,
NORESERVE = rt::MAP_NORESERVE,
GROWSDOWN = rt::MAP_GROWSDOWN,
DENYWRITE = rt::MAP_DENYWRITE,
EXECUTABLE = rt::MAP_EXECUTABLE,
LOCKED = rt::MAP_LOCKED,
POPULATE = rt::MAP_POPULATE,
NONBLOCK = rt::MAP_NONBLOCK,
STACK = rt::MAP_STACK,
HUGETLB = rt::MAP_HUGETLB,
SYNC = rt::MAP_SYNC,
FIXED_NOREPLACE = rt::MAP_FIXED_NOREPLACE,
FILE = rt::MAP_FILE,
HUGE_SHIFT = rt::MAP_HUGE_SHIFT,
HUGE_MASK = rt::MAP_HUGE_MASK,
HUGE_64KB = rt::MAP_HUGE_64KB,
HUGE_512KB = rt::MAP_HUGE_512KB,
HUGE_1MB = rt::MAP_HUGE_1MB,
HUGE_2MB = rt::MAP_HUGE_2MB,
HUGE_8MB = rt::MAP_HUGE_8MB,
HUGE_16MB = rt::MAP_HUGE_16MB,
HUGE_32MB = rt::MAP_HUGE_32MB,
HUGE_256MB = rt::MAP_HUGE_256MB,
HUGE_512MB = rt::MAP_HUGE_512MB,
HUGE_1GB = rt::MAP_HUGE_1GB,
HUGE_2GB = rt::MAP_HUGE_2GB,
HUGE_16GB = rt::MAP_HUGE_16GB,
};
Values for the mmap flags parameter. Only the SHARED, PRIVATE, and FIXED
values are portable.
type mode
type mode = enum u8 {
NONE = 0,
READ = 1 << 0,
WRITE = 1 << 1,
RDWR = READ | WRITE,
};
Used to indicate if a stream should be used for reading, or writing, or both.
type off
type off = i64;
An offset for a handle.
type prot
type prot = enum uint {
NONE = rt::PROT_NONE,
READ = rt::PROT_READ,
WRITE = rt::PROT_WRITE,
EXEC = rt::PROT_EXEC,
GROWSDOWN = rt::PROT_GROWSDOWN,
GROWSUP = rt::PROT_GROWSUP,
};
Values for the mmap prot parameter. Only the EXEC, READ, WRITE, and NONE
values are portable.
type reader
type reader = fn(s: *stream, buf: []u8) (size | EOF | error);
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.
type seeker
type seeker = fn(s: *stream, off: off, w: whence) (off | error);
The interface for a stream which can be seeked. Sets the offset for the next
read or write to offset, interpreted according to whence:
whence::SET means relative to the start of the file,
whence::CUR means relative to the current offset, and
whence::END means relative to the end.
Returns the new offset relative to the start or an error.
type stream
type stream = *vtable;
A stream is a pointer to a vtable which allows for user-defined I/O
abstractions to implement some subset of read, write, seek, close, and other
I/O functionality in userspace. Embed to create a custom stream type:
export type my_stream = struct {
vtable: io::stream,
fd: int,
};
const my_vtable: io::vtable = io::vtable {
reader = &my_stream_read,
writer = &my_stream_write,
closer = null,
...
};
export fn open(path: str) my_stream = {
let fd = // ...
return my_stream {
vtable = &my_vtable,
fd = fd,
...
});
};
let stream = open("example");
io::read(&stream, buf)!;
type vtable
type vtable = struct {
reader: nullable *reader,
writer: nullable *writer,
closer: nullable *closer,
seeker: nullable *seeker,
copier: nullable *copier,
};
The vtable type defines a set of virtual functions for a stream.
type whence
type whence = enum {
SET = 0,
CUR = 1,
END = 2,
};
From "whence" a seek operation should occur.
type writer
type writer = fn(s: *stream, buf: const []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.
type limitstream
Show undocumented member
type limitstream = struct {
vtable: stream,
source: handle,
limit: size,
};
type teestream
Show undocumented member
type teestream = struct {
vtable: stream,
source: handle,
sink: handle,
};
type vector
Show undocumented member
type vector = rt::iovec;
Errors
type error
type error = !(...errors::error | underread);
Any error which may be returned from an I/O function.
type underread
type underread = !size;
Returned by readitem, readitems and readall if the I/O handle
returned EOF prior to completely reading an item. Stores the amount that
was succesfully read.
Globals
let empty
const empty: *stream;
A stream which always reads EOF and discards any writes.
let zero
const zero: *stream;
A stream which always reads zeroes and discards any writes.
Functions
fn close
fn close(h: handle) (void | error);
Closes a handle. No further operations against this handle are permitted
after calling this function. Closing a file handle can fail only under
certain conditions (for example, closing a file twice, or an interrupted
syscall). However, the user should not attempt to close the file again on
failure - at best the user should print a diagnostic message and move on. See
close(2) for details.
fn copy
fn copy(dest: handle, src: handle) (error | size);
Copies data from one handle into another. Note that this function will never
return if the source handle is infinite.
fn drain
fn drain(in: handle) ([]u8 | error);
Reads an entire stream into a []u8. The caller must free the return value.
fn fdopen
fn fdopen(fd: int) file;
Opens a Unix file descriptor as a file. This is a low-level interface, to
open files most programs will use something like os::open. This function
is not portable.
fn limitreader
fn limitreader(source: handle, limit: size) limitstream;
Create an overlay stream that only allows a limited amount of bytes to be
read from the underlying stream. This stream does not need to be closed, and
closing it does not close the underlying stream. Reading any data beyond the
given limit causes the reader to return EOF.
fn limitwriter
fn limitwriter(source: handle, limit: size) limitstream;
Create an overlay stream that only allows a limited amount of bytes to be
written to the underlying stream. This stream does not need to be closed, and
closing it does not close the underlying stream. Writing beyond the given
limit causes the writer to return short writes (as few as zero bytes).
fn mkvector
fn mkvector(buf: []u8) vector;
Creates a vector for use with writev and readv.
fn mmap
fn mmap(
addr: nullable *void,
length: size,
prot: prot,
flags: mflags,
fd: file,
offs: size,
) (*void | errors::error);
Performs the mmap syscall. Consult your system for documentation on this
function.
fn munmap
fn munmap(addr: *void, length: size) (void | errors::error);
Unmaps memory previously mapped with mmap.
fn read
fn read(h: handle, buf: []u8) (size | EOF | error);
Reads up to len(buf) bytes from a handle into the given buffer, returning
the number of bytes read.
fn readall
fn readall(in: handle, buf: []u8) (size | EOF | error);
Reads an entire buffer, perhaps issuing several read calls to do so. If
EOF is immediately encountered, it is returned; if EOF is encountered
partway through reading the buffer, underread is returned.
fn readitem
fn readitem(in: handle, item: *void, itemsz: size) (size | error);
Reads an entire "item", i.e. one Hare object, from an I/O handle. This
function may use multiple reads, but if EOF is encountered before the
entire object is read, an underread error is returned. Otherwise, the
return value is the total number of bytes read (which shall be equal to
itemsz).
fn readitems
fn readitems(in: handle, items: []void, itemsz: size) (size | error);
Reads several "items", i.e. Hare objects, from an I/O handle. If EOF is
returned prior to reading all of the items completely, an underread error
is returned. Otherwise, the return value is the number of items read.
fn readv
fn readv(fd: file, vectors: vector...) (size | EOF | error);
Performs a vectored read on the given file. A read is performed on each of
the vectors, prepared with mkvector, in order, and the total number of
bytes read is returned.
fn seek
fn seek(h: handle, off: off, w: whence) (off | error);
Sets the offset within a handle.
fn strerror
fn strerror(err: error) str;
Converts an I/O error into a user-friendly string.
fn tee
fn tee(source: handle, sink: handle) teestream;
Creates a reader which copies reads into a sink before forwarding them to the
caller. This stream does not need to be closed, and closing it will not close
the secondary streams.
fn tell
fn tell(h: handle) (off | error);
Returns the current offset within a handle.
fn write
fn write(h: handle, buf: const []u8) (size | error);
Writes up to len(buf) bytes to the handle from the given buffer,
returning the number of bytes written.
fn writeall
fn writeall(out: handle, buf: []u8) (size | error);
Writes an entire buffer, perhaps issuing several write calls to do so.
fn writeitem
fn writeitem(out: handle, item: *const void, itemsz: size) (size | error);
Writes an entire "item", i.e. one Hare object, to an I/O handle. This
function may use multiple writes. The return value is the total number of
bytes written (which shall be equal to itemsz).
fn writeitems
fn writeitems(out: handle, items: []const void, itemsz: size) (size | error);
Writes several "items", i.e. Hare objects, to an I/O handle. If successful,
all items will be written. The return value is the number of items written.
fn writev
fn writev(fd: file, vectors: vector...) (size | error);
Performs a vectored write on the given file. Each of the vectors, prepared
with mkvector, are written to the file in order, and the total number of
bytes written is returned.