Browse the docs

silk.io.standard_input.

The StandardInput effect: read raw bytes from standard input.

When to use#

Require &mut StandardInput in code that reads standard input, so a test can provide the bytes. To parse lines or other units, use silk.io.buffered_input.BufferedInput.fillStandard. Decode text after you read the bytes, so invalid UTF-8 does not lose data.

Details#

StandardInput.receive fills a prefix of the buffer and returns the number of bytes, which can be less than the buffer length. When the input ends, it returns an end-of-input outcome. End of input is a normal result, not an error. After it, no later read returns bytes.

This effect is separate from silk.io.writer.Writer: a write completes or fails, but a read can return part of the data and the input ends at some point.

Errors#

Gotchas#

An empty buffer returns a count of 0 and does not read. It never reports end of input. Use a buffer of at least one byte.

Examples#

Provide input in a test and read it to the end#

silk
import silk.core.effect { Effect }
import silk.io.standard_input { ReadOutcome, StandardInput, StreamReadError }

struct OneByte {
  complete: bool,
}

effect fn read(self: &mut OneByte, buffer: &mut [u8]) -> ReadOutcome
  ! StreamReadError {
  if buffer.length == 0 {
    return StandardInput.filled(0)
  }
  if self.complete {
    return StandardInput.endOfInput()
  }
  buffer[0] = 42
  self.complete = true
  return StandardInput.filled(1)
}

impl StandardInput for OneByte {
  read: OneByte.read
}

pub effect fn main() -> i32
  ! StreamReadError {
  let mut provider = OneByte { complete: false }
  let mut buffer: [u8; 4] = [0, 0, 0, 0]
  let first = run StandardInput.receive(&mut buffer)
    |> Effect.provideMut<StandardInput>(&mut provider)
  let second = run StandardInput.receive(&mut buffer)
    |> Effect.provideMut<StandardInput>(&mut provider)
  if StandardInput.count(&first) != 1 || buffer[0] != 42 || !StandardInput.isEndOfInput(&second) {
    return 1
  }
  return 0
}

Import as StandardInput with import silk.io.standard_input { StandardInput }.

Public declarations: 5.

StreamReadError#

silk
pub struct StreamReadError

The error when a standard input provider cannot complete a read.

Implementation Debug for StreamReadError#

silk
impl Debug for StreamReadError

Operation debug#

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

Writes StreamReadError.

Filled#

silk
pub struct Filled

A read that put count bytes at the start of the buffer.

Field count#

silk
pub count: usize

The number of bytes at the start of the buffer. It can be less than the buffer length.

EndOfInput#

silk
pub struct EndOfInput

The input ended. The buffer did not change, and no later read returns bytes.

ReadOutcome#

silk
pub struct ReadOutcome

The result of one read: a count of bytes, or end of input.

Details#

Use StandardInput.count and StandardInput.isEndOfInput, or match on value. After a Filled result, bytes after the count keep their earlier values.

Field value#

silk
pub value: Filled | EndOfInput

The count of bytes, or end of input.

StandardInput#

silk
pub service StandardInput

The effect that reads raw bytes from standard input.

When to use#

Require &mut StandardInput in code that reads standard input, so a test can provide the bytes. To parse lines or other units, use silk.io.buffered_input.BufferedInput.fillStandard. Decode text after you read the bytes, so invalid UTF-8 does not lose data.

Details#

A provider implements read. Callers use StandardInput.receive, which fills a prefix of the buffer and can return fewer bytes than the buffer length. End of input is a normal result, not an error. After it, no later read returns bytes.

Operation read#

silk
effect fn read(
    buffer: &mut [u8]
  ) -> ReadOutcome ! StreamReadError ? &mut StandardInput

Reads up to buffer.length bytes into the start of buffer.

Details#

A provider changes only the bytes that it reports. For a non-empty buffer, it returns at least one byte, or end of input. After end of input, no later read returns bytes.

Errors#

Gotchas#

For an empty buffer, a provider must return a count of 0 and not read, also after end of input.

Implementation StandardInput#

silk
impl StandardInput

Associated function readFailure#

silk
pub fn readFailure() -> StreamReadError

Returns a StreamReadError. Providers use it when a read fails.

Associated function filled#

silk
pub fn filled(count: usize) -> ReadOutcome

Returns the outcome for a read that put count bytes in the buffer. Providers use it.

Gotchas#

count must not be more than the length of the buffer.

Associated function endOfInput#

silk
pub fn endOfInput() -> ReadOutcome

Returns the end-of-input outcome. Providers use it.

Associated function count#

silk
pub fn count(outcome: &ReadOutcome) -> usize

Returns the number of bytes that the read put in the buffer. Returns 0 for end of input.

Gotchas#

A count of 0 does not mean end of input. Use StandardInput.isEndOfInput to decide if more reads can return bytes.

Associated function isEndOfInput#

silk
pub fn isEndOfInput(outcome: &ReadOutcome) -> bool

Returns true if the input ended, so no later read returns bytes.

Associated function receive#

silk
pub effect fn receive(
    buffer: &mut [u8]
  ) -> ReadOutcome ! StreamReadError ? &mut StandardInput

Reads up to buffer.length bytes from the active provider into the start of buffer.

Details#

Read only the first StandardInput.count bytes of the buffer. Read again until StandardInput.isEndOfInput returns true to get all input.

Errors#

Gotchas#

Use a non-empty buffer. An empty buffer never reports end of input.

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