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

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. 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.

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