Skip to content

std.text

Numbers to bytes and back, the ASCII class of a byte, and the searching a line protocol needs. A substring cannot be returned (a borrow is second class), so every search answers with an index into the input and the caller passes the part s[lo..hi] onwards. Cost: one pass per call; the write_ forms touch only the caller's storage and return the number of bytes used, or 0 when the value does not fit. The push_ forms grow a Vec.

// A place in a view that next_line, next_word and next_field move forward. Each finds the next piece at or after `at`,
// sets `lo..hi` to its bounds and moves `at` past it, so the piece is the part s[c.lo..c.hi] and nothing is copied:
// `let mut w = text.cursor(); while text.next_word(input, w) { ... }`.
pub struct Cursor { at:usize; lo:usize; hi:usize; }

pub enum ParseError { Empty; Invalid(usize); Overflow(usize); }

// One byte's ASCII class, as C's <ctype.h> answers it in the "C" locale: a byte above 127 is in none. Cost: a
// comparison or two; nothing is read but the byte.
pub fn is_digit(c:u8) -> bool  // effects: none

pub fn is_upper(c:u8) -> bool  // effects: none
pub fn is_lower(c:u8) -> bool  // effects: none
pub fn is_alpha(c:u8) -> bool  // effects: none
pub fn is_alnum(c:u8) -> bool  // effects: none

// ' ' and the five controls from 9 to 13: '\t', '\n', vertical tab, form feed and '\r'.
pub fn is_space(c:u8) -> bool  // effects: none

// A letter in the other case, by its case bit; every other byte as it is.
pub fn to_lower(c:u8) -> u8  // effects: none

pub fn to_upper(c:u8) -> u8  // effects: none

// Decimal digits and nothing else: no sign, no '+', no spaces around them.
// effects: ffi_precondition, read:s, trap
pub fn parse_u64(n:usize, s:ro<u8>[n]@host) -> std.core.Result[u64, std.text.ParseError]

// Signed decimal: an optional leading '-', then digits. The magnitude may reach 2^63 only when negative, and the error
// offset names the byte at fault as parse_u64 does.
// effects: ffi_precondition, read:s, trap
pub fn parse_i64(n:usize, s:ro<u8>[n]@host) -> std.core.Result[i64, std.text.ParseError]

pub fn cursor() -> std.text.Cursor  // effects: none

// The next line, without its "\n" or "\r\n". A last line without "\n" counts, and an empty view has none. Cost: one
// pass over the line.
// effects: diverge, ffi_precondition, read:c, read:s, trap, write:c
pub fn next_line(n:usize, s:ro<u8>[n]@host, c:rw<std.text.Cursor>) -> bool

// The next word: a run of bytes that are not is_space, which separates words and is skipped. Cost: one pass over the
// word and the space before it.
// effects: diverge, ffi_precondition, read:c, read:s, trap, write:c
pub fn next_word(n:usize, s:ro<u8>[n]@host, c:rw<std.text.Cursor>) -> bool

// The next field of a view split at every `sep`, as a line of comma-separated values is: "a,,b" has three fields, the
// second empty, and an empty view has one, which is empty. Cost: one pass over the field.
// effects: diverge, ffi_precondition, read:c, read:s, trap, write:c
pub fn next_field(n:usize, s:ro<u8>[n]@host, sep:u8, c:rw<std.text.Cursor>) -> bool

// A decimal with at most `places` digits after an optional '.', as a count of units of 10^-places: with two places
// "12.5" and "12.50" are 1250 and "12" is 1200. Digits only, as parse_u64 takes them, with one or more on each side of
// a point; a digit past `places` is Invalid, and a value past U64_MAX is Overflow. An error names the first fault from
// the left. Cost: one pass; `places` less the digits written must be at most 19, or the scale traps.
// effects: ffi_precondition, read:s, trap
pub fn parse_fixed(n:usize, s:ro<u8>[n]@host, places:usize) -> std.core.Result[u64, std.text.ParseError]

// Decimal, most significant digit first. The digits are produced backwards into fixed storage, so the caller's buffer
// is written once and never partially.
// effects: diverge, ffi_precondition, local_read, local_write, stack_storage, trap, write:out, zero_init
pub fn write_u64(n:usize, out:rw<u8>[n]@host, value:u64) -> usize

// A leading '-' and the magnitude, which is representable for every value, the minimum included.
// effects: diverge, ffi_precondition, local_read, local_write, stack_storage, trap, write:out, zero_init
pub fn write_i64(n:usize, out:rw<u8>[n]@host, value:i64) -> usize

// Exactly `width` lowercase hex digits, high nibble first; the high bits above `width` are lost.
// effects: ffi_precondition, trap, write:out
pub fn write_hex(n:usize, out:rw<u8>[n]@host, value:u64, width:usize) -> usize

// effects: alloc, diverge, ffi_precondition, free, local_read, local_write, read:v, stack_storage, trap, write:v,
// zero_init
pub fn push_u64(v:rw<std.vec.Vec[u8]>, value:u64)

// effects: alloc, diverge, ffi_precondition, free, local_read, local_write, read:v, stack_storage, trap, write:v,
// zero_init
pub fn push_i64(v:rw<std.vec.Vec[u8]>, value:i64)

// Lexicographic order on bytes, shorter first on a common prefix: -1, 0 or 1.
// effects: diverge, ffi_precondition, read:a, read:b, trap
pub fn compare(n:usize, a:ro<u8>[n]@host, m:usize, b:ro<u8>[m]@host) -> i32

// effects: diverge, ffi_precondition, read:a, read:b, trap
pub fn equal(n:usize, a:ro<u8>[n]@host, m:usize, b:ro<u8>[m]@host) -> bool

// effects: diverge, ffi_precondition, read:prefix, read:s, trap
pub fn starts_with(n:usize, s:ro<u8>[n]@host, m:usize, prefix:ro<u8>[m]@host) -> bool

// effects: diverge, ffi_precondition, read:s, read:suffix, trap
pub fn ends_with(n:usize, s:ro<u8>[n]@host, m:usize, suffix:ro<u8>[m]@host) -> bool

// effects: ffi_precondition, read:s, trap
pub fn find_byte(n:usize, s:ro<u8>[n]@host, byte:u8, from:usize) -> std.core.Option[usize]

// The last index holding `byte`, which is where a path's extension or a line's last field begins.
// effects: diverge, ffi_precondition, read:s, trap
pub fn find_last_byte(n:usize, s:ro<u8>[n]@host, byte:u8) -> std.core.Option[usize]

// The first index where `needle` starts. Naive, because a line protocol's needles are short.
// effects: diverge, ffi_precondition, read:needle, read:s, trap
pub fn find(n:usize, s:ro<u8>[n]@host, m:usize, needle:ro<u8>[m]@host) -> std.core.Option[usize]

// FNV-1a: no table, no allocation, good enough to key a map or checksum a record.
pub fn hash_bytes(n:usize, s:ro<u8>[n]@host) -> u64  // effects: ffi_precondition, read:s, trap

A generic function's effects are what it may do for any arguments within its bounds, besides what their own trait members do.