Skip to content
CryoCryo home
StdlibOverview

The Standard Library

std is written entirely in Cryo and ships with the compiler as a static library plus its sources. Nothing in it is privileged: the same type struct, type trait, and implement declarations available to your code build Array<T>, HashMap<K, V>, and the HTTP server. When a signature here looks like something you could have written, that is because it is.

The library is layered. core sits at the bottom and neither allocates nor performs I/O — it is the vocabulary the language itself is defined against. alloc introduces the heap, collections builds growable containers on top of it, and everything above that is domain-specific: files, sockets, threads, formatting, time.

core          language foundations - no heap, no I/O
  |
alloc         Layout, Allocator, Box, Rc, Arc, Arena, Pool
  |
collections   Array, Str, String, HashMap, HashSet, Pair
  |
io  fmt  fs  net  sync  thread  future  process  time  json  ...

The prelude

A small set of names is imported into every source file automatically. The set is deliberately short — each entry competes for your attention — and most of it is there because the language desugars to it.

ModuleWhat it brings in
core::panicpanic(message, file, line) -> never, plus assert, unreachable, and todo
core::optionOption<T> and its methods
core::resultResult<T, E> and its methods
core::primitivesMethods on the built-in types (i32::max_value, char::is_digit, ...)
core::intrinsicsCompiler intrinsics: memcpy, memset, sizeof, alignof, malloc, free
core::varargsVaArgs, the compiler-assigned type of a function's args... bucket
collections::arrayArray<T>, because T[] desugars to it
core::sliceSlice<T>, which backs for (x in arr) over a fixed-size array
core::opsRange and RangeInclusive, because a..b desugars to Range::new
core::iterIterator, the trait for-in drives its scrutinee through
alloc::boxBox<T>
alloc::rcRc<T>

Everything else is an explicit import. Most notably the print / println / eprint / eprintln family lives in fmt and is not in the prelude:

namespace app;

import std::fmt::display;

function main() -> i32 {
    println("hello");
    return 0;
}

Importing

Standard library paths are rooted at std, and you import the module that owns the item you want:

import std::collections::array;          // the module
import std::collections::{ str, string }; // two modules from one parent
import std::net::http::status as http_status;
import std::fmt::display::*;             // everything public in the module

Each module page below records the exact import path for the types it documents. Importing a parent aggregator (import std::collections;) brings in whatever that directory's _module.cryo marks public. See Modules and Imports for the full rules.

Module directory

ModuleWhat it covers
coreOption, Result, Slice, NonNull, Range, Ordering, and the trait vocabulary the language is defined against
allocLayout, the Allocator trait, Box, Rc, Arc, Arena, Pool
collectionsArray, Str, String, HashMap, HashSet, Pair
fmtDisplay, Debug, Formatter, the print family, heap-free number writers
jsonRFC 8259 value model, parser, and serializer
encodingBase64 and SHA-1
ioRead / Write, the standard streams, buffered adapters, IoError
fsPath, PathBuf, File, directories, metadata
envArguments, environment variables, process exit
processCommand, Child, Stdio, ExitStatus, signals
timeDuration, Instant, SystemTime, sleep
ffiThe C ABI boundary: libc, CStr, CString
sysRaw syscalls, and the Win32 / NT surfaces
mathlibm wrappers, width-generic where it makes sense
randomRng (xoshiro256**) and SecureRng
syncAtomic, Mutex, RwLock, CondVar, Once, Barrier, mpsc channels
threadspawn, JoinHandle, Builder, scoped threads, thread-local storage
futureFuture, Poll, Context, Waker, combinators, block_on
netIP addressing, DNS, TCP, UDP, TLS
net::httpHTTP/1.1 client and server, HTTP/2, WebSocket
testThe built-in unit-test framework

Conventions

The standard library follows a handful of rules consistently. User code is encouraged to mirror them, and knowing them up front means you can predict most signatures before reading them.

Result for expected failure, panic for broken invariants. A function returns Result<T, E> whenever failure is part of its contract — a file that might not exist, a parse that might not succeed. It panics only when the contract cannot be preserved at all, such as an out-of-bounds index on a method whose contract excludes it. Fallible constructors are usually spelled try_* next to a panicking sibling.

No NUL-terminated strings outside ffi. Every other module works in length-typed Str and String values. Translation to and from C strings happens at the boundary, in ffi.

Explicit resource management. Every owning type exposes drop(mut &this), and its documentation says who is responsible for calling it. In practice the compiler synthesises drops at scope exit — see Ownership, Copy, and Drop — and a manual .drop() remains available for early release.

Allocator-generic containers. Array<T, A>, HashMap<K, V, A>, String<A>, Box<T, A>, Rc<T, A>, and PathBuf<A> all take the allocator as a trailing type parameter defaulting to GlobalAlloc. The *_in constructors plug in an arena, a pool, or your own strategy without changing any other code.

No magic numbers. Every numeric constant in the library is named. A bare literal in a signature is a bug report waiting to happen.

Reading the sources

Each page here documents the surface, but the library is short and readable, and its doc comments are the ground truth. The manifest at stdlib/lib.cryo lists every module, and each directory's _module.cryo describes what its files contain.