# 機能設計書 38-標準入出力

## 概要

本ドキュメントは、Julia Base ライブラリにおける標準入出力機能の設計を記述する。`stdin` / `stdout` / `stderr` のリダイレクト（`redirect_stdio` / `redirect_stdout` / `redirect_stderr`）を提供する。

### 本機能の処理概要

本機能は、Julia プロセスの標準入出力ストリーム（stdin, stdout, stderr）の管理とリダイレクトを提供する。

**業務上の目的・背景**：標準入出力は UNIX の基本概念であり、プロセス間通信、パイプライン処理、テスト時の出力キャプチャ、ログの分離など、多くの場面で標準ストリームの制御が必要となる。Julia はlibuv ベースの非同期I/O基盤上に標準入出力を構築している。

**機能の利用シーン**：テスト時の stdout/stderr のキャプチャ、外部プロセスへの標準入出力接続、ログ出力の分離（stderr への出力）、対話的入力の読み取り（stdin からの読み取り）。

**主要な処理内容**：
1. `stdin` / `stdout` / `stderr` グローバル変数の提供
2. `redirect_stdout(io)` / `redirect_stderr(io)` / `redirect_stdin(io)` による個別リダイレクト
3. `redirect_stdio(; stdin, stdout, stderr)` による一括リダイレクト
4. `redirect_stdout(f)` / `redirect_stderr(f)` による do 構文対応のスコープ付きリダイレクト
5. libuv ベースの非同期I/Oストリーム（`LibuvStream`）の管理
6. `BufferStream` によるインメモリのストリームバッファ
7. IO 型階層の管理（LibuvStream, AbstractPipe, TTY 等）

**関連システム・外部連携**：libuv 非同期I/Oライブラリ、OS の標準ストリーム。

**権限による制御**：該当なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | REPL | 主画面 | stdin からの入力読み取り、stdout/stderr への出力 |

## 機能種別

標準ストリーム管理 / I/Oリダイレクト

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| io | IO | No | リダイレクト先の IO ストリーム | 省略時は新しい Pipe を作成 |
| f | Function | No | スコープ付きリダイレクトの関数 | - |
| stdin | IO | No | redirect_stdio の stdin 先 | - |
| stdout | IO | No | redirect_stdio の stdout 先 | - |
| stderr | IO | No | redirect_stdio の stderr 先 | - |

### 入力データソース

OS の標準ストリーム（ファイルディスクリプタ 0, 1, 2）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| redirect結果 | Pipe / IO | リダイレクト先のストリーム（読み取り用） |
| stdin | IO | 標準入力ストリーム |
| stdout | IO | 標準出力ストリーム |
| stderr | IO | 標準エラー出力ストリーム |

### 出力先

OS の標準ストリームまたはリダイレクト先の IO。

## 処理フロー

### 処理シーケンス

```
1. redirect_stdout(io)
   └─ 現在の stdout を保存
   └─ グローバル stdout を io に置換
   └─ OS レベルのファイルディスクリプタも必要に応じてリダイレクト
2. redirect_stdout(f)
   └─ rd, wr = redirect_stdout() でパイプ作成
   └─ try f() finally redirect_stdout(old_stdout) end
   └─ rd からリダイレクト中の出力を読み取り可能
3. redirect_stdio(; stdin, stdout, stderr)
   └─ 指定された各ストリームを個別にリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[開始: redirect_stdout f] --> B[old_stdout を保存]
    B --> C[pipe = redirect_stdout]
    C --> D[try: result = f]
    D --> E[finally: redirect_stdout old_stdout]
    E --> F[return result]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | グローバルストリーム | stdin/stdout/stderr はグローバル変数として提供 | 全体 |
| BR-38-02 | スコープ付きリダイレクト | f 引数版は finally で自動復元 | redirect_stdout(f) |
| BR-38-03 | LibuvStream | 標準ストリームは libuv ベースの非同期ストリーム | 初期化時 |
| BR-38-04 | TTY | ターミナル接続時は TTY 型を使用 | インタラクティブモード |

### 計算ロジック

該当なし。

## データベース操作仕様

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IOError | リダイレクト先の IO が無効 | 有効な IO ストリームを指定 |
| - | SystemError | OS レベルのリダイレクト失敗 | ファイルディスクリプタの状態を確認 |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- libuv の非同期I/Oにより、stdout/stderr への書き込みがブロッキングを最小化
- BufferStream はメモリ内バッファにより高速な一時ストリームを提供

## セキュリティ考慮事項

- 標準入出力のリダイレクトはプロセス全体に影響するため、マルチスレッド環境では注意が必要
- リダイレクト中に例外が発生した場合も、finally ブロックで確実に復元される

## 備考

- `redirect_stdio` は Julia 1.7 で追加された一括リダイレクト関数
- stream.jl の冒頭コメントに IO 型階層が記述されている: `IO > GenericIOBuffer, AbstractPipe, DevNull, LibuvStream, IOBuffer, IOStream`
- `LibuvServer` と `LibuvStream` は libuv ベースの非同期I/Oの抽象型

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stream.jl | `base/stream.jl` | IO 型階層のコメント（先頭部分）: LibuvServer, LibuvStream の定義 |
| 1-2 | stream.jl | `base/stream.jl` | TTY, Pipe, BufferStream 等の型定義 |

**読解のコツ**: stream.jl は非常に大きなファイルであり、libuv のイベントループと密接に結合している。まず型階層を理解し、次に個別の操作を読むのが効率的。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stream.jl | `base/stream.jl` | redirect_stdout / redirect_stderr / redirect_stdin 関数 |
| 2-2 | stream.jl | `base/stream.jl` | redirect_stdio 関数 |

#### Step 3: 標準ストリームの初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream.jl | `base/stream.jl` | stdin/stdout/stderr の初期化ロジック |

### プログラム呼び出し階層図

```
Julia 起動
    |
    +-- stdin = TTY(STDIN_HANDLE) or PipeEndpoint
    +-- stdout = TTY(STDOUT_HANDLE) or PipeEndpoint
    +-- stderr = TTY(STDERR_HANDLE) or PipeEndpoint

redirect_stdout(io)
    |
    +-- 現在の stdout を保存
    +-- global stdout = io
    +-- OS レベル fd リダイレクト

redirect_stdout(f)
    |
    +-- old = stdout
    +-- pipe = redirect_stdout()
    +-- try: f()
    +-- finally: redirect_stdout(old)
```

### データフロー図

```
[入力]                      [処理]                        [出力]

ユーザー入力 -----------> stdin (LibuvStream) ------> Julia プログラム

Julia プログラム -------> stdout (LibuvStream) -----> ターミナル / リダイレクト先
                              |
                              +-> redirect_stdout(io) で切り替え

Julia プログラム -------> stderr (LibuvStream) -----> ターミナル / リダイレクト先
                              |
                              +-> redirect_stderr(io) で切り替え
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stream.jl | `base/stream.jl` | ソース | LibuvStream/TTY/Pipe/BufferStream/redirect_* の実装 |
| io.jl | `base/io.jl` | ソース | IO 抽象型の基本インターフェース |
| libuv.jl | `base/libuv.jl` | ソース | libuv イベントループの管理 |
| iostream.jl | `base/iostream.jl` | ソース | IOStream（ファイルベースI/O） |
