ratel-rust 0.1.1

A Rust implementation of Ratel the landlord game client.
Documentation
# PtyManager 使用文檔

## 概述

`PtyManager` 是一個簡單的偽終端(PTY)I/O 管理器,它使用 `tokio::sync::mpsc` 通道來處理應用程序和 PTY 之間的數據傳輸。

## 結構

```rust
pub struct PtyManager {
    tx: mpsc::UnboundedSender<Vec<u8>>,  // 發送通道
    rx: mpsc::UnboundedReceiver<Vec<u8>>, // 接收通道
}
```

## 特性

- **異步通道**: 使用 `tokio` 的無界通道
-**零拷貝傳輸**: 直接傳輸 `Vec<u8>` 引用
-**線程安全**: 所有操作都是線程安全的
-**簡單 API**: 只有三個公開方法

## 基本用法

### 1. 創建 PtyManager

```rust
use ratel_rust::pty::PtyManager;

// 方式一:使用 new() 方法
let mut pty = PtyManager::new();

// 方式二:使用 Default trait
let mut pty = PtyManager::default();
```

### 2. 獲取發送器

```rust
// 獲取發送通道(可以用於克隆)
let sender = pty.sender();

// 發送數據到 PTY
let data = b"Hello, PTY!".to_vec();
sender.send(data)?;
```

### 3. 獲取接收器

```rust
// 獲取接收通道的可變引用
let receiver = pty.receiver();

// 在異步任務中接收數據
while let Some(data) = receiver.recv().await {
    println!("Received: {:?}", data);
}
```

## 完整示例

### 示例 1: 基本數據傳輸

```rust
use tokio::spawn;
use ratel_rust::pty::PtyManager;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut pty = PtyManager::new();
    let sender = pty.sender();

    // 發送任務
    let send_task = spawn(async move {
        let data = b"Test message".to_vec();
        for i in 0..5 {
            let msg = format!("Message {}: {}", i, String::from_utf8_lossy(&data));
            sender.send(msg.into_bytes())?;
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
        }
        Ok::<(), anyhow::Error>(())
    });

    // 接收任務
    let recv_task = spawn(async move {
        let receiver = pty.receiver();
        while let Some(data) = receiver.recv().await {
            println!("Received: {}", String::from_utf8_lossy(&data));
        }
    });

    // 等待任務完成
    send_task.await??;
    recv_task.abort();

    Ok(())
}
```

### 示例 2: 與網絡集成

```rust
use tokio::select;
use ratel_rust::pty::PtyManager;

async fn network_loop(pty: &mut PtyManager, mut stream: TcpStream) -> anyhow::Result<()> {
    let sender = pty.sender();
    let receiver = pty.receiver();

    loop {
        tokio::select! {
            // 發送 PTY 數據到網絡
            Some(data) = receiver.recv() => {
                stream.write_all(&data).await?;
            }
            // 接收網絡數據到 PTY
            result = stream.read_buf(&mut buffer) => {
                let n = result?;
                if n == 0 {
                    break;
                }
                let data = buffer.split_to(n).to_vec();
                // 處理數據...
            }
        }
    }

    Ok(())
}
```

### 示例 3: 多個發送器

```rust
use std::sync::Arc;
use tokio::task::JoinHandle;
use ratel_rust::pty::PtyManager;

async fn multi_sender_example() -> anyhow::Result<()> {
    let mut pty = PtyManager::new();

    // 共享發送器
    let sender = Arc::new(pty.sender());

    // 創建多個發送任務
    let tasks: Vec<JoinHandle<()>> = (0..3)
        .map(|i| {
            let sender = Arc::clone(&sender);
            spawn(async move {
                let msg = format!("Task {} message", i);
                let _ = sender.send(msg.into_bytes());
            })
        })
        .collect();

    // 等待所有任務
    for task in tasks {
        task.await?;
    }

    Ok(())
}
```

## 輔助函數

### `read_line()`

直接從標準輸入讀取一行文本。

```rust
use ratel_rust::pty::read_line;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let line = read_line().await?;
    println!("You entered: {}", line);
    Ok(())
}
```

