# 機能設計書 13-request_input

## 概要

本ドキュメントは、Hack Standard Library（HSL）のIO名前空間における`request_input`関数の機能設計を記述する。この関数は、現在のリクエストに対する入力ハンドルを取得するための機能を提供する。

### 本機能の処理概要

`request_input`関数は、現在の実行コンテキストに応じた適切な入力ハンドルを返す。CLIモードでは標準入力（STDIN）、HTTPリクエストモードではPOSTデータなどのリクエストボディへのハンドルを提供する。

**業務上の目的・背景**：アプリケーションは実行コンテキスト（CLI、HTTP等）に関わらず、統一されたインターフェースを通じてクライアントからのデータを受信する必要がある。この関数により、実行環境の差異を抽象化し、コードの移植性と保守性を向上させることができる。

**機能の利用シーン**：CLIツールでの標準入力からのデータ読み取り、Webアプリケーションでのリクエストボディの読み取り、パイプライン処理での前段プロセスからのデータ受信、対話型コマンドラインアプリケーションでのユーザー入力受付など、あらゆる場面でクライアントからデータを受信する際に使用される。

**主要な処理内容**：
1. OS\stdin()を呼び出してファイルディスクリプタの取得を試みる
2. 取得成功時はStdioReadHandleをラップして返す
3. EBADF（Bad File Descriptor）エラー時はRequestReadHandleを返す（HTTPモード）
4. その他のエラーは例外として再スローする

**関連システム・外部連携**：OSレベルのファイルディスクリプタ操作に依存する。CLIモードではプロセスの標準入力ストリーム、HTTPモードではHHVMのリクエストハンドラと連携する。

**権限による制御**：特段の権限制御はないが、ファイルディスクリプタへのアクセス権限はOSレベルで管理される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 画面なし | - | 本プロジェクトはUIを持たないライブラリのため画面機能マッピングは該当しない |

## 機能種別

データ入力 / ハンドル取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | この関数は引数を取らない | - |

### 入力データソース

実行コンテキスト（OSのstdinファイルディスクリプタまたはHHVMのリクエストハンドル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | ReadHandle | 読み取り可能なI/Oハンドル。CLIモードではStdioReadHandle、HTTPモードではRequestReadHandleがラップされている |

### 出力先

呼び出し元に`ReadHandle`インターフェースを実装したオブジェクトを返す

## 処理フロー

### 処理シーケンス

```
1. OS\stdin()を呼び出し
   └─ ファイルディスクリプタの取得を試みる
2. 成功した場合
   └─ StdioReadHandleをインスタンス化して返す
3. ErrnoException発生時
   ├─ EBADFエラーの場合
   │      └─ RequestReadHandleをインスタンス化して返す
   └─ その他のエラーの場合
          └─ 例外を再スローする
```

### フローチャート

