(std ports)

Reference

Overview

Byte-level I/O operations, CML event-driven reads, streaming conversions, and port adapters.

(import (std ports))

;; Read a 4-byte length header followed by the payload.
(defbjo (read-frame in)
  (match (read-bytes in 4)
    ((Some header) (read-bytes in (frame-length header)))
    (None None)))
;; Read available bytes with a 1-second timeout.
(match (sync (choose (read-some-evt in)
                     (wrap (timeout (seconds 1)) (fun (_) (Ok None)))))
  ((Ok (Some bytes)) (use bytes))
  ((Ok None) (log "EOF or stream completed"))
  ((Err e) (raise e)))
;; In-memory bidirectional pipe for unit testing without network/file I/O.
(match (byte-pipe)
  ((Tuple in out)
   (write-string out "hello\n")
   (close-output-port out)
   (read-line in)))           ; "hello"

An InputPort represents an underlying stream of binary bytes. Textual functions like read-line and read-char decode UTF-8 data from the port. Binary functions like read-some, read-bytes, and peek-bytes read raw byte sequences directly. Both textual and binary operations can be interleaved on the same port.

An OutputPort supports both UTF-8 text (write-string, write-char) and binary byte arrays (write-bytes!).

Event-based reads in choose. Inbound data read from the underlying stream is stored in the port’s internal buffer. An event-based read consumes bytes from this buffer only when its branch wins synchronization in choose. If another branch synchronizes first, no bytes are consumed, leaving the buffered bytes available for subsequent read operations.

Byte-reading operations are available as CML events: read-some-evt, read-bytes-evt, and eof-evt. Synchronous wrappers (read-some, read-bytes) synchronize these events directly.

Draining and streaming. port->list, port->vec, and port->lines eagerly consume a port until EOF. port->seq and file->seq provide lazy evaluation sequences. port->chan offloads reads to a dedicated background fiber that sends items over a channel.

Stream adapters. Files are opened via prelude functions open-input-file and open-output-file. .NET Stream instances can be adapted using stream->input-port and stream->output-port. Bidirectional network streams are supported via (std net).

See BjolangRuntime/BjoInputPort.cs for input port implementation details.

See also: read-some-evt, read-some, read-bytes, peek-bytes, write-bytes!, shutdown!, byte-pipe, port->vec, port->chan

Reference

Types

Functions

Types

Stream

type alias ↑ Types

The .NET System.IO.Stream type wrapped by Bjolang ports.

See also: stream->input-port, stream->output-port

Functions

port->list

function ↑ Functions

(: port->list (-> (-?-> InputPort %a) InputPort (List %a)))
(port->list reader p)

Consumes items from a port until EOF, returning them as a list.

