Skip to content

Files

Read, write, inspect, and stream filesystem entries.

Updated View as Markdown

Filesystem operations use IoError and may suspend while the runtime waits for the host filesystem. File and Dir are stateless namespaces; OpenFile is a live host resource.

Whole files

fn read_config(path: string): string ! IoError {
    return File.read(path)?
}

File.read, read_bytes, and read_lines load complete content. write, write_bytes, append, and append_bytes create or update files.

Method Data shape
read(path) UTF-8 string
read_bytes(path) Owned []byte
read_lines(path) Owned []string
write(path, text) Create or replace text
write_bytes(path, bytes) Create or replace binary data
append, append_bytes Add to the end, creating when absent

Use byte methods for protocol data or files whose encoding is not guaranteed. Whole-file methods are convenient but require memory proportional to the content size.

read_bytes_zerocopy sizes one guest buffer and fills it directly, which is useful for large binary files. It obtains metadata first and loops over short reads until the known size or EOF.

Metadata

File.metadata(path) returns size, file/directory/symlink flags, and readable, writable, and executable permissions.

metadata := File.metadata(path)?
if metadata.is_file && metadata.size > MAX_UPLOAD {
    error UploadError.TooLarge { size: metadata.size }
}

DirEntry contains name, full path, and file/directory/symlink flags. Metadata and entries are snapshots: another process can change the filesystem after they are returned. Perform the actual fallible operation instead of treating a prior exists check as a lock.

Lifecycle helpers include copy, move, delete, and delete_if_exists. exists returns false for a missing path and also collapses permission errors; use a fallible operation when that distinction matters.

Open handles

File.open_read and File.create return OpenFile:

file := File.open_read(path)?

mut buffer := List.with_capacity[byte](4096)
mut done := false
for !done {
    count := file.read_into(buffer, 4096)?
    done = count == 0
}

read_into appends up to max bytes and returns the count. Zero means EOF. It does not clear the buffer between calls. write_all consumes a borrowed byte view, writes the complete view, and returns its length.

file := File.create(path)?
written := file.write_all(payload)?

Both methods move data directly between the guest allocation and the host operation. The wrapper reserves space before a read, keeping the buffer stable while the call is suspended.

Handles close automatically through Drop, including during error propagation. Call close() only when the resource must be released before the end of its scope. Do not use a handle after closing it.

Directories

Dir.list returns immediate DirEntry values; Dir.walk traverses recursively. create, create_all, delete, delete_all, copy, move, and exists cover directory lifecycle.

Dir.delete requires an empty directory. Dir.delete_all recursively removes contents and is intentionally destructive; keep its target derived from validated application data rather than an unchecked user string.

Dir.create requires the parent to exist. Dir.create_all creates missing parents. Directory copy is recursive.

Errors

IoError distinguishes missing paths, permissions, existing entries, wrong entry kinds, non-empty directories, disk full, invalid paths, read/write detail, timeouts, and other host failures. Match variants when callers can act on the distinction.

match File.read(path) {
    Ok(text) => parse(text)
    Err(NotFound { path }) => use_default(path)
    Err(PermissionDenied { path }) => report_denied(path)
    Err(error) => return Err(error)
}

The handle-based wrappers currently collapse negative raw host errors into the coarse Other variant. Whole-file host operations can preserve the richer taxonomy.

Capabilities

Host capability policy can deny filesystem operations even when source types check. Configure only required namespaces in the project’s [host] allow-list. Type safety does not grant ambient filesystem authority.

Filesystem paths retain host-platform semantics. Normalize or constrain paths at the application boundary when input must remain within a particular root.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close