io +linux +x86_64

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;

// Undocumented types:
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[link]

type EOF = void;

Indicates an end-of-file condition.

type closer[link]

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[link]

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[link]

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[link]

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[link]

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[link]

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[link]

type off = i64;

An offset for a handle.

type prot[link]

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[link]

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[link]

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[link]

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[link]

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[link]

type whence = enum {
	SET = 0,
	CUR = 1,
	END = 2,

};

From "whence" a seek operation should occur.

type writer[link]

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[link]

Show undocumented member
type limitstream = struct {
	vtable: stream,
	source: handle,
	limit: size,
};

type teestream[link]

Show undocumented member
type teestream = struct {
	vtable: stream,
	source: handle,
	sink: handle,
};

type vector[link]

Show undocumented member
type vector = rt::iovec;

Errors

type error[link]

type error = !(...errors::error | underread);

Any error which may be returned from an I/O function.

type underread[link]

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[link]

const empty: *stream;

A stream which always reads EOF and discards any writes.

let zero[link]

const zero: *stream;

A stream which always reads zeroes and discards any writes.

Functions

fn close[link]

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[link]

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[link]

fn drain(in: handle) ([]u8 | error);

Reads an entire stream into a []u8. The caller must free the return value.

fn fdopen[link]

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[link]

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[link]

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[link]

fn mkvector(buf: []u8) vector;

Creates a vector for use with writev and readv.

fn mmap[link]

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[link]

fn munmap(addr: *void, length: size) (void | errors::error);

Unmaps memory previously mapped with mmap.

fn read[link]

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[link]

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[link]

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[link]

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[link]

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[link]

fn seek(h: handle, off: off, w: whence) (off | error);

Sets the offset within a handle.

fn strerror[link]

fn strerror(err: error) str;

Converts an I/O error into a user-friendly string.

fn tee[link]

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[link]

fn tell(h: handle) (off | error);

Returns the current offset within a handle.

fn write[link]

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[link]

fn writeall(out: handle, buf: []u8) (size | error);

Writes an entire buffer, perhaps issuing several write calls to do so.

fn writeitem[link]

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[link]

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[link]

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.