Sushi Standard Library¶
Complete reference for Sushi's standard library modules and types.
Table of Contents¶
Core Types¶
- Result@(T) - Error handling for fallible operations
- Maybe@(T) - Optional values
Collections¶
- List@(T) - Dynamic growable array
- HashMap@(K, V) - Hash table with open addressing
- Arrays - Fixed and dynamic array methods
- Strings - 33 string manipulation methods
- Iter combinators -
map/filter/fold/composeoverList@(T)
Encoding and Compression¶
- Compression (zlib) - DEFLATE and the zlib container (RFC 1950/1951)
- MessagePack - MessagePack decoder
- Slib reader -
.slibheader and metadata reader
I/O Operations¶
- Console I/O - println, print, stdin/stdout/stderr
- File I/O - File operations with error handling
- Path algebra - Lexical path manipulation (join, basename, dirname, extension, normalize)
- File-system ops - stat, recursive walk, mkdir_all, remove_all
- I/O contracts -
Reader,Writer,Seek: what a handle can do - I/O errors -
IoErrorandFileError, the error vocabulary of the io modules - Buffered I/O -
BufReader,BufWriter: one system call per window
Networking¶
- Socket primitives - the raw BSD calls
- Net errors -
NetError, the error vocabulary of the net modules - TCP -
TcpStreamandTcpListener - UDP -
UdpSocket, send_to and recv_from - DNS - a host name resolved into typed addresses
- IP addresses -
IpAddr, parse and format, both families - URLs - lexical URL splitting
System Modules¶
- Math - Mathematical operations (abs, min, max, sqrt, pow, trig)
- Random - Pseudo-random number generation (rand, rand_range, rand_f64, srand)
- Time - High-precision sleep functions
- Environment - Environment variables and system information
- Process Control - Process management (getcwd, chdir, exit, getpid, getuid)
- Platform - Platform detection and OS-specific utilities
Quick Reference¶
Importing Modules¶
use <collections/strings> # String methods
use <collections/iter> # Higher-order combinators (map/filter/fold/compose)
use <compression/zlib> # DEFLATE and the zlib container
use <encoding/msgpack> # MessagePack decoder
use <io/buf> # BufReader, BufWriter: buffered over any handle
use <io/contracts> # Reader, Writer, Seek (re-exports <io/error>)
use <io/error> # IoError, FileError -- brought by <io/fs>, <io/buf>, <io/files>
use <io/files> # the path utilities and the fd_* primitives
use <io/path> # Lexical path manipulation
use <io/fs> # File, open, stdin/stdout/stderr, stat, walk, mkdir_all
use <net/socket> # the raw socket calls, and NetError
use <net/tcp> # TcpStream, TcpListener
use <net/udp> # UdpSocket
use <net/dns> # resolve a host name
use <net/ip> # IpAddr, parse and format
use <net/url> # split a URL
use <math> # Math functions
use <random> # Random number generation
use <time> # Sleep and clock functions
use <sys/env> # Environment variables
use <sys/process> # Process control
Common Patterns¶
Error Handling¶
use <io/fs>
# Using ?? operator for propagation. The channel is the one open() answers,
# so a read propagates through it with no conversion in the middle.
fn read_config() string | IoError:
let File f = open("config.txt", FileMode.Read())??
return Result.Ok(f.read_all()??)
# Using pattern matching
match parse_number("42"):
Result.Ok(n) -> println("Got: {n}")
Result.Err() -> println("Parse failed")
# Using .realise() for defaults
let i32 port = config.get("port").realise(8080)
Optional Values¶
# Safe array access
match arr.get(0):
Maybe.Some(first) -> println("First: {first}")
Maybe.None() -> println("Array empty")
# String searching
let string text = "hello world"
let Maybe@(i32) pos = text.find("world")
Collections¶
use <collections/hashmap>
# List@(T) - no import required
let List@(i32) numbers = List.new()
numbers.push(1)
numbers.push(2)
numbers.push(3)
# HashMap@(K, V) - requires import
let HashMap@(string, i32) ages = HashMap.new()
ages.insert("Alice", 30)
match ages.get("Alice"):
Maybe.Some(age) -> println("Age: {age}")
Maybe.None() -> println("Not found")
# Arrays - built-in
let i32[] arr = from([1, 2, 3])
arr.push(4)
foreach(n in arr.iter()):
println(n)
String Processing¶
use <collections/strings>
let string text = " Hello World "
let string clean = text.trim().lower() # "hello world"
let string[] parts = "a,b,c".split(',')
let string joined = ','.join(parts) # "a,b,c"
let string path = "/home/user/file.txt"
let string filename = path.strip_prefix("/home/user/") # "file.txt"
File I/O¶
use <io/fs>
# Reading files. A handle closes itself at the end of the arm, so nothing
# calls close() -- and every read answers IoError.
match open("data.txt", FileMode.Read()):
Result.Ok(f) ->
match f.read_all():
Result.Ok(content) -> println(content)
Result.Err(_) -> println("Read failed")
Result.Err(IoError.NotFound()) ->
println("File not found")
Result.Err(_) ->
println("Other error")
# Writing files
match open("output.txt", FileMode.Write()):
Result.Ok(f) ->
match f.writeln("Mostly Harmless"):
Result.Ok(_) -> println("written")
Result.Err(_) -> println("Failed to write")
Result.Err(_) ->
println("Failed to open")
# Buffered, when the loop is long: one system call per window, not per line
let BufWriter@(File) out = BufWriter.new(nom stdout.share()??, 8192)??
out.write_line("Mostly Harmless")??
out.finish()??
Module Overview¶
Collections¶
List@(T) - Generic dynamic array (built-in, no import required):
- Construction: new(), with_capacity()
- Access: get(), len(), is_empty()
- Modification: push(), pop(), insert(), remove(), clear()
- Iteration: iter() for foreach loops
- Memory: free(), destroy()
HashMap@(K, V) - Generic hash table (use <collections/hashmap>):
- Construction: new()
- Operations: insert(), get(), remove(), contains_key()
- Iteration: keys(), values(), entries()
- Automatic resizing at 0.75 load factor
- Memory: free(), destroy()
Arrays - Built-in array support:
- Fixed arrays: i32[10]
- Dynamic arrays: i32[] with from([...])
- Methods: len(), get(), push(), pop(), iter(), clone()
- Safe access with get() returns Maybe@(T)
- Unsafe direct indexing: arr[i]
- Indexed assignment: arr[i] := v (bounds-checked; the element it replaces is freed)
Strings - 33 methods (use <collections/strings>):
- Inspection, slicing, transformation, padding, stripping
- Splitting/joining, case conversion, parsing
- UTF-8 aware where needed
Iter combinators - higher-order functions over List@(T) (use <collections/iter>):
- map(xs, f), filter(xs, pred), fold(xs, init, f), compose(nom g, nom f)
- Ordinary generic free functions (the first Sushi-source stdlib module, no bitcode)
- Copy/primitive element types; pass a typed-param lambda (|i32 x| ...) or a function reference
Compression (use <compression/zlib>)¶
zlib - DEFLATE and the RFC 1950 container, written in Sushi (no C library, no FFI):
- zlib_compress(src, level), zlib_uncompress(src) - the container, with an Adler-32 trailer
- deflate_raw(src, level), inflate_raw(src) - a bare RFC 1951 stream
- adler32(data), zlib_error_text(e) - the checksum, and one stable line per error
- The decoder reads stored, fixed and dynamic blocks; the encoder emits stored and fixed
only, so its ratio is short of a full encoder's
I/O (use <io/fs>, use <io/files>)¶
Console I/O:
- println(), print() - Output with/without newline
- stdin.readln() - One line, or Maybe.None at end of input
- stdin, stdout, stderr - File unit variables (public var) over descriptors 0, 1 and 2
File I/O:
- open() - Open files with Read/Write/Append modes
- One read: read(max) / read_bytes(max); the whole file: read_all(); one line:
readln(); writing: write() / write_bytes() / writeln()
- close() CONSUMES the handle, and is only needed where the failure has to be SEEN --
a File closes itself when its owner leaves scope
- Every read, write, seek, open() and close() answers IoError; the path utilities
and the fd_* primitives keep FileError
- FileMode, FileError, IoError and SeekFrom all come with use <io/fs>: a
predefined enum's import brings its name (#574), and <io/fs> re-exports the
modules that home the other three (#586)
Buffered I/O (use <io/buf>):
- BufReader.new(nom src, cap) / BufWriter.new(nom dst, cap) - one system call per WINDOW
- r.lines() answers a Lines@(R), which foreach walks:
foreach(line?? in r.lines())
Math (use <math>)¶
All functions use a single polymorphic name (no type-suffixed variants):
- Absolute value / min / max: abs(), min(), max() (return the argument's type)
- Floating-point (f64): sqrt(), pow(), floor(), ceil(), round(), trunc()
- Trigonometry: sin(), cos(), tan(), asin(), acos(), atan(), atan2()
- Hyperbolic: sinh(), cosh(), tanh()
- Exponential / logarithm: exp(), exp2(), log(), log2(), log10()
- Utility: hypot()
- Constants: PI, E, TAU
Time (use <time>)¶
High-precision sleep functions:
- sleep(i64) - Sleep for N seconds
- msleep(i64) - Sleep for N milliseconds
- usleep(i64) - Sleep for N microseconds
- nanosleep(i64, i64) - Nanosecond precision
Environment (use <sys/env>)¶
getenv()- Get environment variablesetenv()- Set environment variable
Process (use <sys/process>)¶
getcwd()- Get current working directorychdir()- Change working directoryexit()- Terminate the process with an exit codegetpid()- Get the process IDgetuid()- Get the user IDrun()- Spawn a program by argv (no shell), capturing stdout/stderr and exit code
Design Principles¶
- Explicit error handling - All fallible operations return
Result@(T)orMaybe@(T) - Memory safety - RAII cleanup, no manual memory management
- Zero-cost abstractions - Generics compile to concrete types
- UTF-8 by default - Strings are UTF-8, methods are aware where needed
- Immutability - String methods return new strings, arrays use RAII
- Type safety - No null, no undefined behavior, exhaustive pattern matching
Performance Notes¶
- List@(T): Amortized O(1) push, O(n) insert/remove
- HashMap@(K, V): O(1) average insert/get/remove, O(n) worst case
- String methods: All allocate new strings, O(n) for most operations
- Arrays: Direct memory access, bounds checked at runtime
- Generics: Monomorphized at compile-time (no runtime overhead)
See Also¶
- Language Reference - Core language features
- Memory Management - RAII, borrowing, ownership
- Generics - Generic types and functions
- Getting Started - Installation and first program