Browse the docs

silk.io.writer.

The Writer effect: write bytes without knowing where they go.

When to use#

Require &mut Writer in a function that writes output, such as text for a person or a file format. The caller decides where the bytes go when it provides the writer. Use silk.text.format.Format to write values as text. Use silk.io.logger.Logger for log events.

Details#

A function that needs a writer has ? &mut Writer in its type. The caller supplies a provider with Effect.provideMut<Writer>(&mut provider). A provider is any type that implements Writer.writeAll and Writer.flush, and optionally Writer.writeVectored. silk.io.writer_native has StdoutWriter and StderrWriter. silk.io.buffered_output collects small writes into larger ones. A test can provide a writer that keeps the bytes in memory.

Writer.writeVectored writes several slices as one. A provider with no faster way to do it leaves it out and gets the default, one writeAll for each slice.

Errors#

  • WriterError if the provider cannot complete a write or a flush. Bytes that the provider accepted before the failure stay written.

Gotchas#

The providers in silk.io.writer_native exist only on targets with a system libc (Darwin, or Linux with GNU libc).

Examples#

Write to a provider that counts bytes#

silk
import silk.core.effect { Effect }
import silk.io.writer { Writer, WriterError }

struct CountingWriter {
  count: usize,
}

impl Writer for CountingWriter {
  effect fn writeAll(self: &mut Self, value: &[u8]) -> ()
    ! WriterError
    ? &mut Writer {
    self.count = self.count + value.length
    return ()
  }

  effect fn flush(self: &mut Self) -> ()
    ! WriterError
    ? &mut Writer {
    return ()
  }
}

effect fn greet() -> ()
  ! WriterError
  ? &mut Writer {
  run Writer.writeString("Hello, ")
  run Writer.writeString("world\n")
  return run Writer.flush()
}

pub effect fn main() -> i32
  ! WriterError {
  let mut writer = CountingWriter { count: 0 }
  run greet() |> Effect.provideMut<Writer>(&mut writer)
  if writer.count != 13 {
    return 1
  }
  return 0
}

See also#

  • silk.text.format to write numbers, strings, and templates.

  • silk.io.buffered_output to make fewer, larger writes.

Import as Writer with import silk.io.writer { Writer }.

Public declarations: 2.

WriterError#

silk
pub struct WriterError

The error when a Writer provider cannot complete a write or a flush. Make one with Writer.failure.

Implementation Debug for WriterError#

silk
impl Debug for WriterError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the message, as WriterError { message: "..." }.

Writer#

silk
pub service Writer

The effect that receives output bytes, without the writer knowing where they go.

When to use#

Require &mut Writer in a function that writes output, such as text for a person or a file format. The caller decides where the bytes go when it provides the writer, with Effect.provideMut<Writer>(&mut provider). Use silk.text.format.Format to write values as text, and silk.io.logger.Logger for log events. silk.io.writer_native has StdoutWriter and StderrWriter, and silk.io.buffered_output collects small writes into larger ones.

Details#

A provider implements Writer.writeAll and Writer.flush, and optionally Writer.writeVectored. Code that writes calls them through the effect, as run Writer.writeAll(bytes), and does not know which provider it uses. A provider with no faster way to write several slices leaves writeVectored out and gets the default, one writeAll for each slice.

Operation writeAll#

silk
effect fn writeAll(val: &[u8]) -> () ! WriterError ? &mut Writer

Writes all of val. It returns only after the provider accepted every byte or failed.

Errors#

  • WriterError if the provider fails. Some bytes can be written before the failure.

Operation writeVectored#

silk
effect fn writeVectored(vals: &[&[u8]]) -> () ! WriterError ? &mut Writer

Writes all bytes of each slice of vals, in order, as if they were one slice.

When to use#

Use writeVectored for a message that is in several parts, such as a header and a body, without first copying the parts together.

Details#

A provider can send all parts in one operation, such as one writev system call. A provider with no such operation leaves it out, and this default calls writeAll once for each part. Empty slices write nothing.

Errors#

  • WriterError if the provider fails. Some bytes can be written before the failure.

Operation flush#

silk
effect fn flush() -> () ! WriterError ? &mut Writer

Asks the provider to send any bytes that it holds in a buffer to their destination.

Errors#

Implementation Writer#

silk
impl Writer

Associated function failure#

silk
pub fn failure() -> WriterError

Returns a WriterError. A provider returns it when a write or a flush fails.

Method ignoreError#

silk
pub effect fn ignoreError<A, E, ?R>(self: once Effect<A ! E ? R>) -> A | () ? R

Runs self and returns its value. If it fails, returns () and drops the error.

When to use#

Use ignoreError for output where a failure does not matter, such as a diagnostic message in a program that is about to exit.

Gotchas#

The error is lost. The result type is A | (), so the caller cannot tell a failure from a successful ().

Associated function writeString#

silk
pub effect fn writeString(val: string) -> () ! WriterError ? &mut Writer

Writes the UTF-8 bytes of val.

Errors#

  • WriterError if the provider fails. Some bytes can be written before the failure.

Category: Input and output.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page