Strings

Strings

string is a class holding a managed byte buffer and a length.

[public] class string impl Hash, Equals<string>, NotEquals<string>,
    Index<number, char>, Plus<string>, Serialize, Deserialize {
    [public] fn size() => number
    [public] fn index(i: number) => char
    [public] fn substring(start: number, end: number) => string
    [public] fn index_of(needle: string) => number
    [public] fn contains(needle: string) => bool
    [public] fn starts_with(prefix: string) => bool
    [public] fn ends_with(suffix: string) => bool
    [public] fn to_number() => number
    [public] fn to_raw() => pointer<i8>
}

Behavior worth knowing

Indexing is by byte. size() counts bytes and index(i) returns the byte at that offset as a char. For ASCII text these coincide with characters; for anything else they do not.

index_of returns -1 when the needle is absent, not an optional. An empty needle matches at 0.

let cut = path.index_of("/")
if cut < 0 {
    return None
}

substring clamps rather than failing on out-of-range bounds, and takes a start and an end, not a start and a length.

to_number() returns a plain number, not an optional, and parses the leading number. Non-numeric text yields zero, so "abc" and "0" are indistinguishable. Where the difference matters, check the text first.

string implements Index but not IndexRef, so s[i] reads and s[i] = c is a compile error. It also has no iter(), so for c in text does not work; index in a loop instead.

== on two strings compares contents, because string implements Equals.

Building strings

Interpolation covers most cases. For a loop, StringBuilder avoids quadratic copying:

let builder: StringBuilder = new StringBuilder()
builder.append("[")
builder.append(name)
builder.append("]")
let result: string = builder.build()