Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
0.2.0 Preview 1 · Frozen documentation

BufferedWriter

Owns a fixed-capacity byte cache and its concrete Writer source. Construction allocates; subsequent cache operations do not grow storage. External synchronization is required. Movement transfers the source and cache, leaving the old adapter closed. Destruction never performs hidden I/O.

Sn is under heavy development. Reference extracted from this release’s bundled standard library. Public API examples are not an exhaustive compatibility test. Read the matching release guide for tested workflows and limitations. 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.

BufferedWriter

pub final class BufferedWriter<S> where S: Writer, Movable

Owns a fixed-capacity byte cache and its concrete Writer source. Construction allocates; subsequent cache operations do not grow storage. External synchronization is required. Movement transfers the source and cache, leaving the old adapter closed. Destruction never performs hidden I/O. S: Movable structural Writer implementation.

A provider may report failure after accepting bytes. This workflow proves that the buffer retains only the tail and retries without duplicate output.

Example

module example.buffered_streams;
from std.io import BufferedReader, BufferedWriter, IoError;
from std.prelude import Result;
struct Source {
    pub Written: usize;
    pub ReadCount: usize;
    pub FailNext: bool;
    pub init() { this.Written = 0; this.ReadCount = 0; this.FailNext = true; }
    pub fn Write(Input: readonly byte[]) -> Result<usize, IoError> {
        if this.FailNext { this.FailNext = false; return .Err { Error = .Failure { Reason = .Interrupted, Transferred = 0 } }; }
        if Input.Length == 0 { return .Ok { Value = 0 }; }
        this.Written += 1; return .Ok { Value = 1 };
    }
    pub fn Flush() -> Result<void, IoError> { return .Ok; }
    pub fn Read(Output: mut byte[]) -> Result<usize, IoError> {
        if this.ReadCount != 0 || Output.Length == 0 { return .Ok { Value = 0 }; }
        Output[0] = 0x61_byte; this.ReadCount += 1; return .Ok { Value = 1 };
    }
}
fn Main() -> i32 {
    var Writer = {
        // Keep writable result storage through the explicit noncopy payload transfer.
        var WriterCreation = BufferedWriter<Source>.TryCreate(Source(), 2);
        switch WriterCreation {
            case .Ok { Value = Value: mut BufferedWriter<Source>& } => break move(Value);
            case .Err => return 1;
        }
    };
    let Input: byte[2] = [0x61_byte, 0x62_byte];
    if Writer.Write(Input) is .Err { Error = _ } { return 2; }
    if Writer.BufferedLength != 2 || Writer.Capacity != 2 || Writer.IsClosed { return 3; }
    switch Writer.Flush() { case .Err { Error = Failure } => { switch Failure { case .Failure { Reason = Reason, Transferred = Count } if (Reason is .Interrupted) => { if Count != 0 { return 4; } } default => return 5; } } default => return 5; }
    if Writer.BufferedLength != 2 { return 6; }
    var Finished = switch Writer.TryFinish() { case .Ok { Value = Value } => break Value; case .Err => return 7; };
    if Finished.Written != 2 || !Writer.IsClosed { return 8; }
    var Reader = {
        // Keep writable result storage through the explicit noncopy payload transfer.
        var ReaderCreation = BufferedReader<Source>.TryCreate(Source(), 2);
        switch ReaderCreation {
            case .Ok { Value = Value: mut BufferedReader<Source>& } => break move(Value);
            case .Err => return 9;
        }
    };
    var Moved = move(Reader);
    if !Reader.IsClosed { return 10; }
    var Output: byte[1] = [0_byte];
    switch Moved.Read(Output) { case .Ok { Value = Count } => { if Count != 1 || Output[0] != 0x61_byte { return 11; } } case .Err => return 12; }
    switch Moved.Read(Output) { case .Ok { Value = Count } => { if Count != 0 { return 13; } } case .Err => return 14; }
    var Original = Moved.DiscardBufferedBytesAndTakeSource();
    if !Moved.IsClosed || Original.ReadCount != 1 { return 15; }
    switch BufferedWriter<Source>.TryCreate(Source(), 0) {
        case .Err { Error = Error } => { if !Error.Source.FailNext { return 16; } switch Error.Reason { case .Failure { Reason = Reason } if (Reason is .InvalidInput) => {} default => return 17; } }
        case .Ok => return 18;
    }
    return 0;
}

Example