```mermaid
flowchart TD
    A[request_input呼び出し] --> B[OS\stdin取得試行]
    B --> C{成功?}
    C -->|Yes| D[StdioReadHandle生成]
    D --> E[ReadHandle返却]
    C -->|No| F{EBADFエラー?}
    F -->|Yes| G[RequestReadHandle生成]
    G --> E
    F -->|No| H[例外再スロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | メモ化 | 関数の戻り値はメモ化され、同一リクエスト内で再利用される | `<<__Memoize>>`属性により常時適用 |
| BR-02 | コンテキスト自動判定 | 実行環境に応じて適切なハンドル型が自動選択される | 常時適用 |

### 計算ロジック

特になし

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

該当なし（本機能はI/O操作のみでデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EBADF | OS\ErrnoException | stdinが利用不可能な場合（HTTPモード等） | 内部で捕捉しRequestReadHandleを返す |
| その他 | OS\ErrnoException | ファイルディスクリプタ操作の失敗 | 例外として再スローされる |

### リトライ仕様

リトライは実装されていない

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

該当なし

## パフォーマンス要件

`<<__Memoize>>`属性により、同一リクエスト内での複数呼び出しはキャッシュされた結果を返すため、オーバーヘッドは最小限に抑えられる。

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

- 入力ハンドルから読み取るデータは、呼び出し側で適切にバリデーション・サニタイズする必要がある
- HTTPモードでは、POSTデータの取り扱いに注意が必要

## 備考

- `CloseableReadFDHandle`を返す場合があるが、型定義は`ReadHandle`である
- 関連関数として`request_output()`（標準出力）、`request_error()`（標準エラー出力）がある

---

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

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

### 推奨読解順序

#### Step 1: インターフェース定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Handle.php | `src/io/Handle.php` | IOハンドルの基本インターフェース。全てのハンドルの基底 |
| 1-2 | ReadHandle.php | `src/io/ReadHandle.php` | 読み取りハンドルのインターフェース定義。readImpl、readAllowPartialSuccessAsync、readAllAsync、readFixedSizeAsyncメソッドを理解する |

**読解のコツ**: Hackのインターフェース階層を理解することが重要。`Handle` -> `ReadHandle` -> `CloseableReadHandle`等の継承関係を把握する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stdio.php | `src/io/stdio.php` | request_input関数の本体。メモ化属性と例外ハンドリングを確認 |

**主要処理フロー**:
1. **77-87行目**: request_input関数本体。try-catchでstdin取得を試み、失敗時の代替処理を行う
2. **80行目**: OS\stdin()でファイルディスクリプタを取得しStdioReadHandleを生成
3. **81-86行目**: EBADFエラー時にRequestReadHandleを返す

#### Step 3: 内部実装クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StdioReadHandle.php | `src/io/_Private/StdioReadHandle.php` | CLIモード用の入力ハンドル実装 |
| 3-2 | RequestReadHandle.php | `src/io/_Private/RequestReadHandle.php` | HTTPモード用の入力ハンドル実装 |
| 3-3 | FileDescriptorHandle.php | `src/io/_Private/FileDescriptorHandle.php` | ファイルディスクリプタハンドルの基底クラス |

**主要処理フロー**:
- **StdioReadHandle**: FileDescriptorHandleを継承し、FileDescriptorReadHandleTraitを使用
- **RequestReadHandle**: ReadHandleインターフェースを直接実装し、request_read関数を呼び出す

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

```
IO\request_input()
    │
    ├─ OS\stdin()
    │      └─ ファイルディスクリプタ取得
    │
    ├─ _IO\StdioReadHandle (成功時)
    │      ├─ FileDescriptorHandle
    │      │      └─ OS\fcntl() - O_NONBLOCK設定
    │      └─ FileDescriptorReadHandleTrait
    │
    └─ _IO\RequestReadHandle (EBADF時)
           └─ request_read() - HHVMネイティブ関数
```

### データフロー図

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

STDIN/POST ────────▶ request_input() ─────────▶ ReadHandle
                          │
                    ┌─────┴─────┐
                    ▼           ▼
              CLIモード    HTTPモード
                    │           │
                    ▼           ▼
            StdioReadHandle  RequestReadHandle
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stdio.php | `src/io/stdio.php` | ソース | request_input等のエントリーポイント関数 |
| Handle.php | `src/io/Handle.php` | ソース | 基底インターフェース定義 |
| ReadHandle.php | `src/io/ReadHandle.php` | ソース | 読み取りハンドルインターフェース |
| StdioReadHandle.php | `src/io/_Private/StdioReadHandle.php` | ソース | CLI用入力ハンドル実装 |
| RequestReadHandle.php | `src/io/_Private/RequestReadHandle.php` | ソース | HTTP用入力ハンドル実装 |
| FileDescriptorHandle.php | `src/io/_Private/FileDescriptorHandle.php` | ソース | FDハンドル基底クラス |
| ReadHandleConvenienceMethodsTrait.php | `src/io/ReadHandleConvenienceMethodsTrait.php` | ソース | 読み取りの便利メソッド提供 |
| intersection_interfaces.php | `src/io/intersection_interfaces.php` | ソース | 複合インターフェース定義 |
