# 機能設計書 103-marshal

## 概要

本ドキュメントは、Nim標準ライブラリの`marshal`モジュールの機能設計を記述する。このモジュールは、任意のNimデータ構造のシリアライズ（直列化）およびデシリアライズ（復元）機能を提供する。

### 本機能の処理概要

`marshal`モジュールは、Nimの任意のデータ構造をJSON形式で保存・復元するための機能を提供する。コンパイル時と実行時の両方で使用可能であり、データの永続化やプロセス間通信に活用できる。

**業務上の目的・背景**：アプリケーション開発において、オブジェクトの状態を保存・復元する必要がある場面は多い。設定ファイルの読み書き、キャッシュデータの保存、デバッグ用のデータダンプなど、様々な用途でシリアライズ機能が必要となる。本モジュールはJSONを中間形式として使用することで、人間が読みやすく、他システムとの互換性も確保できるシリアライズを実現する。

**機能の利用シーン**：アプリケーション状態の保存・復元、設定ファイルの読み書き、テスト用データの生成・検証、デバッグ時のオブジェクト内容確認など。

**主要な処理内容**：
1. 任意のNimオブジェクトをJSON文字列にシリアライズ（`$$`演算子）
2. JSON文字列からNimオブジェクトにデシリアライズ（`to`関数）
3. ストリームへのシリアライズ出力（`store`関数）
4. ストリームからのデシリアライズ読み込み（`load`関数）

**関連システム・外部連携**：`streams`、`typeinfo`、`json`モジュールとの連携。

**権限による制御**：権限による制御は存在しない。

## 関連画面

本モジュールは標準ライブラリであり、特定の画面との関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

データ変換 / シリアライズ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | T (ジェネリック) | Yes | シリアライズ対象のデータ | 任意のNim型 |
| data | string | Yes | デシリアライズするJSON文字列 | 有効なJSON形式 |
| s | Stream | Yes | 入出力ストリーム | 有効なストリーム |

### 入力データソース

プログラムコードからの直接呼び出し、ストリーム入力。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| string | string | JSON形式のシリアライズ結果 |
| T | T (ジェネリック) | デシリアライズされたオブジェクト |

### 出力先

呼び出し元への戻り値、ストリーム。

## 処理フロー

### 処理シーケンス