**特點:**
- 異步讀取
- 自動去除首尾空白字符
- 返回 `Result<String>`

### `read_key()`

使用 `crossterm` 從終端讀取單個鍵盤事件。

```rust
use ratel_rust::pty::read_key;
use crossterm::event::KeyEvent;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let key = read_key().await?;
    println!("Key pressed: {:?}", key);
    Ok(())
}
```

**特點:**
- 輪詢間隔: 100ms
- 返回 `Result<KeyEvent>`
- 支持所有 `crossterm` 鍵盤事件

## 注意事項

### 1. 通道類型

使用的是 `Unbounded` 通道,意味著:
- 無容量限制
- 如果生產速度遠大於消費速度,可能導致內存問題
- 適合於生產者和消費者速度相近的場景

### 2. 接收器權限

只有通過 `receiver()` 方法才能獲得接收器:
- 接收器是可變引用,同一時間只有一個消費者
- 發送器可以克隆,支持多個生產者

### 3. 錯誤處理

通道操作返回 `Result`,應該正確處理錯誤:

```rust
match sender.send(data) {
    Ok(_) => println!("Sent successfully"),
    Err(e) => {
        // 接收端已關閉
        eprintln!("Failed to send: {:?}", e);
        return Err(e.into());
    }
}
```

## 性能考慮

### 內存使用

- 每個消息都是 `Vec<u8>`,會在堆上分配
- 大量小消息可能導致內存碎片
- 考慮批量發送以減少分配

### 延遲

- 無界通道在負載高時可能有延遲
- 如果需要低延遲,考慮使用有界通道

## 最佳實踐

### 1. 使用 `tokio::select!`

在網絡應用中,使用 `tokio::select!` 同時處理 PTY 和網絡 I/O:

```rust
tokio::select! {
    Some(data) = receiver.recv() => {
        // 處理 PTY 數據
    }
    result = network.receive() => {
        // 處理網絡數據
    }
}
```

### 2. 優雅地關閉

發送端需要優雅地關閉通道:

```rust
drop(sender);  // 關閉發送端

// 接收端會收到 None
while let Some(data) = receiver.recv().await {
    // 處理最後的消息
}
```

### 3. 錯誤恢復

在生產環境中,應該有錯誤恢復機制:

```rust
loop {
    match receiver.recv().await {
        Some(data) => {
            if let Err(e) = process_data(data) {
                eprintln!("Processing error: {:?}", e);
                // 繼續而不是退出
            }
        }
        None => {
            println!("Channel closed");
            break;
        }
    }
}
```

## 相關模塊

- `crate::shell`: 使用 `PtyManager` 的主 shell 邏輯
- `crate::network`: 網絡 I/O,可以與 `PtyManager` 配合使用
- `crate::util`: 工具函數

## API 參考

### `PtyManager::new()`

```rust
pub fn new() -> Self
```

創建新的 `PtyManager` 實例。

**返回:** 新的 `PtyManager`

---

### `PtyManager::sender()`

```rust
pub fn sender(&self) -> mpsc::UnboundedSender<Vec<u8>>
```

獲取發送通道的克隆。

**返回:** 發送通道的克隆

---

### `PtyManager::receiver()`

```rust
pub fn receiver(&mut self) -> &mut mpsc::UnboundedReceiver<Vec<u8>>
```

獲取接收通道的可變引用。

**返回:** 接收通道的可變引用

---

### `read_line()`

```rust
pub async fn read_line() -> Result<String>
```

從標準輸入讀取一行文本。

**返回:** 讀取的行(去除空白)

**錯誤:** 讀取失敗時返回錯誤

---

### `read_key()`

```rust
pub async fn read_key() -> Result<KeyEvent>
```

從終端讀取單個鍵盤事件。

**返回:** 鍵盤事件

**錯誤:** 讀取失敗時返回錯誤

## 依賴

- `tokio` - 異步運行時和通道
- `crossterm` - 跨平台終端操作
- `anyhow` - 錯誤處理

## 授權

本模塊是 `ratel-rust` 項目的一部分,遵循相同的許可證。