# 機能設計書 15-BufferedReader

## 概要

本ドキュメントは、Hack Standard Library（HSL）のIO名前空間における`BufferedReader`クラスの機能設計を記述する。このクラスは、ReadHandleに対してバッファリングと行単位・バイト単位の便利なアクセサを提供するラッパークラスである。

### 本機能の処理概要

`BufferedReader`クラスは、任意の`ReadHandle`をラップし、バッファリングされた読み取り機能を提供する。行単位の読み取り（`readLineAsync`）、指定文字列までの読み取り（`readUntilAsync`）、単一バイトの読み取り（`readByteAsync`）など、PHPの`fgets()`や`fgetc()`に相当する機能を非同期で実現する。

**業務上の目的・背景**：低レベルのReadHandleは効率的なバイトストリームアクセスを提供するが、多くのアプリケーションでは行単位や特定のデリミタまでの読み取りが必要となる。BufferedReaderはこれらの高レベルな読み取りパターンを効率的に実装し、開発者の生産性を向上させる。

**機能の利用シーン**：テキストファイルの行単位処理、CSVファイルの解析、HTTPヘッダーの読み取り、プロトコル解析でのメッセージ境界検出、対話型コンソールアプリケーションでの入力処理など、構造化されたテキストデータの読み取りに使用される。

**主要な処理内容**：
1. 内部バッファを使用してデータを先読みする
2. readLineAsync()で改行までの行を読み取る
3. readUntilAsync()で指定サフィックスまでを読み取る
4. readByteAsync()で単一バイトを読み取る
5. linesIterator()で行を非同期イテレートする

**関連システム・外部連携**：任意のReadHandle実装と連携可能。ファイル、ネットワークソケット、パイプなど様々な入力ソースに対応する。

**権限による制御**：特段の権限制御はない。

## 関連画面

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

## 機能種別

バッファリング / 読み取り操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | ReadHandle | Yes | ラップ対象の読み取りハンドル | - |

#### メソッド別パラメータ

##### readAllowPartialSuccessAsync / readImpl
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| max_bytes | ?int | No | 読み取る最大バイト数 | nullまたは正の整数 |
| timeout_ns | ?int | No | タイムアウト（ナノ秒） | nullまたは正の整数 |

##### readUntilAsync
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| suffix | string | Yes | 検索する終端文字列 | - |

##### readFixedSizeAsync
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| size | int | Yes | 読み取るバイト数 | 正の整数 |
| timeout_ns | ?int | No | タイムアウト（ナノ秒） | nullまたは正の整数 |

##### readByteAsync
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| timeout_ns | ?int | No | タイムアウト（ナノ秒） | nullまたは正の整数 |

### 入力データソース

コンストラクタで渡されるReadHandle

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| readImpl戻り値 | string | 読み取ったバイト列 |
| readUntilAsync戻り値 | ?string | サフィックスまでの文字列、見つからない場合null |
| readLineAsync戻り値 | ?string | 改行までの行、EOFの場合null |
| readByteAsync戻り値 | string | 単一バイト |
| linesIterator戻り値 | AsyncIterator<string> | 行の非同期イテレータ |

### 出力先

呼び出し元に読み取ったデータを返す

## 処理フロー

### 処理シーケンス

```
1. BufferedReaderをReadHandleで初期化
   └─ 内部バッファを空文字列で初期化
2. 読み取りメソッド呼び出し時
   ├─ バッファに十分なデータがある場合
   │      └─ バッファからデータを返却
   └─ バッファが不足している場合
          ├─ 下層のReadHandleから読み取り
          ├─ バッファに追加
          └─ 必要なデータを返却
3. EOFに達した場合
   └─ eofフラグをtrueに設定
```

### フローチャート

