# 機能設計書 16-MemoryHandle

## 概要

本ドキュメントは、Hack Standard Library（HSL）のIO名前空間における`MemoryHandle`クラスの機能設計を記述する。このクラスは、インメモリバッファへの読み書き機能を提供し、主にユニットテストでのI/Oモック用途に使用される。

### 本機能の処理概要

`MemoryHandle`クラスは、メモリ上の文字列バッファをファイルのように読み書きできるハンドルを提供する。読み取り、書き込み、シーク操作をサポートし、クローズ後は操作が禁止される。

**業務上の目的・背景**：ユニットテストにおいて、実際のファイルやネットワークソケットを使用せずにI/O処理をテストする必要がある。MemoryHandleを使用することで、テストデータの準備と結果の検証が容易になり、テストの実行速度も向上する。また、外部リソースへの依存を排除し、テストの再現性を高める。

**機能の利用シーン**：I/O処理のユニットテスト、ReadHandle/WriteHandleを必要とする関数のモック、入出力データの事前準備と事後検証、パイプの代替としての簡易データ受け渡しなど、テスト環境でのI/O操作シミュレーションに使用される。

**主要な処理内容**：
1. メモリバッファとオフセット位置を管理する
2. readImpl()でオフセット位置からデータを読み取る
3. writeImpl()でオフセット位置にデータを書き込む（上書きまたは追記モード）
4. seek()でオフセット位置を変更する
5. getBuffer()でバッファ全体を取得する

**関連システム・外部連携**：外部システムとの連携はない。純粋にメモリ上で動作する。

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

## 関連画面

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

## 機能種別

テスト支援 / メモリI/O

## 入力仕様

### 入力パラメータ

#### コンストラクタ
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| buffer | string | No | 初期バッファ内容 | デフォルト: 空文字列 |
| writeMode | MemoryHandleWriteMode | No | 書き込みモード | デフォルト: OVERWRITE |

#### MemoryHandleWriteMode列挙型
| 値 | 説明 |
|-----|------|
| OVERWRITE | 現在位置から上書き |
| APPEND | バッファ末尾に追記 |

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

#### seek
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pos | int | Yes | 新しいオフセット位置 | 0以上 |

#### writeAllowPartialSuccessAsync
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| data | string | Yes | 書き込むデータ | - |
| timeout_nanos | ?int | No | タイムアウト（使用されない） | - |

### 入力データソース

コンストラクタで渡される初期バッファ、またはwrite操作で追加されるデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| readImpl戻り値 | string | 読み取ったデータ |
| tell戻り値 | int | 現在のオフセット位置 |
| getBuffer戻り値 | string | バッファ全体の内容 |
| writeImpl戻り値 | int | 書き込んだバイト数 |

### 出力先

呼び出し元にデータを返す、またはバッファに書き込み

## 処理フロー

### 処理シーケンス

```
1. MemoryHandleを初期化
   ├─ バッファを初期値で設定
   ├─ オフセットを0に設定
   └─ openフラグをtrueに設定
2. 読み取り操作時
   ├─ openチェック
   ├─ オフセットからmax_bytesを読み取り
   └─ オフセットを更新
3. 書き込み操作時
   ├─ openチェック
   ├─ モードに応じて上書きまたは追記
   └─ オフセットを更新
4. シーク操作時
   ├─ openチェック
   └─ オフセットを更新
5. クローズ時
   ├─ openフラグをfalseに設定
   └─ オフセットを-1に設定
```

### フローチャート

```mermaid
flowchart TD
    A[MemoryHandle操作] --> B{open?}
    B -->|No| C[EBADFエラー]
    B -->|Yes| D{操作種別}
    D -->|read| E[オフセット位置から読み取り]
    D -->|write| F{writeMode}
    D -->|seek| G[オフセット更新]
    D -->|close| H[フラグ更新]
    F -->|OVERWRITE| I[現在位置から上書き]
    F -->|APPEND| J[末尾に追記]
    E --> K[オフセット更新]
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | オープン状態管理 | クローズ後の操作はEBADFエラー | 全操作 |
| BR-02 | 上書きモード | 現在位置からデータを上書き、既存データが残る場合は保持 | OVERWRITE時 |
| BR-03 | 追記モード | 常にバッファ末尾に追加 | APPEND時 |
| BR-04 | ゼロパディング | オフセットがバッファ長を超える場合、NULLバイトで埋める | write時 |
| BR-05 | ファイル末尾超えシーク | シークはバッファ末尾を超えた位置でも許可 | seek時 |

### 計算ロジック

#### 読み取りバイト数計算
```
to_read = min(max_bytes, buffer_length - offset)
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EBADF | OS\ErrnoException | クローズ済みハンドルへの操作 | reset()でリオープン |

### リトライ仕様

リトライは不要。close()後はreset()で再初期化可能。

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

該当なし

## パフォーマンス要件

- すべての操作はO(n)（nはデータサイズ）
- メモリ使用量はバッファサイズに比例

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