module example.buffered_partial_write;
from std.io import BufferedWriter, IoError;
from std.prelude import Result;
struct CountedSink {
    pub Written: usize;
    pub Failed: bool;
    pub init() { this.Written = 0; this.Failed = false; }
    pub fn Write(Input: readonly byte[]) -> Result<usize, IoError> {
        if Input.Length == 0 { return .Ok { Value = 0 }; }
        // Model an actual byte commit followed by a provider cleanup failure.
        this.Written += 1;
        if !this.Failed { this.Failed = true; return .Err { Error = .Failure { Reason = .AccessDenied, Transferred = 1 } }; }
        return .Ok { Value = 1 };
    }
    pub fn Flush() -> Result<void, IoError> { return .Ok; }
}
fn Main() -> i32 {
    var Writer = {
        // Scoped writable carriers end immediately after explicit payload transfer.
        var WriterCreation = BufferedWriter<CountedSink>.TryCreate(CountedSink(), 2);
        switch WriterCreation {
            case .Ok { Value = Value: mut BufferedWriter<CountedSink>& } => break move(Value);
            case .Err => return 1;
        }
    };
    let Input: byte[2] = [0x41_byte, 0x42_byte];
    switch Writer.Write(Input) { case .Ok { Value = Count } => { if Count != 2 { return 2; } } case .Err => return 3; }
    switch Writer.Flush() {
        case .Err { Error = PatternPayload5001 } => {
            switch PatternPayload5001 {
                case .Failure { Reason = PatternPayload5002, Transferred = Count } if (PatternPayload5002 is .AccessDenied) => { if Count != 1 { return 4; } }
                default => return 5;
            }
        }
        default => return 5;
    }
    if Writer.BufferedLength != 1 { return 6; }
    var Finished = switch Writer.TryFinish() { case .Ok { Value = Value } => break Value; case .Err => return 7; };
    if Finished.Written != 2 || !Writer.IsClosed { return 8; }
    // The committed first byte was removed from the cache and never replayed.
    return 0;
}

BufferedWriter.init

pub init(Source: readonly Self&) = delete;

Rejects implicit source/cache copying. Source: Existing adapter.

BufferedWriter.operator

pub fn operator =(Source: readonly Self&) -> void = delete;

Rejects replacement that could silently discard pending bytes. Source: Existing adapter. Return: No runtime result; this assignment is deleted and cannot be invoked.

BufferedWriter.operator

pub fn operator =(Source: mut Self&&) -> void = delete;

Requires explicit finishing/extraction before replacing an adapter. Source: Existing adapter. Return: No runtime result; this assignment is deleted and cannot be invoked.

BufferedWriter.Capacity

pub Capacity: usize;

Observes initialized cache capacity in bytes.

BufferedWriter.IsClosed

pub IsClosed: bool;

Observes extraction/movement closure without I/O.

BufferedWriter.TryCreate

pub static fn TryCreate(mut Source: S, Capacity: usize) -> Result<Self, BufferedStreamCreationError<S>>

Allocates initialized cache slots and transfers a concrete source. Source: Owned source; returned in the error on failure. Capacity: Positive cache capacity in bytes; default is 8192. Return: Adapter or error retaining the source; no stream I/O occurs. Warning: May allocate.

BufferedWriter.TryCreate

pub static fn TryCreate(mut Source: S) -> Result<Self, BufferedStreamCreationError<S>>

Supplies the omitted arguments to TryCreate. Note: Defaults: Capacity = DefaultBufferCapacity. Source: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's owned success value or typed failure.

BufferedWriter.init

pub init(Source: mut Self&&)

Transfers pending bytes without flushing. Source: Adapter left closed.

BufferedWriter.BufferedLength

pub BufferedLength: usize;

Counts accepted bytes not yet submitted to the source.

BufferedWriter.Write

pub fn Write(Input: readonly byte[]) -> Result<usize, IoError>

Accepts input into owned cache, draining full cache when necessary. Input: Borrowed bytes copied during this call. Return: Accepted input count or failure counting only this call's accepted prefix. Warning: May block in source writes; never implicitly calls source Flush.

BufferedWriter.Flush

pub fn Flush() -> Result<void, IoError>

Submits pending bytes and then flushes downstream layers. Return: Success or failure counting bytes submitted from this cache in this call. Warning: May block; never promises durable storage. Unwritten tail survives failure.

BufferedWriter.TryFinish

pub fn TryFinish() -> Result<S, IoError>

Flushes successfully before transferring the source. Return: Owned source, or failure leaving this adapter available for retry. Warning: May block. Destruction alone discards pending bytes without flushing.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library