# 機能設計書 88-インライン構造体テスト

## 概要

本ドキュメントは、mrubyのmruby-test-inline-struct gemが提供するインライン構造体（MRB_TT_ISTRUCT）のテスト用gemの機能設計を記述する。mrubyのインライン構造体機能の動作検証を目的としたテスト専用のgemである。

### 本機能の処理概要

**業務上の目的・背景**：mrubyのインライン構造体（ISTRUCT）は、小さなデータをRBasicオブジェクトのポインタスロット内に直接格納する最適化機構である。ヒープ割り当てを回避し、メモリ効率とキャッシュ効率を向上させる。本gemはこの機構が正しく動作することを検証するためのテスト専用gemである。

**機能の利用シーン**：mruby本体の開発・テスト時。インライン構造体の機能が正しく動作することの回帰テスト。

**主要な処理内容**：
1. InlineStructTestクラスの定義（MRB_TT_ISTRUCTタイプ）
2. initialize - 引数の型に応じた文字列をインライン構造体内に格納
3. to_s - インライン構造体内の文字列を返す
4. mutate - インライン構造体内のデータを変更する
5. test_receive / test_receive_direct - インライン構造体の受け渡しテスト
6. dup/clone時の値コピーの検証

**関連システム・外部連携**：mrubyコアのISTRUCT機能（mruby/istruct.h）

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | テスト専用。画面なし |

## 機能種別

テスト支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| object (initialize) | Object | Yes | 型判定の対象。Integer/Float/String/その他 | - |
| object (test_receive) | InlineStructTest | Yes | 検証対象のISTRUCTオブジェクト | InlineStructTestであること |

### 入力データソース

テストコードからの関数呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| to_s | String | ISTRUCT内に格納された文字列 |
| test_receive | Boolean | 先頭文字が's'ならtrue |
| length | Integer | ISTRUCT領域のサイズ（バイト数） |

### 出力先

Ruby関数の戻り値

## 処理フロー

### 処理シーケンス

```
1. InlineStructTest.new(object)
   ├─ mrb_istruct_ptr(self) でISTRUCT領域のポインタ取得
   ├─ 引数の型判定:
   │   ├─ Integer → "fixnum" を格納
   │   ├─ Float → "float" を格納
   │   ├─ String → "string" を格納
   │   └─ その他 → "anything" を格納
   └─ NUL終端を保証

2. InlineStructTest#to_s
   └─ mrb_istruct_ptr(self) から文字列生成

3. InlineStructTest.test_receive(obj)
   ├─ objのクラスをInlineStructTestと照合
   ├─ 不一致時はTypeError
   └─ ISTRUCT先頭バイトが's'かチェック

4. InlineStructTest.test_receive_direct(obj)
   ├─ mrb_istruct_p(is) でISTRUCT型チェック
   ├─ mrb_obj_is_kind_of で型チェック
   └─ ISTRUCT先頭バイトが's'かチェック
```

### フローチャート

```mermaid
flowchart TD
    A[InlineStructTest.new] --> B{引数の型?}
    B -->|Integer| C["fixnum"格納]
    B -->|Float| D["float"格納]
    B -->|String| E["string"格納]
    B -->|Other| F["anything"格納]
    C --> G[NUL終端]
    D --> G
    E --> G
    F --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-88-1 | サイズ制限 | ISTRUCT領域はポインタ3個分のサイズ（64bit:24byte, 32bit:12byte） | プラットフォーム依存 |
| BR-88-2 | 値コピー | dup/cloneはISTRUCT領域をバイトコピーする | dup/clone時 |
| BR-88-3 | IV不可 | ISTRUCTオブジェクトにはインスタンス変数を設定できない | @変数アクセス時 |

### 計算ロジック

特になし

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | test_receiveに非InlineStructTestを渡した場合 | "Expected InlineStructTest" |
| - | ArgumentError | インスタンス変数設定を試みた場合 | ISTRUCTはIV不可 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

特になし（テスト専用）

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

test_receive_directのコメント（62-63行目）に記載の通り、信頼できないコードからISTRUCTを取得する場合はクラス差し替え攻撃に注意が必要。

## 備考

- 本gemはテスト専用であり、プロダクション用途には使用しない
- ISTRUCT領域のサイズはプラットフォーム（16/32/64bit）によって異なる
- mruby-randomがISTRUCTの実用例として参照可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inline.c | `mrbgems/mruby-test-inline-struct/test/inline.c` | mrb_istruct_ptr/mrb_istruct_sizeの使い方（9-10行目）を理解 |

**読解のコツ**: `mrb_istruct_ptr(self)` はRBasicオブジェクトのインラインデータ領域へのポインタを返す。`mrb_istruct_size()` はこの領域のバイト数を返す。`MRB_SET_INSTANCE_TT(cls, MRB_TT_ISTRUCT)` でクラスのインスタンスタイプをISTRUCTに設定する（85行目）。

#### Step 2: テストクラスの定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inline.c | `mrbgems/mruby-test-inline-struct/test/inline.c` | mrb_mruby_test_inline_struct_gem_test（80-92行目）でクラス定義を確認 |

**主要処理フロー**:
- **84行目**: InlineStructTestクラスをObject直下に定義
- **85行目**: MRB_SET_INSTANCE_TT でISTRUCTタイプを設定
- **86-91行目**: 各メソッドの登録

#### Step 3: テストケースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inline.rb | `mrbgems/mruby-test-inline-struct/test/inline.rb` | dup/clone/mutate/object_id/IVテスト（18-118行目）を確認 |

**主要処理フロー**:
- **18-27行目**: dup/cloneが値コピーであることを検証
- **39-57行目**: mutate後もdup/cloneの元オブジェクトが影響を受けないことを検証
- **91-97行目**: インスタンス変数設定でArgumentErrorが発生することを検証
- **100-118行目**: プラットフォーム別のISTRUCTサイズ検証（24/12/6バイト）

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

```
mrb_mruby_test_inline_struct_gem_test
    │
    ├─ mrb_define_class(InlineStructTest)
    │   └─ MRB_SET_INSTANCE_TT(MRB_TT_ISTRUCT)
    │
    ├─ initialize ──▶ istruct_test_initialize
    │                   ├─ mrb_istruct_ptr(self)
    │                   └─ strncpy(型名文字列)
    │
    ├─ to_s ──▶ istruct_test_to_s
    │              └─ mrb_str_new_cstr(mrb_istruct_ptr)
    │
    ├─ mutate ──▶ istruct_test_mutate
    │               └─ memcpy(ptr, "mutate", 6)
    │
    ├─ length ──▶ istruct_test_length
    │               └─ mrb_istruct_size()
    │
    └─ test_receive ──▶ istruct_test_test_receive
                          └─ mrb_istruct_ptr(obj)[0] == 's'
```

### データフロー図

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

Integer/Float/ ───▶ istruct_test_initialize ───▶ ISTRUCT内データ
String/Other           │                             │
                       └─ strncpy(型名)              │
                                                     ▼
                       istruct_test_to_s ──────▶ String("fixnum"等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inline.c | `mrbgems/mruby-test-inline-struct/test/inline.c` | テスト | InlineStructTestクラス定義（C） |
| inline.rb | `mrbgems/mruby-test-inline-struct/test/inline.rb` | テスト | テストケース（Ruby） |
| mrbgem.rake | `mrbgems/mruby-test-inline-struct/mrbgem.rake` | 設定 | gem仕様定義 |
