silk/standard_input
Portable blocking reads of raw standard-input bytes through an explicit provider.
When to use
Require StandardInput for byte-oriented input that should be replaceable in tests. Decode
text separately so invalid input can be handled without losing its original bytes.
Details
Each read writes only a prefix of the caller's mutable buffer and reports the exact committed
count, which may be smaller than the buffer length. For valid non-empty reads, EndOfInput is
ordinary outcome data and promises that no later read will produce bytes. StreamReadError is
reserved for a provider that could not complete a read.
This service is separate from StandardStreams: output commits a complete message or fails,
while input is inherently partial and eventually ends.
Gotchas
The caller must supply a non-empty read buffer. A zero-length native read cannot distinguish available input from end-of-input.
Examples
Read one byte and then observe the end of input
import silk.effect { Effect }
import silk.standard_input as Input
import silk.u8 as u8
import silk.usize as usize
struct OneByte {
complete: bool
}
effect fn read(self: &mut OneByte, buffer: &mut [u8]) -> Input.ReadOutcome
! Input.StreamReadError {
if self.complete {
return Input.endOfInput()
}
buffer[usize.ZERO] = u8.toU8(42)
self.complete = true
return Input.filled(usize.ONE)
}
impl Input.StandardInput for OneByte {
read: OneByte.read
}
effect fn program() -> i32
! Input.StreamReadError {
let mut provider = OneByte {complete: false}
let mut buffer = [u8.toU8(0)]
let first = run Input.receive(&mut buffer)
|> Effect.provideMut<Input.StandardInput>(&mut provider)
if Input.count(&first) != usize.ONE {
return 1
}
let second = run Input.receive(&mut buffer)
|> Effect.provideMut<Input.StandardInput>(&mut provider)
if Input.isEndOfInput(&second) == false {
return 2
}
return u8.toI32(buffer[usize.ZERO])
}
effect fn recover(error: Input.StreamReadError) -> i32 {
return 0
}
pub fn main() -> i32 {
return run Effect.catchAll(program(), recover)
}Import as StandardInput with import silk.standard_input.
Public declarations: 11.
StreamReadError
pub struct StreamReadErrorA typed failure from a standard-input provider that could not complete one read.
readFailure
pub fn readFailure() -> StreamReadErrorCreates a standard-input failure for a provider that cannot complete one read.
Filled
pub struct FilledA read that committed a known prefix of the caller's buffer.
Field count
pub count: usizeThe exact number of leading bytes written, which can be less than the buffer length.
EndOfInput
pub struct EndOfInputA valid non-empty read that observed permanent end-of-input without changing the buffer.
ReadOutcome
pub struct ReadOutcomeOne completed read, represented as committed bytes or permanent end-of-input.
Details
End-of-input is outcome data instead of failure. Filled identifies the exact initialized
prefix; bytes after that prefix retain their previous values.
Field value
pub value: silk/standard_input.EndOfInput | silk/standard_input.FilledThe committed-byte count or permanent end-of-input result.
StandardInput
pub service StandardInputA portable blocking service for partial reads of raw standard-input bytes.
When to use
Use this service for replaceable byte input. Decode text in a separate operation after each read when text validation is required.
Details
read changes only the reported leading prefix of the buffer. The committed count can be less
than the buffer length. A host error produces StreamReadError; end-of-input does not.
After EndOfInput from a valid non-empty read, later reads do not produce bytes.
Operation read
effect fn read(buffer: &mut [u8]) -> ReadOutcome ! StreamReadError ? &mut StandardInputReads at most the buffer length and reports the exact committed prefix or end-of-input.
Details
Bytes after a Filled count keep their previous values. For a valid non-empty buffer,
EndOfInput means no later call produces bytes. Provider failure produces StreamReadError.
Gotchas
buffer must be non-empty. A native provider cannot distinguish a zero-capacity read from
end-of-input.
filled
pub fn filled(count: usize) -> ReadOutcomeCreates an outcome for a read that committed exactly count leading bytes.
Gotchas
A provider must not use a count greater than the buffer length passed to its read operation.
endOfInput
pub fn endOfInput() -> ReadOutcomeCreates an outcome that reports permanent end-of-input after a valid non-empty read.
count
pub fn count(outcome: &silk/standard_input.ReadOutcome) -> usizeReturns the committed byte count, or zero for end-of-input.
Gotchas
A zero count does not by itself identify end-of-input. Use isEndOfInput when that
distinction controls another read.
isEndOfInput
pub fn isEndOfInput(outcome: &silk/standard_input.ReadOutcome) -> boolReports whether the outcome guarantees that no later read produces bytes.
receive
pub effect fn receive(buffer: &mut [u8]) -> ReadOutcome ! StreamReadError ? &mut StandardInputReads through the active StandardInput provider into a mutable buffer.
Details
This wrapper preserves partial-read behavior and the exclusive provider requirement. Inspect
count before reading buffer bytes. Use isEndOfInput to decide when draining is complete.
Gotchas
buffer must be non-empty. A native provider can otherwise report end-of-input while bytes are
still available.