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#
WriterErrorif 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#
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.formatto write numbers, strings, and templates.silk.io.buffered_outputto make fewer, larger writes.
Import as Writer with import silk.io.writer { Writer }.
Public declarations: 2.
WriterError#
pub struct WriterErrorThe error when a Writer provider cannot complete a write or a flush. Make one with
Writer.failure.
Implementation Debug for WriterError#
impl Debug for WriterErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the message, as WriterError { message: "..." }.
Writer#
pub service WriterThe 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#
effect fn writeAll(val: &[u8]) -> () ! WriterError ? &mut WriterWrites all of val. It returns only after the provider accepted every byte or failed.
Errors#
WriterErrorif the provider fails. Some bytes can be written before the failure.
Operation writeVectored#
effect fn writeVectored(vals: &[&[u8]]) -> () ! WriterError ? &mut WriterWrites 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#
WriterErrorif the provider fails. Some bytes can be written before the failure.
Operation flush#
effect fn flush() -> () ! WriterError ? &mut WriterAsks the provider to send any bytes that it holds in a buffer to their destination.
Errors#
WriterErrorif the provider cannot send the bytes.
Implementation Writer#
impl WriterAssociated function failure#
pub fn failure() -> WriterErrorReturns a WriterError. A provider returns it when a write or a flush fails.
Method ignoreError#
pub effect fn ignoreError<A, E, ?R>(self: once Effect<A ! E ? R>) -> A | () ? RRuns 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#
pub effect fn writeString(val: string) -> () ! WriterError ? &mut WriterWrites the UTF-8 bytes of val.
Errors#
WriterErrorif 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.