```
1. シリアライズ ($$)
   └─ toAnyでランタイム型情報を取得
   └─ storeAnyで再帰的にJSON出力
   └─ ポインタ共有を検出して効率化

2. デシリアライズ (to)
   └─ JsonParserでJSON解析
   └─ loadAnyで再帰的に値を復元
   └─ ポインタ参照を再構築

3. ストリーム書き込み (store)
   └─ storeAnyでストリームに出力

4. ストリーム読み込み (load)
   └─ loadAnyでストリームから読み込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始: シリアライズ] --> B[toAnyで型情報取得]
    B --> C{型の種類?}
    C -->|基本型| D[直接JSON出力]
    C -->|配列/シーケンス| E[要素を再帰処理]
    C -->|オブジェクト| F[フィールドを再帰処理]
    C -->|参照型| G{既存ポインタ?}
    G -->|Yes| H[ポインタIDのみ出力]
    G -->|No| I[ID付きで値を出力]
    D --> J[終了]
    E --> J
    F --> J
    H --> J
    I --> J

    K[開始: デシリアライズ] --> L[JSONパーサーで解析]
    L --> M{トークンの種類?}
    M -->|数値| N[数値として復元]
    M -->|文字列| O[文字列として復元]
    M -->|配列| P[要素を再帰復元]
    M -->|オブジェクト| Q[フィールドを再帰復元]
    M -->|null| R[nilを設定]
    N --> S[終了]
    O --> S
    P --> S
    Q --> S
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | オブジェクト型制限 | オブジェクトのランタイム型は保存されない | 継承を使用したオブジェクト |
| BR-02 | ポインタ共有 | 同一ポインタは一度だけシリアライズ | 参照型の循環参照時 |
| BR-03 | プラットフォーム制限 | JavaScript/NimScriptでは使用不可 | 対象プラットフォーム |
| BR-04 | コンパイル時使用 | コンパイル時でも使用可能（VM経由） | static/const式内 |

### 計算ロジック

**シリアライズのJSONマッピング**:
- Bool: `true` / `false`
- Char: 文字列またはコードポイント
- Int/Float: 数値
- String: 文字列（非UTF-8は配列）
- Array/Seq: `[...]`
- Object/Tuple: `{"field": value, ...}`
- Set: `[elements...]`
- Enum: 文字列（名前）
- Ref/Ptr: `[pointer_id, value]` または `pointer_id`
- nil: `null`

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| JsonParsingError | 実行時例外 | 不正なJSON形式 | 正しいJSON形式を入力 |
| IOError | 実行時例外 | ストリーム読み書きエラー | ストリームの状態を確認 |

### リトライ仕様

リトライは不要。

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

トランザクション管理は不要。

## パフォーマンス要件

- シリアライズ/デシリアライズはオブジェクトサイズに比例
- ポインタ共有検出によりメモリ効率を最適化
- IntSetを使用した高速なポインタID管理

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

- 信頼できないソースからのデシリアライズには注意が必要
- ポインタの復元により任意のメモリ位置にアクセス可能な潜在的リスク

## 備考

- JavaScript、NimScriptプラットフォームでは使用不可
- オブジェクトの継承型情報は保存されないため、基底型として復元される

---

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

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

### 推奨読解順序

#### Step 1: モジュールの制約を理解する

プラットフォーム制限と基本的な制約を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | marshal.nim | `lib/pure/marshal.nim` | 46-55行目: プラットフォーム制限（JS/NimScript不可） |
| 1-2 | marshal.nim | `lib/pure/marshal.nim` | 10-15行目: オブジェクト型の制限事項 |
| 1-3 | marshal.nim | `lib/pure/marshal.nim` | 57行目: 依存モジュールのimport |

**読解のコツ**: `when defined(js):`や`when defined(nimscript):`で条件コンパイルが行われている。このモジュールはtypeinfo（ランタイム型情報）に依存しており、これがJSバックエンドでは利用できない。

#### Step 2: シリアライズ処理を理解する

storeAny関数の再帰的なシリアライズロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | marshal.nim | `lib/pure/marshal.nim` | 62-64行目: ptrToIntヘルパー |
| 2-2 | marshal.nim | `lib/pure/marshal.nim` | 65-128行目: storeAny関数 |
| 2-3 | marshal.nim | `lib/pure/marshal.nim` | 295-312行目: store関数 |
| 2-4 | marshal.nim | `lib/pure/marshal.nim` | 317-343行目: `$$`演算子 |

**主要処理フロー**:
- **66-67行目**: akNoneはアサーション失敗
- **68-74行目**: Bool、Charの処理
- **75-80行目**: 配列/シーケンスは`[...]`で出力
- **81-90行目**: オブジェクト/タプルは`{...}`で出力
- **91-98行目**: セットは要素の配列として出力
- **101-114行目**: 参照型はポインタIDで共有を検出

#### Step 3: デシリアライズ処理を理解する

loadAny関数のJSONパース処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | marshal.nim | `lib/pure/marshal.nim` | 130-273行目: loadAny関数（メイン） |
| 3-2 | marshal.nim | `lib/pure/marshal.nim` | 275-280行目: loadAny関数（Stream版） |
| 3-3 | marshal.nim | `lib/pure/marshal.nim` | 282-293行目: load関数 |
| 3-4 | marshal.nim | `lib/pure/marshal.nim` | 348-368行目: to関数 |

**主要処理フロー**:
- **133-138行目**: Boolのパース（jsonFalse/jsonTrue）
- **139-150行目**: Charのパース（文字列またはint）
- **151-156行目**: Enumのパース（文字列から序数へ）
- **157-165行目**: 配列のパース
- **207-227行目**: 参照型のパース（null/int/配列形式）

#### Step 4: コンパイル時実行を理解する

VM経由でのコンパイル時シリアライズを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | marshal.nim | `lib/pure/marshal.nim` | 314-315行目: loadVM関数（VMops用プレースホルダ） |
| 4-2 | marshal.nim | `lib/pure/marshal.nim` | 332-333行目: `$$`のwhen nimvm分岐 |
| 4-3 | marshal.nim | `lib/pure/marshal.nim` | 345-346行目: toVM関数（VMops用プレースホルダ） |
| 4-4 | marshal.nim | `lib/pure/marshal.nim` | 363-364行目: toのwhen nimvm分岐 |

**読解のコツ**: `when nimvm:`ブロックはコンパイル時に実行される。実際のVM実装は`compiler/vmops.nim`にあり、ここではプレースホルダとして`raiseAssert`が使用されている。

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

```
marshal.nim
    │
    ├─ シリアライズ
    │      ├─ `$$` ─── toAny ─── storeAny
    │      │              │
    │      │              └─ initIntSet (ポインタ追跡)
    │      │
    │      └─ store ─── storeAny
    │
    ├─ デシリアライズ
    │      ├─ to ─── loadAny ─── JsonParser
    │      │              │
    │      │              └─ Table (ポインタ復元)
    │      │
    │      └─ load ─── loadAny
    │
    └─ VM実行（コンパイル時）
           ├─ loadVM (vmops.nim)
           └─ toVM (vmops.nim)
```

### データフロー図

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

Nimオブジェクト ─────────▶ toAny ─────────────────▶ Any (ランタイム型情報)
                              │
                              ▼
Any ─────────────────────▶ storeAny ──────────────▶ JSON文字列/Stream

JSON文字列 ──────────────▶ JsonParser ─────────────▶ トークン列
                              │
                              ▼
トークン列 ──────────────▶ loadAny ────────────────▶ Nimオブジェクト

ポインタ情報:
  シリアライズ: IntSet (訪問済みポインタID)
  デシリアライズ: Table[BiggestInt, pointer] (ポインタ復元用)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| marshal.nim | `lib/pure/marshal.nim` | ソース | メインモジュール、全機能の実装 |
| streams.nim | `lib/pure/streams.nim` | 依存 | ストリーム入出力 |
| typeinfo.nim | `lib/pure/typeinfo.nim` | 依存 | ランタイム型情報 (toAny等) |
| json.nim | `lib/pure/json.nim` | 依存 | JSONパーサー |
| intsets.nim | `lib/pure/collections/intsets.nim` | 依存 | ポインタID管理用IntSet |
| tables.nim | `lib/pure/collections/tables.nim` | 依存 | ポインタ復元用Table |
| unicode.nim | `lib/pure/unicode.nim` | 依存 | UTF-8検証 |
