# 機能設計書 52-Array#pack / String#unpack

## 概要

本ドキュメントは、mrubyにおけるバイナリデータのパック・アンパック機能（Array#pack / String#unpack / String#unpack1）の設計を記述する。Ruby標準のバイナリデータ操作メソッドを提供し、構造化されたデータとバイト列の相互変換を実現する。

### 本機能の処理概要

Array#packは配列の各要素をフォーマット文字列（テンプレート）に従ってバイナリ文字列にエンコードする。String#unpackはその逆で、バイナリ文字列をフォーマット文字列に従って配列にデコードする。

**業務上の目的・背景**：ネットワークプロトコル、ファイルフォーマット、ハードウェアI/Oなど、バイナリデータの操作が必要な場面は組み込みシステムにおいて頻繁に発生する。mrubyが対象とする組み込み環境では、外部デバイスやプロトコルとの通信においてバイナリデータの構築・解析が不可欠であり、この機能はその基盤を提供する。

**機能の利用シーン**：バイナリプロトコルのパケット構築/解析、ファイルヘッダの読み書き、データのシリアライズ/デシリアライズ、Base64エンコード/デコード、数値のバイト列変換など。

**主要な処理内容**：
1. フォーマット文字列のパース（テンプレート文字の解析）
2. 整数型（C/S/L/Q）のバイト列変換（エンディアン対応）
3. 浮動小数点型（e/E/f/d/D/g/G）のバイト列変換
4. 文字列型（A/a/Z）のパディング付き変換
5. エンコーディング変換（UTF-8: U, BER: w）
6. ビット列変換（B/b）、16進文字列変換（H/h）
7. Base64エンコード/デコード（m）、UUエンコード/デコード（u）
8. Quoted-Printableエンコード/デコード（M）

**関連システム・外部連携**：Stringクラス、Arrayクラス、Numericクラスと連携する。エンディアン処理はプラットフォームのバイトオーダーに依存する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能であり、画面との直接的関連なし |

## 機能種別

データ変換処理（バイナリデータのパック/アンパック）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| template（pack） | String | Yes | パックフォーマット文字列 | 有効なフォーマット指定子のみ |
| self（pack） | Array | Yes | パックする要素を含む配列 | フォーマットに対応する型の要素 |
| template（unpack） | String | Yes | アンパックフォーマット文字列 | 有効なフォーマット指定子のみ |
| self（unpack） | String | Yes | アンパックするバイナリ文字列 | バイト列 |

### 入力データソース

Rubyプログラムからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pack結果 | String | バイナリエンコードされた文字列 |
| unpack結果 | Array | デコードされた値の配列 |
| unpack1結果 | Object | デコードされた最初の値のみ |

### 出力先

呼び出し元のRubyプログラムへの戻り値。

## 処理フロー

### 処理シーケンス

```
1. フォーマット文字列のパース
   └─ テンプレート文字、修飾子（!_<>）、カウントを解析
2. 各フォーマット指定子に対して変換処理を実行
   └─ 整数型: エンディアン考慮してバイト列に変換
   └─ 浮動小数点型: IEEE 754形式でバイト列に変換
   └─ 文字列型: パディング付きで格納
   └─ エンコーディング: UTF-8/BERエンコード
3. 結果をStringまたはArrayとして返却
```

### フローチャート

