pub struct PipeTransport<W, R>{ /* private fields */ }Expand description
Pipe-based transport for communicating with Playwright server
This implementation matches playwright-python’s PipeTransport:
- Messages are framed with 4-byte little-endian length prefix
- Reads happen in a background task
- Received messages are sent via mpsc channel
§Architecture
┌─────────────┐
│ Server │
│ (Node.js) │
└──────┬──────┘
│ stdio
│
┌──────▼──────────────────────┐
│ PipeTransport │
│ ┌────────┐ ┌──────────┐ │
│ │ Writer │ │ Reader │ │
│ │ (send) │ │ (loop) │ │
│ └────────┘ └──────────┘ │
└─────────────────┬───────────┘
│ mpsc channel
▼
┌──────────────┐
│ Connection │
│ (dispatch) │
└──────────────┘§Platform-Specific Cleanup
Windows: The transport takes ownership of stdin/stdout from a Child process.
When the transport is dropped, these handles are closed. On Windows, tokio uses
a blocking threadpool for child process stdio, so proper cleanup requires that
stdio handles be closed before terminating the parent process. See PlaywrightServer
for the platform-specific cleanup logic.
Unix: Standard pipe cleanup applies - no special handling needed.
Implementations§
Source§impl<W, R> PipeTransport<W, R>
impl<W, R> PipeTransport<W, R>
Sourcepub fn new(stdin: W, stdout: R) -> (Self, UnboundedReceiver<JsonValue>)
pub fn new(stdin: W, stdout: R) -> (Self, UnboundedReceiver<JsonValue>)
Create a new pipe transport from child process stdio handles
§Arguments
stdin- Child process stdin for sending messagesstdout- Child process stdout for receiving messages
Returns a tuple of (PipeTransport, message receiver channel)
§Example
let mut child = Command::new("node")
.arg("cli.js")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.spawn()?;
let stdin = child.stdin.take().unwrap();
let stdout = child.stdout.take().unwrap();
let (mut transport, mut rx) = PipeTransport::new(stdin, stdout);
// Spawn read loop
tokio::spawn(async move {
transport.run().await
});
// Receive messages
while let Some(message) = rx.recv().await {
println!("Received: {:?}", message);
}Sourcepub fn into_parts(self) -> (W, PipeTransportReceiver<R>)
pub fn into_parts(self) -> (W, PipeTransportReceiver<R>)
Split the transport into stdin and the rest
This allows Connection to hold stdin separately (for sending) while run() owns stdout (for receiving).
§Returns
Returns (stdin, self_without_stdin) where self_without_stdin can still run the receive loop but cannot send.
Sourcepub async fn run(&mut self) -> Result<()>
pub async fn run(&mut self) -> Result<()>
Run the message read loop
This continuously reads messages from the server and sends them
to the message channel. Matches playwright-python’s run() method.
For messages larger than 32KB, reads in chunks to reduce peak memory usage. Matches playwright-python’s chunked reading strategy.
The loop will run until:
- An error occurs
- The stdout stream is closed
- The message channel is dropped
§Errors
Returns an error if reading from stdout fails or if message parsing fails.