```mermaid
flowchart TD
    A[読み取りリクエスト] --> B{バッファに十分なデータ?}
    B -->|Yes| C[バッファからデータ抽出]
    B -->|No| D[下層ハンドルから読み取り]
    D --> E{データ取得?}
    E -->|Yes| F[バッファに追加]
    F --> C
    E -->|No| G[EOFフラグ設定]
    G --> H[null/空文字列返却]
    C --> I[データ返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | バッファ管理 | 先読みしたデータはバッファに保持される | 常時適用 |
| BR-02 | EOF検出 | 下層ハンドルが空文字列を返した場合EOFとみなす | readImpl時 |
| BR-03 | 行末処理 | readLineAsyncは改行を含まない行を返す | readLineAsync時 |
| BR-04 | サフィックス消費 | readUntilAsyncはサフィックスを消費するが返却値に含まない | readUntilAsync時 |

### 計算ロジック

#### readUntilAsyncのサーチオフセット計算
```
offset = max(0, buffer_length - suffix_length + 1)
```
前回の検索で見つからなかった部分のみを再検索し、効率化を図る。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EPIPE | OS\BrokenPipeException | readUntilxAsyncでサフィックスが見つからずEOF到達 | 入力データの形式を確認 |
| EPIPE | OS\BrokenPipeException | readLinexAsyncでEOF到達 | 入力完了を適切に処理 |
| EPIPE | OS\BrokenPipeException | readByteAsyncでEOF到達 | EOFを事前にチェック |
| EPIPE | OS\BrokenPipeException | readFixedSizeAsyncで要求サイズ読み取り前にEOF | サイズ要件を見直し |
| ETIMEDOUT | OS\ErrnoException | タイムアウト到達 | タイムアウト値を調整 |
| EBADF | OS\ErrnoException | クローズ済みハンドルの読み取り | ハンドル状態を確認 |

### リトライ仕様

リトライは実装されていない。エラー時は例外がスローされる。

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

該当なし

## パフォーマンス要件

- バッファリングにより、小さな読み取りの繰り返しでも効率的に動作
- isEndOfFile()は非同期ではなく即座に結果を返す（最善努力ベース）

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

- 大量のデータを読み取る場合、バッファサイズに注意
- readAllAsyncは無制限に読み取る可能性があるため、max_bytesを適切に設定

## 備考

- PHPの`fgets()`相当: `readLineAsync()`
- PHPの`fgetc()`相当: `readByteAsync()`
- 行イテレーション: `foreach ($reader->linesIterator() await as $line)`

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReadHandle.php | `src/io/ReadHandle.php` | ReadHandleインターフェースの定義。BufferedReaderが実装するメソッドを理解する |

**読解のコツ**: BufferedReaderはReadHandleインターフェースを実装しているため、ReadHandle利用者はBufferedReaderを透過的に使用できる。

#### Step 2: メインクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BufferedReader.php | `src/io/BufferedReader.php` | BufferedReaderクラスの全体構造 |

**主要処理フロー**:
1. **24行目**: クラス定義。final classでReadHandleを実装
2. **27-28行目**: コンストラクタ。ReadHandleを受け取りプライベートフィールドに格納
3. **34-35行目**: 内部状態（eofフラグ、バッファ）
4. **38-63行目**: readImpl - 同期的なバッファ読み取り
5. **102-126行目**: readUntilAsync - サフィックスまでの読み取り
6. **165-182行目**: readLineAsync - 改行までの行読み取り
7. **255-275行目**: readByteAsync - 単一バイト読み取り
8. **206-208行目**: linesIterator - 行イテレータ生成

#### Step 3: ヘルパークラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BufferedReaderLineIterator.php | `src/io/BufferedReaderLineIterator.php` | 行イテレータの実装 |
| 3-2 | ReadHandleConvenienceMethodsTrait.php | `src/io/ReadHandleConvenienceMethodsTrait.php` | 便利メソッドのトレイト |

**主要処理フロー**:
- **BufferedReaderLineIterator**: AsyncIteratorを実装し、readLineAsyncを繰り返し呼び出す

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

```
IO\BufferedReader
    │
    ├─ __construct(ReadHandle)
    │      └─ ハンドルを格納、バッファ初期化
    │
    ├─ readImpl(?int)
    │      ├─ バッファチェック
    │      └─ handle->readImpl()
    │
    ├─ readAllowPartialSuccessAsync(?int, ?int)
    │      └─ fillBufferAsync() → readImpl()
    │
    ├─ readUntilAsync(string)
    │      ├─ バッファ内検索
    │      └─ handle->readAllowPartialSuccessAsync()
    │
    ├─ readLineAsync()
    │      └─ readUntilAsync("\n")
    │
    ├─ readByteAsync(?int)
    │      └─ fillBufferAsync()
    │
    ├─ linesIterator()
    │      └─ BufferedReaderLineIterator
    │
    └─ isEndOfFile()
           └─ handle->readImpl() (非ブロッキング)
```

### データフロー図

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

ReadHandle ──────────▶ BufferedReader ─────────────────▶ 行/バイト/文字列
                              │
                        ┌─────┴─────┐
                        ▼           ▼
                    バッファ    下層ハンドル
                        │           │
                        ▼           ▼
                    先読み済    必要時読取
                    データ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BufferedReader.php | `src/io/BufferedReader.php` | ソース | BufferedReaderクラス本体 |
| BufferedReaderLineIterator.php | `src/io/BufferedReaderLineIterator.php` | ソース | 行イテレータ実装 |
| ReadHandle.php | `src/io/ReadHandle.php` | ソース | 読み取りハンドルインターフェース |
| ReadHandleConvenienceMethodsTrait.php | `src/io/ReadHandleConvenienceMethodsTrait.php` | ソース | 読み取り便利メソッドトレイト |
| Handle.php | `src/io/Handle.php` | ソース | 基底インターフェース定義 |