```mermaid
flowchart TD
    A[pack/unpack呼び出し] --> B[フォーマット文字列パース]
    B --> C{次の指定子あり?}
    C -->|Yes| D[指定子の種類を判定]
    D --> E{型判定}
    E -->|整数| F[pack_int/unpack_int]
    E -->|浮動小数点| G[pack_double/unpack_double]
    E -->|文字列| H[pack_str/unpack_str]
    E -->|UTF-8| I[pack_utf8/unpack_utf8]
    E -->|Base64| J[pack_base64/unpack_base64]
    E -->|その他| K[対応する変換処理]
    F --> C
    G --> C
    H --> C
    I --> C
    J --> C
    K --> C
    C -->|No| L[結果を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | エンディアン制御 | `>`で大きいエンディアン、`<`で小さいエンディアン、`!`や`_`でネイティブサイズを指定 | 整数型フォーマット指定子使用時 |
| BR-52-02 | カウント指定 | 数字でカウント指定、`*`で残り全部を意味する | 各フォーマット指定子 |
| BR-52-03 | パディング | Aはスペースパディング、aはヌルパディング、Zはヌル終端 | 文字列型フォーマット |
| BR-52-04 | 整数オーバーフロー | パック時に値が指定サイズを超える場合はオーバーフロー検出 | 整数型パック時 |

### 計算ロジック

- エンディアン変換: be_idx/le_idxルックアップテーブルによるバイト配置
- Base64: 6ビットを1文字に変換するbase64charsテーブル使用
- UTF-8: マルチバイトシーケンスの先頭バイトからシーケンス長を判定

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | 不正なUTF-8シーケンスのunpack | 入力データの妥当性確認 |
| - | ArgumentError | 冗長なUTF-8シーケンス | 正規化されたUTF-8を使用 |
| - | RangeError | 整数オーバーフロー | 適切なフォーマットサイズを指定 |
| - | TypeError | 型が不一致の要素をパック | 配列要素の型確認 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

- ビット処理にバッチ処理関数（pack_8_bits_msb/lsb）を使用して高速化
- 16進文字列変換にルックアップテーブル（hex_lookup）を使用
- エンディアン変換にインデックス配列（be_idx/le_idx）を使用
- UTF-8処理にシーケンス長ルックアップテーブルを使用

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

- バッファオーバーフロー: pack.cでは文字列長の厳密なチェックを行い、バッファ境界を超えるアクセスを防止
- 不正なUTF-8入力: malformedおよびredundantなUTF-8シーケンスを検出して例外を発生

## 備考

- pack.cは約2100行超の大規模な実装であり、Ruby標準のpackフォーマットの主要部分をサポートしている
- フォーマット指定子はenum pack_dirで定義され、テンプレートパース結果はstruct tmplで管理される
- unpack1メソッドはunpackの最初の要素のみを返す最適化版

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pack.c | `mrbgems/mruby-pack/src/pack.c` | struct tmpl: テンプレート文字列管理構造体（26-29行目） |
| 1-2 | pack.c | `mrbgems/mruby-pack/src/pack.c` | enum pack_dir: フォーマット指定子の列挙型（31-52行目） |
| 1-3 | pack.c | `mrbgems/mruby-pack/src/pack.c` | enum pack_type: データ型の分類（54-59行目） |
| 1-4 | pack.c | `mrbgems/mruby-pack/src/pack.c` | PACK_FLAGマクロ群: フォーマット修飾子フラグ（61-70行目） |

**読解のコツ**: pack_dirはフォーマット文字列の各文字（C, S, L, Q, U, A等）に対応する。PACK_FLAG_GTとPACK_FLAG_LTはエンディアン指定（>と<）に対応する。

#### Step 2: ルックアップテーブルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pack.c | `mrbgems/mruby-pack/src/pack.c` | base64chars/base64_dec_tab: Base64変換テーブル（77-92行目） |
| 2-2 | pack.c | `mrbgems/mruby-pack/src/pack.c` | hex_lookup: 16進文字変換テーブル（95-112行目） |
| 2-3 | pack.c | `mrbgems/mruby-pack/src/pack.c` | be_idx/le_idx: エンディアン変換用インデックス配列（114-119行目） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pack.c | `mrbgems/mruby-pack/src/pack.c` | mrb_mruby_pack_gem_init(): メソッド登録（2119-2124行目） |

**主要処理フロー**:
- **2121行目**: Array#packメソッドの登録
- **2122行目**: String#unpackメソッドの登録
- **2123行目**: String#unpack1メソッドの登録

#### Step 4: ビット処理ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pack.c | `mrbgems/mruby-pack/src/pack.c` | pack_8_bits_msb/lsb: 8ビットバッチパック（133-161行目） |
| 4-2 | pack.c | `mrbgems/mruby-pack/src/pack.c` | unpack_8_bits_msb/lsb: 8ビットバッチアンパック（163-187行目） |

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

```
Array#pack (mrb_pack_pack)
    |
    +-- テンプレートパース
    |    +-- フォーマット文字解析
    |    +-- カウント/修飾子解析
    |
    +-- pack_int()      (整数パック)
    +-- pack_double()   (浮動小数点パック)
    +-- pack_str()      (文字列パック)
    +-- pack_utf8()     (UTF-8パック)
    +-- pack_base64()   (Base64パック)
    +-- pack_hex()      (16進パック)
    +-- pack_bstr()     (ビット列パック)

String#unpack (mrb_pack_unpack)
    |
    +-- テンプレートパース
    |
    +-- unpack_int()    (整数アンパック)
    +-- unpack_double() (浮動小数点アンパック)
    +-- unpack_str()    (文字列アンパック)
    +-- unpack_utf8()   (UTF-8アンパック)
    +-- unpack_base64() (Base64アンパック)
    +-- unpack_hex()    (16進アンパック)
    +-- unpack_bstr()   (ビット列アンパック)
```

### データフロー図

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

Array + template  ───> pack処理 ──────────────> String (バイナリ)
                        |
                        +-- 各要素を変換
                        +-- エンディアン制御
                        +-- パディング制御

String + template ───> unpack処理 ────────────> Array (値の配列)
                        |
                        +-- バイト列を解析
                        +-- 型変換
                        +-- エンディアン復元
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pack.c | `mrbgems/mruby-pack/src/pack.c` | ソース | Array#pack, String#unpack, String#unpack1のC実装 |
| pack.rb | `mrbgems/mruby-pack/test/pack.rb` | テスト | pack/unpackの動作テスト |
| mrbgem.rake | `mrbgems/mruby-pack/mrbgem.rake` | 設定 | gemメタデータ定義 |
