Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Development · Evolving reference

ReadText

Collects and strictly decodes a complete UTF-8 stream. Validation occurs after EOF, so a Unicode sequence may span short reads. Invalid encoding and allocation/provider failures retain consumed bytes; no replacement decoding, newline conversion or locale behavior is introduced.

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. Read the status →

Module std.io

import std.io;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

ReadText

pub fn ReadText<S>(Source: mut S&) -> Result<String, StreamReadError> where S: Reader

Collects and strictly decodes a complete UTF-8 stream. Validation occurs after EOF, so a Unicode sequence may span short reads. Invalid encoding and allocation/provider failures retain consumed bytes; no replacement decoding, newline conversion or locale behavior is introduced. S: Structural Reader source type. Source: Borrowed mutable stream, retained through completion. Return: owned immutable text or failure owning the consumed byte prefix. Warning: May allocate and block until EOF; text construction copies collected bytes.

Example

module example.stream_text;
from std.io import ReadBytes, ReadText, WriteText, IoError;
from std.prelude import Result;
class Stream {
    pub Input: readonly byte[];
    pub Offset: usize;
    pub Written: usize;
    pub FailAfterTwo: bool;
    pub init(Input: readonly byte[], FailAfterTwo: bool) { this.Input = Input; this.Offset = 0; this.Written = 0; this.FailAfterTwo = FailAfterTwo; }
    pub fn Read(Output: mut byte[]) -> Result<usize, IoError> {
        if Output.Length == 0 || this.Offset == this.Input.Length { return .Ok { Value = 0 }; }
        if this.FailAfterTwo && this.Offset == 2 { Output[0] = this.Input[this.Offset]; this.Offset += 1; return .Err { Error = .Failure { Reason = .Interrupted, Transferred = 1 } }; }
        Output[0] = this.Input[this.Offset]; this.Offset += 1; return .Ok { Value = 1 };
    }
    pub fn Write(Input: readonly byte[]) -> Result<usize, IoError> {
        if Input.Length == 0 { return .Ok { Value = 0 }; }
        this.Written += 1; return .Ok { Value = 1 };
    }
    pub fn Flush() -> Result<void, IoError> { return .Ok; }
}
fn Main() -> i32 {
    // U+03BB spans two one-byte provider reads; NUL is valid text content.
    let Input: byte[4] = [0xCE_byte, 0xBB_byte, 0_byte, 0x61_byte];
    var Source = Stream(Input, false);
    var Text = switch ReadText(Source) { case .Ok { Value = Value } => break Value; case .Err => return 1; };
    if Text.View != "λ\0a" { return 2; }
    if WriteText(Source, Text.View) is .Err { Error = _ } { return 3; }
    if Source.Written != 4 { return 4; }
    let Invalid: byte[1] = [0xFF_byte];
    var InvalidSource = Stream(Invalid, false);
    // Match one enum layer at a time while preserving each original fallback.
    switch ReadText(InvalidSource) {
        case .Err { Error = Error } => {
            if Error.Bytes.Length != 1 || Error.Bytes.At(0) != 0xFF_byte { return 5; }
            switch Error.Reason {
                case .Failure { Reason = PatternPayload5012, Transferred = Count } if (PatternPayload5012 is .InvalidUtf8) => { if Count != 1 { return 6; } }
                default => return 7;
            }
        }
        case .Ok => return 8;
    }
    var FailingSource = Stream(Input, true);
    switch ReadBytes(FailingSource) {
        case .Err { Error = Error } => {
            if Error.Bytes.Length != 3 || Error.Bytes.At(2) != 0_byte || FailingSource.Offset != 3 { return 9; }
            switch Error.Reason {
                case .Failure { Reason = PatternPayload5013, Transferred = Count } if (PatternPayload5013 is .Interrupted) => { if Count != 3 { return 10; } }
                default => return 11;
            }
        }
        case .Ok => return 12;
    }
    return 0;
}
Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library