Standard Library
Built-in types: String, Vec, HashMap, Iterator, IO.
Three-tier architecture
Hew's standard library is organized into three tiers, enabling use in environments ranging from bare-metal to full OS:
- core — No allocation, no OS. Primitive types,
Option<T>,Result<T, E>, Iterator trait, marker traits (Send,Frozen,Copy), and memory intrinsics. Works on bare metal. - alloc — Heap allocation, no OS.
Vec<T>,string,Box<T>,Arc<T>,Rc<T>,HashMap<K, V>,HashSet<T>, and formatting. Works anywhere with a heap. - std — Full OS integration. File system (
std::fs), networking (std::net), IO (std::io), environment (std::env), and process spawning (std::process).
string
string is an owned, heap-allocated, growable UTF-8 string. Internally it wraps a Vec<u8> that is guaranteed to contain valid UTF-8.
type string {
// Internal: Vec<u8> guaranteed valid UTF-8
}
impl String {
fn new() -> String;
fn from(s: str) -> String;
fn len(self) -> usize;
fn push(self, c: char);
fn push_str(self, s: str);
fn as_str(self) -> str;
}Vec<T>
Vec<T> is a growable, heap-allocated array. It manages a contiguous block of memory with a length and capacity.
impl<T> Vec<T> {
fn new() -> Vec<T>;
fn with_capacity(cap: usize) -> Vec<T>;
fn push(self, item: T);
fn pop(self) -> Option<T>;
fn len(self) -> usize;
fn get(self, index: usize) -> Option<T>;
fn truncate(self, len: usize);
fn clone(self) -> Vec<T>;
fn swap(self, a: usize, b: usize);
fn sort(self) where T: Ord;
}
// Default: uses actor's current allocator
let items = Vec::new();
// Explicit: uses provided allocator
let temp = Vec::new_in(arena_allocator);HashMap<K, V>
HashMap<K, V> is a hash table using Robin Hood hashing. Keys must implement Hash + Eq.
impl<K: Hash + Eq, V> HashMap<K, V> {
fn new() -> HashMap<K, V>;
fn insert(self, key: K, value: V) -> Option<V>;
fn get(self, key: K) -> Option<V>;
fn remove(self, key: K) -> Option<V>;
fn contains_key(self, key: K) -> bool;
}Iterator
The Iterator trait provides lazy, composable data transformation with combinators like map, filter, fold, and collect.
trait Iterator {
type Item;
fn next(self) -> Option<Self::Item>;
// Provided combinators
fn map<B>(self, f: fn(Self::Item) -> B) -> Map<Self, B>;
fn filter(self, pred: fn(Self::Item) -> bool) -> Filter<Self>;
fn collect<C: FromIterator<Self::Item>>(self) -> C;
fn fold<B>(self, init: B, f: fn(B, Self::Item) -> B) -> B;
}
trait IntoIterator {
type Item;
type IntoIter: Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter;
}IO
The IO system is built on Read and Write traits. All IO operations return Result — there is no implicit blocking.
trait Read {
fn read(self, buf: [u8]) -> Result<usize, IoError>;
fn read_exact(self, buf: [u8]) -> Result<(), IoError>;
fn read_to_end(self, buf: Vec<u8>) -> Result<usize, IoError>;
fn read_to_string(self, buf: String) -> Result<usize, IoError>;
}
trait Write {
fn write(self, buf: [u8]) -> Result<usize, IoError>;
fn flush(self) -> Result<(), IoError>;
fn write_all(self, buf: [u8]) -> Result<(), IoError>;
}
trait BufRead: Read {
fn fill_buf(self) -> Result<[u8], IoError>;
fn consume(self, amt: usize);
fn read_line(self, buf: String) -> Result<usize, IoError>;
}The File type wraps a file descriptor with safe open/close semantics using Drop for deterministic resource cleanup:
type File { fd: i32; }
impl File {
pub fn open(path: String) -> Result<File, IoError> {
let c_path = path.to_c_string();
let fd = unsafe { open(c_path.as_ptr(), O_RDONLY) };
if fd < 0 {
Err(IoError::from_errno())
} else {
Ok(File { fd })
}
}
}
impl Drop for File {
fn drop(f: File) {
unsafe { close(f.fd); }
}
}
// File I/O convenience functions
fn read_file(path: String) -> Result<String, IoError>;
fn write_file(path: String, content: String) -> Result<(), IoError>;File I/O
The std::fs module provides convenience functions for reading, writing, and deleting files. The std::stream module adds streaming file access for line-by-line processing without loading the entire file into memory.
import std::fs;
import std::stream;
import std::os;
fn main() {
let tmp = os.temp_dir();
let path = tmp + "/example.txt";
// Write and read a file
fs.write(path, "apple\nbanana\ncherry\n");
let content = fs.read(path);
let size = fs.size(path);
println(f"Size: {size} bytes");
// Stream: read file line by line
let raw = match stream.from_file(path) {
Ok(s) => s,
Err(e) => { panic(e); },
};
let lines = raw.lines();
for await line in lines {
println(line);
}
// Stream: write to a file
let out_path = tmp + "/output.txt";
let sink = match stream.to_file(out_path) {
Ok(s) => s,
Err(e) => { panic(e); },
};
sink.write("hello ");
sink.write("from ");
sink.write("hew");
sink.flush();
sink.close();
// Cleanup
fs.delete(path);
fs.delete(out_path);
}CLI arguments
The std::os module provides access to command-line arguments. Use os.args_count() for the argument count and os.args(i) to get individual arguments by index. String methods like starts_with, find, and slice handle parsing.
import std::os;
fn main() {
let argc = os.args_count();
if argc <= 1 {
println("Usage: myapp [OPTIONS] [FILES...]");
return;
}
var i = 1;
while i < argc {
let arg = os.args(i);
if arg.starts_with("--") {
let eq_pos = arg.find("=");
if eq_pos >= 0 {
let key = arg.slice(2, eq_pos);
let val = arg.slice(eq_pos + 1, arg.len());
println(f"{key} = {val}");
} else {
println(f"flag: {arg}");
}
} else {
println(f"file: {arg}");
}
i += 1;
}
}Stream channels
std::stream.channel(capacity) creates a bounded, typed channel for passing data between producers and consumers. The producer writes to the sink; the consumer reads with for await. Close the sink to signal completion.
import std::stream;
fn main() {
let (sink, input) = stream.channel(8);
// Producer writes to sink
sink.write("alpha");
sink.write("beta");
sink.write("gamma");
sink.write("delta");
sink.close();
// Consumer reads with for-await
for await item in input {
println(item);
}
input.close();
}Allocators
Hew provides an explicit allocator interface for fine-grained memory control. Collections can be parameterized over allocators.
- GlobalAllocator — Default system allocator
- ArenaAllocator — Bump allocation with O(1) bulk deallocation
- PoolAllocator — Fixed-size object pools for uniform allocations
trait Allocator {
fn alloc(self, size: usize, align: usize) -> Result<*var u8, AllocError>;
fn dealloc(self, ptr: *var u8, size: usize, align: usize);
}