Text
std/text is Flint’s portable text package.
It complements the built-in string and char types:
stringhandles read-only and view-returning text operationscharexposes Unicode scalar values plus small UTF-8 helpersstd/textprovides split results and fixed-capacity mutable text throughtext.Buffer[N]
See String and Char for the built-in type surface.
Read-Only Text Surface
Most day-to-day string work reads naturally as methods on string:
let text = " key?=value\r\n"
let trimmed = text.trim()
let found = text.contains("?=")
let first = text.find("?=")
let split = text.split_once("?=")
Those methods are backed by the portable std/text layer and the minimal built-in string substrate. The important rule is that they remain allocation-free in the portable baseline.
text.Split
split_once and split_once_last return text.Split, a small allocation-free view result:
let text = "key?=value?=tail"
let split = text.split_once("?=")
if split.found() {
let key = split.before()
let value = split.after()
}
Current methods:
found()before()after()
If no delimiter matches, before() returns the full input and after() returns an empty string.
text.Buffer[N]
text.Buffer[N] is the current mutable text type for portable code.
It uses explicit fixed capacity and preserves UTF-8 validity instead of hiding allocation behind string methods.
use std/text as text
alias NameBuffer = text.Buffer[32]
fn build_name() -> Result<NameBuffer, text.BufferError> {
let mut buffer = text.buffer(32)
buffer.push_str("pico")?
buffer.push('-')?
buffer.push_str("uart")?
return Ok(buffer)
}
The constructor:
let mut buffer = text.buffer(32)
creates an empty text.Buffer[32].
Core Buffer Methods
Current shipped core methods:
capacity()len_bytes()is_empty()clear()as_string()
Example:
let mut buffer = text.buffer(16)
let cap = buffer.capacity()
let empty = buffer.is_empty()
let pushed = buffer.push_str("hi")
let view = buffer.as_string()
buffer.clear()
as_string() returns an immutable string view over the live buffer contents.
Mutation Methods
Current shipped mutation methods:
push(ch: char) -> Result<(), text.BufferError>push_ascii(byte: u8) -> Result<(), text.BufferError>push_str(text: string) -> Result<(), text.BufferError>insert(index: usize, text: string) -> Result<(), text.BufferError>remove(index: usize) -> Result<char, text.BufferError>replace(old: string, new: string) -> Result<u32, text.BufferError>
Example:
fn rewrite_name() -> Result<u32, text.BufferError> {
let mut buffer = text.buffer(32)
buffer.push_str("pico-led")?
buffer.insert(4, "-board")?
let removed = buffer.remove(4)?
let replaced = buffer.replace("led", "uart")?
return Ok(replaced)
}
Notes:
push,push_ascii,push_str,insert, andreplacepreserve UTF-8 validitypush_ascii(byte)is the explicit ASCII bridge for raw byte-stream input such as UART terminal bytesremove(index)removes one UTF-8 scalar value at a validated byte boundary and returns thatcharreplace(old, new)returns the number of non-overlapping replacementsreplace(old, new)rejects an empty pattern
text.BufferError
Current shipped error cases:
FullInvalidIndexEmptyPatternNonAscii
These cover the current fixed-capacity and index-validation failure modes.
Current Backend Status
The current executable backend supports:
- local
text.Buffer[N]construction and mutation - local copies
- direct by-value
text.Buffer[N]parameters and returns
Current limitation:
- by-value buffer arguments still need to come from local
text.Buffer[N]bindings at the call site on the current backend
Design Direction
The portable text baseline is intentionally conservative:
- UTF-8 everywhere
- no hidden allocation for read-only string operations
- fixed-capacity mutation through
text.Buffer[N] - explicit ASCII naming for ASCII-only classification or future transforms
Future richer Unicode behavior belongs in a separate std/unicode layer rather than changing the meaning of the core text APIs across targets.