reader
Reader function or bjoroutine invoked to read each item.
p
The input port.
returns
A list of read items in order of occurrence.
(port->list read-char (open-input-string "abc"))   ; (#\\a #\\b #\\c)

The reader is invoked repeatedly while port-eof? returns #f. The reader must consume input on each invocation to prevent an infinite loop.

If reader is a bjoroutine, calls suspend cooperatively. If it is a standard synchronous function, calls block the active thread. The port is not closed automatically.

See also: port->vec, port->lines, port->seq, port->chan

port->vec

function ↑ Functions

(: port->vec (-> (-?-> InputPort %a) InputPort (Vec %a)))
(port->vec reader p)

Consumes items from a port until EOF, returning them as a vector.

reader
Reader function or bjoroutine invoked to read each item.
p
The input port.
returns
A vector containing all read items in order.

Equivalent to port->list, but collects items into an indexed vector.

See also: port->list, port->lines, port->chan

port->lines

function ↑ Functions

(: port->lines (-> InputPort (#:mode LineMode) (Vec string)))
(port->lines port #:mode Any)

Reads all remaining lines from a port into a list.

port
The input port.
#:mode
Line delimiter mode (defaults to Any).
returns
A list of strings containing remaining lines without delimiters.

Reads synchronously using read-line. To suspend cooperatively within a bjoroutine, use port->vec with a bjoroutine reader.

See also: port->vec, read-line, LineMode

port->seq

function ↑ Functions

(: port->seq (-> (-> InputPort %a) InputPort (Seq %a)))
(port->seq reader p)

Returns a lazy sequence of items read from a port.

reader
Reader function invoked to produce each item.
p
The input port.
returns
A lazy sequence that reads from the port as elements are evaluated.

Items are read on demand during sequence iteration, not at sequence creation time. The port is not closed upon completion. Reading mutates port state, so repeated traversals continue from where the previous traversal ended.

Sequence evaluation cannot suspend cooperatively; within a bjoroutine, use port->vec or port->chan instead.

See also: port->vec, port->chan, file->seq

file->seq

function ↑ Functions

(: file->seq (-> (-> InputPort %a) string (Result Exception (Seq %a))))
(file->seq reader path)

Returns a lazy sequence of items read from a file path.

reader
Reader function invoked on the file's input port.
path
Path to the target file.
returns
(Ok seq) on success, or (Err e) if the file cannot be opened.

The file is initially opened to verify accessibility and immediately closed. Each sequence iteration opens the file anew, reads from the beginning, and closes it upon reaching EOF.

See also: file-read/seq, port->seq

port->chan

function ↑ Functions

(: port->chan (-> (-bjo-> InputPort %a) InputPort (Tuple (Chan %a) (Promise int))))
(port->chan reader p)

Spawns a fiber that reads items from a port and streams them over a channel.

reader
Bjoroutine reader invoked to read each item.
p
The input port.
returns
A tuple containing the output channel and a completion promise holding the count of read items.
raises Bjolang.Runtime.ScopeEnded
When invoked outside an ambient structured concurrency scope.
(match (port->chan read-line port)
  ((Tuple lines done)
   (let go ()
     (match (chan-next lines done)
       ((Some line) (handle line) (go))
       (None 'finished)))))

The producer fiber executes within the ambient scope. The unbuffered channel ensures backpressure: the worker fiber reads the next item only after the receiver consumes the previous one. The port is not closed automatically.

If the reader throws an exception, the completion promise fails and no further items are emitted.

See also: chan-next, port->vec

chan-next

function ↑ Functions

(: chan-next (-bjo-> (Chan %a) (Promise int) (Option %a)))
(chan-next c done)

Fetches the next item from a port->chan stream, or None at EOF.

c
The channel returned by port->chan.
done
The completion promise returned by port->chan.
returns
(Some item) if an item is available, or None if the stream completed.

Synchronizes on both the channel and the completion promise. To check for errors after None is returned, join the completion promise: (sync (promise-join done)).

See also: port->chan

read-some-evt

function ↑ Functions

(: read-some-evt (-> InputPort (Event (Result Exception (Option (Array byte))))))
(read-some-evt p)

Returns a CML event that reads available bytes from the port buffer.

p
The input port.
returns
An event yielding (Ok (Some bytes)) with at least 1 byte, (Ok None) at EOF, or (Err e) on I/O failure.

First-class CML event. If another branch in choose synchronizes first, no bytes are consumed and the buffer contents remain intact.

The event is ephemeral: each synchronization evaluates against the current port state, allowing repeated reads in a loop without stale cached results.

See also: read-some, read-bytes-evt, eof-evt

read-bytes-evt

function ↑ Functions

(: read-bytes-evt (-> InputPort int (Event (Result Exception (Option (Array byte))))))
(read-bytes-evt p n)

Returns a CML event that reads exactly n bytes, or remaining bytes at EOF.

p
The input port.
n
Target byte count. Must be at least 1.
returns
An event yielding (Ok (Some bytes)), (Ok None) at EOF, or (Err e) on failure.
raises System.ArgumentOutOfRangeException
When n is less than 1.

If EOF is reached before n bytes are read, any remaining bytes are yielded as (Some bytes), and the subsequent read yields None.

See also: read-bytes, read-some-evt

eof-evt

function ↑ Functions

(: eof-evt (-> InputPort (Event Unit)))
(eof-evt p)

Returns a CML event that triggers when a port reaches EOF or encounters an error.

p
The input port.
returns
An event enabled when no further bytes can be read.

Triggers when the port buffer is exhausted and no further input can arrive. Useful for detecting peer disconnections in network protocols.

See also: read-some-evt, port-eof?

read-some

function ↑ Functions

(: read-some (-> InputPort (Option (Array byte))))
(read-some p)

Reads available bytes from the port, blocking or suspending until at least one byte arrives.

p
The input port.
returns
(Some bytes) containing at least 1 byte, or None at EOF.
raises System.IO.IOException
When an underlying stream I/O failure occurs.

Synchronizes on read-some-evt. Suspends cooperatively within a bjoroutine; blocks the thread in standard synchronous code.

See also: read-some-evt, read-bytes

read-bytes

function ↑ Functions

(: read-bytes (-> InputPort int (Option (Array byte))))
(read-bytes p n)

Reads exactly n bytes, or remaining bytes at EOF.

p
The input port.
n
Number of bytes to read. Must be at least 1.
returns
(Some bytes) (shorter than n only at EOF), or None if already at EOF.
raises System.ArgumentOutOfRangeException
When n is less than 1.
raises System.IO.IOException
When an underlying stream I/O failure occurs.

See also: read-bytes-evt, read-some, peek-bytes

peek-bytes

function ↑ Functions

(: peek-bytes (-> InputPort int int (Option (Array byte))))
(peek-bytes p skip count)

Inspects bytes ahead of the port cursor without consuming them.

p
The input port.
skip
Number of bytes to skip before peeking. Must be non-negative.
count
Number of bytes to peek. Must be non-negative.
returns
(Some bytes) (shorter than count at EOF), or None if EOF occurs before skip.
raises System.ArgumentOutOfRangeException
When skip or count is negative.
raises System.IO.IOException
When the stream fails and the buffer is empty.
;; Inspect magic bytes before choosing a decompression strategy:
(match (peek-bytes in 0 2)
  ((Some magic) (if (gzip-magic? magic) (inflate in) (plain in)))
  (None (empty)))

Buffers data until the requested range is satisfied or EOF is reached. Bytes remain in the port buffer and can subsequently be consumed by read-bytes or textual readers.

See also: read-bytes, reencode-input-port

write-bytes!

function ↑ Functions

(: write-bytes! (-> OutputPort (Array byte) void))
(write-bytes! p bytes)

Writes a byte array to an output port.

p
The output port.
bytes
Byte array to write.
raises System.InvalidOperationException
When called after shutdown! has closed the output side.

Output ports are buffered. Writes that fill the buffer trigger a flush to the underlying stream, suspending cooperatively in fibers or blocking in synchronous functions.

See also: flush-port, shutdown!, write-string

shutdown!

function ↑ Functions

(: shutdown! (-> OutputPort void))
(shutdown! p)

Shuts down the write half of a duplex port while keeping the read half open.

p
The output port.

Flushes buffered data and transmits a shutdown signal (e.g. TCP FIN or pipe EOF) to the peer. Subsequent write operations throw InvalidOperationException. The port must still be closed with close-output-port to release underlying system handles.

See also: write-bytes!, flush-port, byte-pipe

limited

function ↑ Functions

(: limited (-> InputPort int InputPort))
(limited p n)

Wraps an input port to read at most n bytes before reporting EOF.

p
The source input port.
n
Maximum number of bytes to read. Must be non-negative.
returns
A new limited input port reading through p.
raises System.ArgumentOutOfRangeException
When n is negative.
;; Read a fixed-length HTTP body as text lines without consuming trailing data:
(port->lines (limited conn content-length))

Reads through the underlying port’s buffer without skipping or duplicating data. Closing the limited port does not close the underlying source port.

See also: byte-pipe, reencode-input-port

byte-pipe

function ↑ Functions

(: byte-pipe (-> (Tuple InputPort OutputPort)))
(byte-pipe)

Creates an in-memory duplex byte pipe.

returns
A pair of (input-port, output-port).

An unbounded in-memory pipe suitable for testing and internal message buffering. Writes do not block. Closing or shutting down the output port signals EOF to the input port once buffered bytes are drained.

See also: limited, shutdown!, stream->input-port

stream->input-port

function ↑ Functions

(: stream->input-port (-> Stream InputPort))
(stream->input-port s)

Wraps a .NET Stream in a Bjolang input port.

s
The .NET Stream instance.
returns
A new input port reading from s.
raises Bjolang.Runtime.ScopeEnded
When called without an ambient structured concurrency scope.

The port takes ownership of the stream. Closing the port or exiting the ambient concurrency scope disposes the underlying stream.

See also: stream->output-port

stream->output-port

function ↑ Functions

(: stream->output-port (-> Stream OutputPort))
(stream->output-port s)

Wraps a .NET Stream in a Bjolang output port.

s
The .NET Stream instance.
returns
A new output port writing to s.
raises Bjolang.Runtime.ScopeEnded
When called without an ambient structured concurrency scope.

The port takes ownership of the stream. Closing the port or exiting the ambient concurrency scope flushes and disposes the underlying stream.

See also: stream->input-port

reencode-input-port

function ↑ Functions

(: reencode-input-port (-> InputPort Encoding InputPort))
(reencode-input-port p encoding)

Wraps an input port to transcode bytes from a specified encoding into UTF-8.

p
The source input port.
encoding
Source text encoding from (text encodings).
returns
A new input port yielding UTF-8 bytes.
(import (only (text encodings) windows-1252))

(read-line (reencode-input-port in windows-1252))

Transcodes input on the fly into UTF-8. Unrecognized byte sequences are replaced with U+FFFD. Closing the re-encoded port does not close the underlying source port.

See also: reencode-output-port, peek-bytes, Encoding

reencode-output-port

function ↑ Functions

(: reencode-output-port (-> OutputPort Encoding OutputPort))
(reencode-output-port p encoding)

Wraps an output port to transcode outgoing UTF-8 bytes into a specified target encoding.

p
The destination output port.
encoding
Target text encoding from (text encodings).
returns
A new output port accepting UTF-8 bytes.

Transcodes UTF-8 input into the target encoding before writing to p. Characters not representable in the target encoding are replaced with fallback characters. Closing the wrapped port flushes remaining data to p while leaving p open.

See also: reencode-input-port, Encoding