std::tstring (v0.2.1)

Owned null-terminated strings with byte operations, UTF-8 validation, and Unicode code point helpers.

Latest

Overview

The std::tstring module provides TString, an owned string type implemented with std::collections::vector. It stores bytes as char values and keeps a trailing null terminator so the buffer can be exposed as a CString when needed.

Use TString when code needs a mutable string-like buffer with explicit lifetime management. The module covers construction from C strings, copying, concatenation, trimming, prefix and suffix checks, ASCII case conversion, and UTF-8 validation.

The API is still low-level. TString owns its vector allocation, so callers must destroy values they create when the string is no longer needed. Operations that return a new TString also return ownership to the caller.

Source: thrustc/std/v0.2.1/tstring.thrust

Public Signatures

Exported declarations for this module snapshot.

type UnicodeCodePoint @public = u32;
struct TString @public {
fn newTString() TString @public;
fn withCapacity(capacity: usize) TString @public;
fn fromCString(text: CString) TString @public;
fn copy(text: ptr[TString]) TString @public;
fn toCString(text: ptr[TString]) CString @public;
fn destroyTString(text: ptr[TString]) void @public;
fn len(text: ptr[TString]) usize @public;
fn unicodeCodePointCount(text: ptr[TString]) usize @public;
fn isEmpty(text: ptr[TString]) bool @public;
fn hasIndex(text: ptr[TString], index: usize) bool @public;
fn get(text: ptr[TString], index: usize) char @public;
fn capacity(text: ptr[TString]) usize @public;
fn clear(text: ptr[TString]) void @public;
fn reserve(text: ptr[TString], requestedCapacity: usize) void @public;
fn appendCString(text: ptr[TString], value: CString) void @public;
fn appendTString(text: ptr[TString], value: ptr[TString]) void @public;
fn concat(left: ptr[TString], right: ptr[TString]) TString @public;
fn trim(text: ptr[TString]) TString @public;
fn trimStart(text: ptr[TString]) TString @public;
fn trimEnd(text: ptr[TString]) TString @public;
fn startsWith(text: ptr[TString], prefix: CString) bool @public;
fn endsWith(text: ptr[TString], suffix: CString) bool @public;
fn contains(text: ptr[TString], value: CString) bool @public;
fn indexOf(text: ptr[TString], value: CString) usize @public;
fn equals(left: ptr[TString], right: ptr[TString]) bool @public;
fn toUpperCaseASCII(text: ptr[TString]) TString @public;
fn toLowerCaseASCII(text: ptr[TString]) TString @public;
fn isValidUTF8(text: CString) bool @public;
fn isCharBoundary(text: ptr[TString], index: usize) bool @public;
fn decodeNext(text: ptr[TString], index: usize, outCodePoint: ptr[UnicodeCodePoint]) usize @public;
fn pushUnicodeCodePoint(text: ptr[TString], codePoint: UnicodeCodePoint) bool @public;

Behavior and Use

len returns the byte length without the trailing null terminator, while capacity reports usable byte capacity without counting that terminator.

toCString returns a pointer to the internal null-terminated buffer. Treat that pointer as borrowed from the TString and avoid using it after the TString is destroyed or mutated.

get, hasIndex, and indexOf use byte indexes. get returns '\0' when the index is outside the string, and indexOf returns len(text) when the value is not found.

UTF-8 helpers also operate on byte indexes. isCharBoundary can be used before slicing-style logic, and decodeNext advances from one code point boundary to the next.

ASCII case conversion only changes bytes in the A-Z or a-z ranges. It does not perform locale-aware or full Unicode casing.

Examples

import std::tstring;
import std::io;

fn main() s32 @public {
    var text := tstring::fromCString("thrust");

    tstring::appendCString(ref text, " language");
    io::print("%s\n", tstring::toCString(ref text));

    tstring::destroyTString(ref text);
    return 0;
}
import std::tstring;

fn main() s32 @public {
    var left := tstring::fromCString("hello");
    var right := tstring::fromCString(" world");
    var joined := tstring::concat(ref left, ref right);

    var ok: bool = tstring::startsWith(ref joined, "hello") &&
        tstring::endsWith(ref joined, "world");

    tstring::destroyTString(ref joined);
    tstring::destroyTString(ref right);
    tstring::destroyTString(ref left);

    if ok {
        return 0;
    }

    return 1;
}
import std::tstring;

fn main() s32 @public {
    var text := tstring::fromCString("  data  ");
    var trimmed := tstring::trim(ref text);
    var upper := tstring::toUpperCaseASCII(ref trimmed);
    var expected := tstring::fromCString("DATA");

    var ok: bool = tstring::isValidUTF8(tstring::toCString(ref upper)) &&
        tstring::equals(ref upper, ref expected);

    tstring::destroyTString(ref expected);
    tstring::destroyTString(ref upper);
    tstring::destroyTString(ref trimmed);
    tstring::destroyTString(ref text);

    if ok {
        return 0;
    }

    return 1;
}
import std::tstring;

fn main() s32 @public {
    var text := tstring::newTString();
    var ok: bool = tstring::pushUnicodeCodePoint(ref text, 0x41);

    tstring::destroyTString(ref text);

    if ok {
        return 0;
    }

    return 1;
}
import std::tstring;

fn main() s32 @public {
    var text := tstring::fromCString("hello");

    if !tstring::hasIndex(ref text, 4) {
        return 1;
    }

    if tstring::get(ref text, 1) != 'e' {
        return 2;
    }

    if tstring::indexOf(ref text, "lo") != 3 {
        return 3;
    }

    tstring::destroyTString(ref text);
    return 0;
}

Notes

Back to std index