Skip to content
volt
GitHub

The standard library

std is an ordinary package: a directory of .volt files that voltc compiles along with your program (--std DIR, $VOLT_STD, or the std/ next to voltc). The compiler knows only a few of its names (@derive falls back to std::derive’s traits; bindings and C++ imports use std::vec and std::string), so a std of your own can replace it as long as it keeps those.

Each file is wrapped in namespace std, and most declare a namespace of their own inside it. The parts that need an OS (files, processes, time, random bytes, networking and threads) have code for Linux, macOS, FreeBSD and Windows, 64-bit, on x86-64 and ARM64, picked with @cfg:

Module What it has
std::io println, print, eprintln, eprint: formatted output, checked at compile time (Printing)
std::fmt format (text as a std::string) and write (into any writer); format specifiers like {:>8.2} (Formatting into strings and writers)
std::text methods on str: search, trim, split, replace, case, parse numbers; UTF-8; ASCII classes on u8; join (Text and strings)
std::string string: owned, growable UTF-8 text (Building text)
std::vec vec<T>: a growable array that owns its elements; insert, remove, retain, dedup
std::map map<K, V>: a hash map, iter() over its entries, and hash for the built-in key types
std::set set<T>: a hash set
std::sorted_map sorted_map<K, V>: a map that walks its keys in order
std::deque deque<T>: a double-ended queue
std::heap heap<T>: a priority queue, smallest first
std::slice on any T[..]: stable sort, sort_by, binary_search, reverse, contains, min, max (Collections and algorithms)
std::compare eq and cmp, which collections and algorithms compare values with (Comparing values)
std::derive what @derive(eq, hash, fmt, json) attaches (Derive)
std::math constants, sqrt, pow, trig and the rest of libm (f64 and f32; in Volt as std::math::portable), min/max/clamp, integer limits, checked and saturating arithmetic, gcd/lcm (Math)
std::simd SIMD vectors (f64x2, f32x4, i32x4, …, or vec(T, n)): arithmetic lane by lane, lanes by index, splat, sum, load, store (SIMD vectors)
std::random random numbers (xoshiro256**), seeded or from the OS; ranges, floats, shuffle, choose; secure OS bytes (Random numbers)
std::mem the allocator trait and allocators (arena, fixed_buffer, failing), box<T> (an owning pointer), T::new, mem_error (Allocators)
std::fs files and directories: whole files, file streams (open, read_line, seek), listing, walking, creating, removing (Files)
std::path paths as text: join, parent, file_name, extension, normalize (Paths)
std::process running programs, arguments, the environment and the working directory, exit (Processes)
std::time the monotonic clock, the wall clock, sleep, durations, UTC dates in ISO 8601 (Time)
std::net TCP (listen, connect, streams), UDP, resolve, timeouts; the same on Linux, macOS, FreeBSD and Windows (Networking)
std::thread threads (spawn, join), mutex<T> and its guard, cond, atomic_i64/atomic_bool, shared<T>, channel<T> (Threads)
std::json JSON values: parse, build and print (JSON)
std::html text escaped for HTML, and templates (slots, loops, conditions) rendered from JSON values or checked against a type while compiling (HTML templates)
std::base64, std::hex bytes as base64 (standard and URL-safe) or hex text, and back (Encoding and hashing)
std::digest CRC-32, 64-bit FNV-1a and SHA-256 (in one call, or fed in pieces) (Checksums and hashes)
std::softfloat IEEE 754 arithmetic, comparison and conversion on the bits of f32s and f64s with integer instructions only: what bare metal cores without a floating-point unit use
std::softint division, 64-bit shifts and wide multiplies from 32-bit operations, for cores without them (a Cortex-M0); std/bare.volt hands them and the rest of a bare-metal program’s runtime to the compiler, in place of C’s
std::testing assertions that print the values they compared (assert_eq, assert_near, …), and run for a file of tests (Tests)

use std::io; makes std::io’s members reachable through the first namespace, so std::io::println can be written std::println. The containers are declared directly in std (std::string, std::vec<T>, std::map<K, V>; see Collections), and box in std::mem.

use std::io;
fn main() -> !void {
var names: std::vec<std::string> = {};
try names.push(std::string::from("volt"));
var ages: std::map<str, i32> = {};
ages.put("volt", 1);
val b: std::mem::box<i32> = try i32::new(5);
std::println("{} {} {} {}", names.len, names[0], *(ages.get("volt") ?? return), b);
}
// expect: 1 volt 1 5

A std binds what only the compiler can do through two attributes:

  • @attributes([@intrinsic("println")]) on a body-less fn makes it a compiler builtin (the formatted print functions, format and write) or, for a name starting with volt_, a function of the C runtime. The runtime’s functions include allocation, atomics, and threads with a wait and wake on a word, so another std can build threads too.
  • @attributes([@owns("ptr")]) on a struct makes it an owning pointer like box: it’s used like a T&, and when it goes out of scope the value it points at is deleted first.

tests/std_alt in the repository is a std written from scratch. In bolt, [std] path = "../mystd" picks one per package; voltc --std DIR does it by hand.

The reference pages (std::io and the rest) come from voltc doc std, which prints a package’s declarations and their comments as JSON (the comment block directly above a declaration, or after a field on its line). Run it on your own packages with voltc doc NAME --pkg NAME=DIR.