- バッファ内容はメモリ上に平文で保持される
- 機密データを扱う場合は適切なタイミングでreset()を呼び出す

## 備考

- 主にユニットテスト用途
- より複雑なテストにはIO\pipe()を検討

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReadHandle.php | `src/io/ReadHandle.php` | ReadHandleインターフェース |
| 1-2 | WriteHandle.php | `src/io/WriteHandle.php` | WriteHandleインターフェース |
| 1-3 | SeekableHandle.php | `src/io/SeekableHandle.php` | SeekableHandleインターフェース |
| 1-4 | CloseableHandle.php | `src/io/CloseableHandle.php` | CloseableHandleインターフェース |
| 1-5 | intersection_interfaces.php | `src/io/intersection_interfaces.php` | CloseableSeekableReadWriteHandle定義 |

**読解のコツ**: MemoryHandleはCloseableSeekableReadWriteHandleを実装しており、読み取り・書き込み・シーク・クローズの全てをサポートする。

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

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

**主要処理フロー**:
1. **16-19行目**: MemoryHandleWriteMode列挙型。OVERWRITEとAPPENDを定義
2. **27行目**: クラス定義。CloseableSeekableReadWriteHandleを実装
3. **31-32行目**: 内部状態（offset、open）
4. **34-38行目**: コンストラクタ。バッファと書き込みモードを設定
5. **40-43行目**: close()。フラグとオフセットを更新
6. **57-71行目**: readImpl()。バッファからデータを読み取り
7. **73-79行目**: seek()。オフセット位置を更新
8. **81-84行目**: tell()。現在のオフセット位置を返す
9. **86-116行目**: writeImpl()。モードに応じてバッファに書き込み
10. **125-127行目**: getBuffer()。バッファ全体を取得
11. **134-138行目**: reset()。バッファとオフセットをリセット
12. **144-147行目**: appendToBuffer()。オフセットを変更せずにバッファに追加

#### Step 3: トレイトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReadHandleConvenienceMethodsTrait.php | `src/io/ReadHandleConvenienceMethodsTrait.php` | 読み取り便利メソッド |
| 3-2 | WriteHandleConvenienceMethodsTrait.php | `src/io/WriteHandleConvenienceMethodsTrait.php` | 書き込み便利メソッド |

**主要処理フロー**:
- **ReadHandleConvenienceMethodsTrait**: readAllAsync、readFixedSizeAsyncを提供
- **WriteHandleConvenienceMethodsTrait**: writeAllAsyncを提供

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

```
IO\MemoryHandle
    │
    ├─ __construct(string, MemoryHandleWriteMode)
    │      └─ バッファ・モード・オフセット初期化
    │
    ├─ readImpl(?int)
    │      ├─ checkIsOpen()
    │      └─ バッファスライス・オフセット更新
    │
    ├─ writeImpl(string)
    │      ├─ checkIsOpen()
    │      ├─ ゼロパディング（必要時）
    │      └─ モード別処理
    │             ├─ APPEND: バッファ追記
    │             └─ OVERWRITE: 位置上書き
    │
    ├─ seek(int)
    │      └─ オフセット更新
    │
    ├─ tell()
    │      └─ オフセット返却
    │
    ├─ getBuffer()
    │      └─ バッファ全体返却
    │
    ├─ reset(string)
    │      └─ バッファ・オフセット・openフラグリセット
    │
    └─ close()
           └─ openフラグ無効化
```

### データフロー図

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

初期バッファ ─────────▶ MemoryHandle ──────────────────▶ 読み取りデータ
                              │
書き込みデータ ─────────▶     │                      ▶ バッファ内容
                              ▼
                        ┌─────────────┐
                        │   バッファ   │
                        │   (string)  │
                        │             │
                        │  offset: 0  │
                        └─────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MemoryHandle.php | `src/io/MemoryHandle.php` | ソース | MemoryHandleクラス本体 |
| Handle.php | `src/io/Handle.php` | ソース | 基底インターフェース定義 |
| ReadHandle.php | `src/io/ReadHandle.php` | ソース | 読み取りハンドルインターフェース |
| WriteHandle.php | `src/io/WriteHandle.php` | ソース | 書き込みハンドルインターフェース |
| SeekableHandle.php | `src/io/SeekableHandle.php` | ソース | シーク可能ハンドルインターフェース |
| CloseableHandle.php | `src/io/CloseableHandle.php` | ソース | クローズ可能ハンドルインターフェース |
| ReadHandleConvenienceMethodsTrait.php | `src/io/ReadHandleConvenienceMethodsTrait.php` | ソース | 読み取り便利メソッド |
| WriteHandleConvenienceMethodsTrait.php | `src/io/WriteHandleConvenienceMethodsTrait.php` | ソース | 書き込み便利メソッド |
| intersection_interfaces.php | `src/io/intersection_interfaces.php` | ソース | 複合インターフェース定義 |
