Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

std/*

std/* packages are the higher-level, cross-target library. They may depend on heap allocation or target-specific runtime services.

std/text: Portable Text

std/text is the portable text package that complements the built-in string and char types.

Today it provides:

  • read-only string behavior through the string method surface
  • allocation-free split results with text.Split
  • fixed-capacity mutable text with text.Buffer[N]
use std/text as text

let text_value = " key?=value\r\n"
let split = text_value.trim().split_once("?=")

let mut buffer = text.buffer(32)
let first = buffer.push_str(split.before())
let middle = buffer.push('=')
let last = buffer.push_str(split.after())

See Text for the actual current std/text API surface.

std/io: Buffered IO

use std/io

let mut buf_writer = io.BufferedWriter.new(uart_port, 256)?
buf_writer.write(data)?
buf_writer.flush()?    // flush accumulated bytes to underlying writer

std/fs: Filesystem

Available on host targets and MCU targets with SD card / FAT support:

use std/fs

let text = fs.read_text("config.txt")?
let bytes = fs.read_bytes("firmware.bin")?

let mut file = fs.open("log.txt")?
defer file.close()
file.write(b"log entry\n")?

Collections

List<T>, Deque<T>, Map<K, V>, and Set<T> are always available without an explicit use. They are compiler-known generic types:

let mut items: List<u32> = List.new()
items.push(1)?    // fallible: allocation can fail
items.push(2)?
items.push(3)?

let first = items[0]    // infallible: after allocation, indexing does not fail
let len = items.len()

for item in items {
    process(item)
}
let mut config: Map<string, string> = Map.new()
config.insert("baud", "115200")?
config.insert("target", "rp2040")?

if let Some(baud) = config.get("baud") {
    log.info(baud)
}

for entry in config.entries() {
    log.info(entry.key)
    log.info(entry.value)
}

Collection operations that allocate (push, insert, extend) return Result. Operations that do not allocate (len, get, indexing after allocation) are infallible.

std/sync: Channels and Mutexes

use std/sync

// Create a channel with capacity 16
let ends = sync.channel<u32>(16)?
let tx = ends.tx
let rx = ends.rx

// Send (blocking)
tx.send(42)?

// Non-blocking send
tx.try_send(42)?

// Receive (blocking)
let value = rx.recv()?

// Non-blocking receive
if let Ok(value) = rx.try_recv() {
    process(value)
}

Mutex:

use std/sync

let counter: sync.Mutex<u32> = sync.Mutex.new(0)?

{
    let mut guard = counter.lock()?
    defer guard.release()
    guard.value += 1
}

ISR rules: ISR code must not call blocking recv, send, lock, or wait operations. Use try_send and try_recv in interrupt contexts.

std/embed

Higher-level wrappers over core/embed for structured asset loading. Details depend on the specific asset type.