runnel 0.4.3

the pluggable io stream. now support: stdio, string io, in memory pipe, line pipe
Documentation
# Code Review for `runnel` (v0.4.0)

## 1. Introduction
This review evaluates the `runnel` library, a pluggable I/O stream implementation in Rust. The library provides a clean abstraction for swapping between standard I/O, in-memory strings, and thread-safe pipes.

## 2. Architecture Overview
The core architecture is based on three main traits: `StreamIn`, `StreamOut`, and `StreamErr`. This design is highly extensible and allows users to inject custom I/O implementations easily. The `RunnelIoeBuilder` provides a convenient way to assemble these streams, defaulting to standard I/O when not specified.

### Strengths
- **Decoupling**: Successfully decouples application logic from specific I/O backends.
- **Zero Dependencies**: Implementation is lean and relies only on the standard library.
- **Thread Safety**: Pipe implementations use `mpsc` channels and `Mutex` correctly to handle concurrent access.
- **Builder Pattern**: The builder implementation is idiomatic and user-friendly.

## 3. Module Analysis

### 3.1. `lib.rs` (Core Traits & Builder)
- The `LockAny` trait helper is a clever way to handle poisoned mutexes, ensuring the application can continue even if a thread panicked while holding a lock.
- Traits are well-defined, though `StreamIn` forcing `lock_bufread` for all implementations leads to `unimplemented!()` panics in `linepipeio.rs`.

### 3.2. `medium/stdio.rs`
- Clean and efficient wrappers around `std::io` types.
- Correctly implements `buffer()` as empty for system streams where peeking is not supported.

### 3.3. `medium/stringio.rs`
- **Correction Needed**: The implementation of `BufRead` for `RawStringIn` is non-idiomatic. `fill_buf` should not advance the internal position (`pos`); that is the responsibility of `consume`. While it is currently wrapped in a `BufReader`, having a broken `BufRead` implementation on the inner type is risky.
- **UTF-8 Handling**: `RawStringOut::write` uses `String::from_utf8_lossy`. This is acceptable for a "string" stream but will corrupt data if non-UTF-8 bytes are written.

### 3.4. `medium/pipeio.rs`
- **Performance**: In `RawPipeOut::flush`, `self.buf.clone()` is used. This can be optimized by using `std::mem::take(&mut self.buf)` or `self.buf.split_off(0)` to avoid unnecessary allocations and copies.
- **Robustness**: `RawPipeIn::fill_buf` calls `unwrap()` on `receiver.recv()`. This will cause a panic if the sender is dropped. It should handle the error gracefully, typically by returning an empty buffer (EOF).
- **Correctness**: Similar to `stringio.rs`, `fill_buf` in `RawPipeIn` advances the position, which violates the `BufRead` contract.

### 3.5. `medium/linepipeio.rs`
- **Design Trade-off**: This module intentionally focuses on line-based communication. However, it leaves several `StreamIn`/`StreamOut` methods as `unimplemented!()`. Users must be careful to check `is_line_pipe()` before calling byte-oriented methods.
- **Efficiency**: The use of `reverse()` and `pop()` in `RawLinePipeIn::next` is an efficient way to consume a vector from "front" to "back" without shifting elements.

## 4. General Recommendations

### 4.1. Fix `BufRead` Contract
Ensure that `fill_buf` does not modify the internal state (except for filling the buffer if empty) and that `consume` is used to advance the read pointer.

### 4.2. Optimize Buffer Handling
Use `std::mem::take` or `Vec::split_off` in pipe implementations to move data into the channel instead of cloning it.

### 4.3. Error Handling over Panics
Avoid `.unwrap()` in stream implementations. When a pipe's other end is closed, it should be treated as an EOF or a specific I/O error rather than a thread panic.

### 4.4. Documentation
Explicitly document that `LinePipe` implementations will panic if used as a byte stream via `lock_bufread()` or `lock()`.

## 5. Conclusion
`runnel` is a well-designed library that achieves its goal of providing pluggable I/O. By addressing the non-idiomatic `BufRead` implementations and improving error handling in pipes, it can become even more robust and performant.

---
Review Date: 2026-05-15
Reviewer: Gemini CLI Agent