Files
vercel-labs--zerolang/docs/articles/modules/str.md
T
wehub-resource-sync e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:29:30 +08:00

74 lines
4.5 KiB
Markdown

## When To Use std.str
In Zerolang, use `std.str` for allocation-free byte-string helpers over spans and
caller-owned storage.
Runnable today:
| API | Return | Notes |
| --- | --- | --- |
| `std.str.copy(buffer, text)` | `Maybe<Span<u8>>` | Copies `text` into caller storage. |
| `std.str.concat(buffer, left, right)` | `Maybe<Span<u8>>` | Writes `left` followed by `right`. |
| `std.str.repeat(buffer, text, count)` | `Maybe<Span<u8>>` | Repeats `text` into caller storage. |
| `std.str.replace(buffer, text, old, replacement)` | `Maybe<Span<u8>>` | Replaces non-overlapping `old` byte substrings into caller storage; empty `old` returns `null`. |
| `std.str.reverse(buffer, text)` | `Maybe<Span<u8>>` | Writes reversed bytes into non-overlapping caller-provided storage. |
| `std.str.countByte(text, byte)` | `usize` | Counts exact byte matches. |
| `std.str.count(text, needle)` | `usize` | Counts non-overlapping byte substring matches; the empty needle returns `len + 1`. |
| `std.str.splitCount(text, separator)` | `usize` | Counts byte-separator split parts; an empty separator returns `0`. |
| `std.str.split(text, separator, index)` | `Maybe<Span<u8>>` | Borrows a zero-based split part. |
| `std.str.fieldCountAscii(text)` | `usize` | Counts non-empty ASCII-whitespace separated fields. |
| `std.str.fieldAscii(text, index)` | `Maybe<Span<u8>>` | Borrows a zero-based ASCII-whitespace field. |
| `std.str.lineCount(text)` | `usize` | Counts LF-delimited lines; a trailing LF does not add a final empty line. |
| `std.str.line(text, index)` | `Maybe<Span<u8>>` | Borrows a zero-based line and strips `\r` before `\n`. |
| `std.str.indexOf(text, needle)` / `std.str.lastIndexOf(text, needle)` | `usize` | Returns a matching byte index or the input length when absent. |
| `std.str.startsWith(text, prefix)` | `Bool` | Checks a byte prefix. |
| `std.str.endsWith(text, suffix)` | `Bool` | Checks a byte suffix. |
| `std.str.contains(text, needle)` | `Bool` | Checks for a byte substring; the empty needle is present. |
| `std.str.trimAscii(text)` | `Span<u8>` | Borrows `text` without leading or trailing ASCII space bytes. |
| `std.str.trimStartAscii(text)` / `std.str.trimEndAscii(text)` | `Span<u8>` | Borrows one-sided trimmed views. |
| `std.str.toLowerAscii(buffer, text)` / `std.str.toUpperAscii(buffer, text)` | `Maybe<Span<u8>>` | Writes ASCII case-converted bytes into caller storage. |
| `std.str.eqlIgnoreAsciiCase(left, right)` | `Bool` | Compares ASCII case-insensitively. |
| `std.str.wordCountAscii(text)` | `usize` | Counts non-empty runs separated by ASCII space bytes. |
Current scope:
- Helpers operate on byte spans and ASCII delimiter rules for space, tab, line feed, and carriage return.
- `reverse`, `repeat`, `replace`, `copy`, and `concat` write into caller storage and return `null` when the buffer is too small. The destination buffer must not overlap the input.
- The module does not implement Unicode case mapping, grapheme segmentation, or locale-aware text rules.
## Example
```zero
pub fn main(world: World) -> Void raises {
var storage: [6]u8 = [0_u8; 6]
let reversed: Maybe<Span<u8>> = std.str.reverse(storage, "drawer")
var repeated_storage: [8]u8 = [0_u8; 8]
let repeated: Maybe<Span<u8>> = std.str.repeat(repeated_storage, "ha", 3)
var lower_storage: [4]u8 = [0_u8; 4]
let lower: Maybe<Span<u8>> = std.str.toLowerAscii(lower_storage, "ZERO")
let field: Maybe<Span<u8>> = std.str.fieldAscii("zero text", 1)
if reversed.has && repeated.has && (lower.has && field.has) {
if std.mem.eql(reversed.value, "reward") && std.mem.eql(repeated.value, "hahaha") && (std.mem.eql(lower.value, "zero") && std.mem.eql(field.value, "text")) {
check world.out.write("string helper ok\n")
}
}
}
```
## Design Notes
`std.str` is allocation-free. Functions that create new byte sequences use
caller-provided storage, and functions that return spans borrow from an input or
that caller-provided storage.
`reverse` is a copy helper, not an in-place reversal primitive. Pass separate
destination storage when the source text comes from mutable bytes.
String literals can be passed directly to these helpers; fixed arrays and
mutable buffers can be passed as spans when the caller needs non-literal input.
The current helpers are byte-string primitives. They are suitable for protocol
tokens, Rosetta-style ASCII examples, and fixed-buffer tools. Unicode text
algorithms should be added as explicit APIs with documented behavior instead of
being implied by these byte-span helpers.