plushie/bridge
Bridge actor: manages the Erlang Port to the Rust binary.
The bridge is a thin pipe – it receives pre-encoded wire bytes from the runtime and writes them to the port. Inbound port data is decoded and forwarded to the runtime as events.
Transport modes
Spawn(default): spawns the renderer binary as a child process using an Erlang Port.Stdio: reads/writes the BEAM’s own stdin/stdout. Used when the renderer spawns the Gleam process (e.g.plushie --exec).Iostream: sends and receives protocol messages via an external process (the iostream adapter). Used for custom transports like SSH channels, TCP sockets, or WebSockets.
Wire framing
- MessagePack: 4-byte big-endian length prefix (Erlang {packet, 4})
- JSONL: newline-delimited (Erlang {line, 65536})
Types
Messages the bridge actor handles.
pub type BridgeMessage {
Send(data: BitArray)
PortData(data: dynamic.Dynamic)
PortLineData(line_data: ffi.LineData)
PortExit(status: dynamic.Dynamic)
IoStreamData(data: BitArray)
IoStreamClosed
RegisterRuntime(process.Subject(RuntimeNotification))
Shutdown
}
Constructors
-
Send(data: BitArray)Send pre-encoded wire bytes to the Rust binary.
-
PortData(data: dynamic.Dynamic)Port data received from the Rust binary (via selector).
-
PortLineData(line_data: ffi.LineData)Line data received from the Rust binary in JSON mode (via selector).
-
PortExit(status: dynamic.Dynamic)Port closed/exited (via selector).
-
IoStreamData(data: BitArray)Data received from an iostream adapter.
-
IoStreamClosedThe iostream adapter closed the transport.
-
RegisterRuntime(process.Subject(RuntimeNotification))Register the runtime’s notification subject. Sent by the runtime after it starts under the supervisor. Any events received before this message are buffered and flushed on receipt.
-
ShutdownGraceful shutdown request.
Internal bridge state.
pub opaque type BridgeState
Messages sent to an iostream adapter process. The adapter must handle these messages to integrate with a custom transport (TCP, WebSocket, SSH, etc.).
pub type IoStreamMessage {
IoStreamBridge(bridge: process.Subject(BridgeMessage))
IoStreamSend(data: BitArray)
}
Constructors
-
IoStreamBridge(bridge: process.Subject(BridgeMessage))The bridge is registering itself. The adapter should send IoStreamData messages to the bridge subject.
-
IoStreamSend(data: BitArray)The bridge wants to send data over the transport.
Notifications sent from bridge to runtime.
pub type RuntimeNotification {
InboundEvent(decode.InboundMessage)
RendererExited(status: Int)
}
Constructors
-
InboundEvent(decode.InboundMessage)A decoded inbound message from the Rust binary.
-
RendererExited(status: Int)The Rust binary process exited.
Transport mode for the bridge.
pub type Transport {
TransportSpawn
TransportStdio
TransportIoStream(adapter: process.Subject(IoStreamMessage))
}
Constructors
-
TransportSpawnSpawn the renderer binary as a child process.
-
TransportStdioUse the BEAM’s own stdin/stdout.
-
TransportIoStream(adapter: process.Subject(IoStreamMessage))Use a custom iostream adapter process.
Values
pub fn start(
binary_path: String,
format: protocol.Format,
runtime: process.Subject(RuntimeNotification),
session: String,
renderer_args: List(String),
) -> Result(process.Subject(BridgeMessage), actor.StartError)
Start the bridge actor with spawn transport (default).
Opens a port to the plushie binary and begins forwarding messages. Inbound wire data is decoded and sent as RuntimeNotification values to the provided runtime subject.
pub fn start_supervised(
name: process.Name(BridgeMessage),
binary_path: String,
format: protocol.Format,
session: String,
renderer_args: List(String),
transport: Transport,
) -> Result(
actor.Started(process.Subject(BridgeMessage)),
actor.StartError,
)
Start the bridge under a supervisor with a registered name.
The runtime subject is not available yet – the runtime will send
a RegisterRuntime message after it starts. Events received before
registration are buffered and flushed automatically.
pub fn start_with_transport(
binary_path: String,
format: protocol.Format,
runtime: process.Subject(RuntimeNotification),
session: String,
renderer_args: List(String),
transport: Transport,
) -> Result(process.Subject(BridgeMessage), actor.StartError)
Start the bridge actor with an explicit transport mode.