# 機能設計書 80-TextEncoder/Decoder

## 概要

本ドキュメントは、BunのTextEncoder/TextDecoder機能の機能設計を記述する。これらはWHATWG Encoding Standardに準拠したテキストエンコーディング変換APIを提供する。

### 本機能の処理概要

BunのTextEncoder/TextDecoder APIは、文字列とバイナリデータ（Uint8Array）間の変換を行うWeb標準APIを提供する。TextEncoderは常にUTF-8を出力し、TextDecoderは多数のエンコーディングからのデコードをサポートする。

**業務上の目的・背景**：文字列のバイナリ表現の取得、バイナリデータからの文字列復元、国際化対応のエンコーディング変換など、テキストエンコーディング処理で使用される。Web標準互換により、ブラウザとサーバーでコードを共有可能。

**機能の利用シーン**：
- 文字列をUTF-8バイト列に変換
- バイナリデータから文字列を復元
- 各種エンコーディング（Shift_JIS、EUC-JP、ISO-8859-1等）からの変換
- ストリーミングデコード（部分的なデータの処理）
- BOMの処理

**主要な処理内容**：
1. TextEncoder.encode() - 文字列をUTF-8 Uint8Arrayに変換
2. TextEncoder.encodeInto() - 既存Uint8Arrayに書き込み
3. TextDecoder.decode() - バイト列を文字列に変換
4. ストリーミングモードでの部分デコード

**関連システム・外部連携**：Blob、Response、Request、Buffer、ストリームAPIと連携。

**権限による制御**：特に権限による制御は行われない。すべてのコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | コマンドライン/API経由での利用（画面なし） |

## 機能種別

テキストエンコーディング / Web標準API

## 入力仕様

### TextEncoderコンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | 引数なし | - |

### TextDecoderコンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | string | No | エンコーディング名 | 有効なラベル |
| options | TextDecoderOptions | No | デコードオプション | - |

### TextDecoderOptions

| オプション | 型 | デフォルト | 説明 |
|-----------|-----|-----------|------|
| fatal | boolean | false | 不正バイトでエラー発生 |
| ignoreBOM | boolean | false | BOMを無視する |

### サポートされるエンコーディング

| カテゴリ | エンコーディング |
|---------|-----------------|
| Unicode | UTF-8, UTF-16LE, UTF-16BE |
| 日本語 | Shift_JIS, EUC-JP, ISO-2022-JP |
| 韓国語 | EUC-KR |
| 中国語 | GBK, GB18030, Big5 |
| 西欧 | windows-1252 (latin1), ISO-8859-1 |
| キリル | windows-1251, KOI8-U, IBM866 |
| その他 | windows-874, ISO-8859-3/6/7/8等 |

### 入力データソース

TextEncoder: JavaScript文字列
TextDecoder: ArrayBuffer, TypedArray, DataView

## 出力仕様

### 出力データ

| メソッド | 戻り値 | 説明 |
|---------|--------|------|
| TextEncoder.encode() | Uint8Array | UTF-8エンコードされたバイト列 |
| TextEncoder.encodeInto() | {read, written} | 読み取った文字数と書き込んだバイト数 |
| TextDecoder.decode() | string | デコードされた文字列 |

### TextEncoderプロパティ

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| encoding | string | 常に"utf-8" |

### TextDecoderプロパティ

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| encoding | string | エンコーディング名 |
| fatal | boolean | fatalモードか |
| ignoreBOM | boolean | BOMを無視するか |

### 出力先

Uint8Arrayまたはstringとして返却。

## 処理フロー

### 処理シーケンス（TextEncoder.encode）

```
1. encode呼び出し
   └─ 入力文字列を取得
2. 文字列タイプ判定
   └─ Latin1(8bit) or UTF16(16bit)
3. UTF-8変換
   └─ copyLatin1IntoUTF8 or copyUTF16IntoUTF8
4. Uint8Array作成
   └─ JSCメモリに割り当て
5. 結果返却
```

### 処理シーケンス（TextDecoder.decode）

```
1. decode呼び出し
   └─ ArrayBuffer/TypedArrayを取得
2. streamオプション確認
   └─ 部分デコードか完全フラッシュか
3. エンコーディングに応じたデコード
   └─ UTF-8, UTF-16, その他
4. BOM処理
   └─ ignoreBOMでない場合はBOMを除去
5. 結果返却
```

### フローチャート

```mermaid
flowchart TD
    subgraph TextEncoder
    A1[encode] --> B1{文字列タイプ}
    B1 -->|Latin1| C1[copyLatin1IntoUTF8]
    B1 -->|UTF16| D1[copyUTF16IntoUTF8]
    C1 --> E1[Uint8Array作成]
    D1 --> E1
    E1 --> F1[結果返却]
    end

    subgraph TextDecoder
    A2[decode] --> B2{エンコーディング}
    B2 -->|UTF-8| C2[UTF-8デコード]
    B2 -->|UTF-16| D2[UTF-16デコード]
    B2 -->|その他| E2[TextCodecでデコード]
    C2 --> F2{BOM処理}
    D2 --> F2
    E2 --> F2
    F2 --> G2{fatalモード?}
    G2 -->|Yes, エラー| H2[エラー]
    G2 -->|No| I2[文字列返却]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | UTF-8出力固定 | TextEncoderは常にUTF-8を出力 | 常時 |
| BR-80-02 | 置換文字 | 不正バイト時は置換文字(U+FFFD)に変換 | fatal=false |
| BR-80-03 | エラースロー | 不正バイト時にTypeError | fatal=true |
| BR-80-04 | ストリーミング | stream=trueで部分データをバッファリング | decode時 |
| BR-80-05 | BOM除去 | ignoreBOM=falseでBOMを自動除去 | decode時 |

### 計算ロジック

**UTF-8バイト長計算**：
- ASCII (U+0000-U+007F): 1バイト
- U+0080-U+07FF: 2バイト
- U+0800-U+FFFF: 3バイト
- U+10000-U+10FFFF: 4バイト（サロゲートペア）

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

### 操作別データベース影響一覧

なし（データベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | Error | 不正なエンコーディングラベル | 有効なラベルを指定 |
| TypeError | Error | fatal=trueで不正バイト | データ修正またはfatal=false |
| RangeError | Error | サポートされないエンコーディング | サポート済みエンコーディングを使用 |

### リトライ仕様

なし（呼び出し側で制御）

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

なし

## パフォーマンス要件

- 小さな文字列はスタック割り当てで処理（2048バイトまで）
- ASCII文字列のファストパス
- SIMD最適化（可能な環境で）
- Rope文字列の効率的処理

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

- 不正なバイトシーケンスは置換文字に変換
- バッファオーバーフロー防止
- 出力バッファサイズの適切な計算

## 備考

内部実装の特徴：
- TextEncoderはZig実装で高速化
- TextDecoderは状態を保持（ストリーミング対応）
- Latin1とUTF-16で異なる処理パス
- WebKitのTextCodecを一部エンコーディングで使用

---

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

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

### 推奨読解順序

#### Step 1: TextEncoderを理解する

UTF-8エンコード処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TextEncoder.zig | `src/bun.js/webcore/TextEncoder.zig` | TextEncoder__encode8関数（3-35行目） |
| 1-2 | TextEncoder.zig | `src/bun.js/webcore/TextEncoder.zig` | TextEncoder__encode16関数（37-80行目） |

**読解のコツ**: encode8はLatin1文字列、encode16はUTF-16文字列を処理。小さい文字列はスタックバッファ使用。

**主要処理フロー**:
1. **3-35行目**: encode8でLatin1→UTF-8変換（小:スタック、大:ヒープ）
2. **37-80行目**: encode16でUTF-16→UTF-8変換（サロゲートペア対応）
3. **129-174行目**: RopeStringEncoderでRope文字列を効率処理

#### Step 2: TextDecoderを理解する

デコード処理と状態管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TextDecoder.zig | `src/bun.js/webcore/TextDecoder.zig` | TextDecoder構造体（1-30行目） |
| 2-2 | TextDecoder.zig | `src/bun.js/webcore/TextDecoder.zig` | decode関数（158-186行目） |
| 2-3 | TextDecoder.zig | `src/bun.js/webcore/TextDecoder.zig` | decodeSlice関数（192-310行目） |

**主要処理フロー**:
- **1-20行目**: 状態フィールド（buffered, lead_byte, lead_surrogate等）
- **17-19行目**: オプション（ignore_bom, fatal, encoding）
- **158-186行目**: decode関数（引数パース、stream判定）
- **192-310行目**: decodeSliceでエンコーディング別処理

#### Step 3: エンコーディングラベルを理解する

サポートされるエンコーディングの定義。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EncodingLabel.zig | `src/bun.js/webcore/EncodingLabel.zig` | EncodingLabel enum（1-60行目） |
| 3-2 | EncodingLabel.zig | `src/bun.js/webcore/EncodingLabel.zig` | string_mapエイリアス（62-150行目以降） |

**主要処理フロー**:
- **1-30行目**: EncodingLabel enum定義（UTF-8, UTF-16, Shift_JIS等）
- **31-58行目**: getLabel関数（enum→文字列）
- **62行目以降**: string_mapでエイリアス対応（latin1→windows-1252等）

#### Step 4: コンストラクタを理解する

TextDecoderの初期化処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TextDecoder.zig | `src/bun.js/webcore/TextDecoder.zig` | constructor関数（312-352行目） |

**主要処理フロー**:
- **312-331行目**: エンコーディングラベルのパースと検証
- **333-349行目**: オプション（fatal, ignoreBOM）の処理

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

```
TextEncoder:
encoder.encode(string)
    │
    ├─ JSString.is8Bit() 判定
    │      │
    │      ├─ true → TextEncoder__encode8()
    │      │         ├─ strings.copyLatin1IntoUTF8()
    │      │         └─ Uint8Array作成
    │      │
    │      └─ false → TextEncoder__encode16()
    │                 ├─ strings.copyUTF16IntoUTF8()
    │                 └─ Uint8Array作成
    │
    └─ Rope文字列の場合
           └─ TextEncoder__encodeRopeString()
                  └─ RopeStringEncoder.iter()

TextDecoder:
decoder.decode(arrayBuffer, options)
    │
    ├─ decode()
    │      ├─ 引数パース
    │      └─ stream判定
    │
    └─ decodeSlice()
           │
           ├─ encoding == UTF-8
           │      ├─ BOM除去（0xEF 0xBB 0xBF）
           │      ├─ バッファリング処理
           │      └─ strings.toUTF16AllocMaybeBuffered()
           │
           ├─ encoding == UTF-16LE/BE
           │      ├─ BOM除去
           │      └─ decodeUTF16()
           │
           └─ その他
                  └─ TextCodec.decode()

コンストラクタ:
new TextDecoder(label, options)
    │
    └─ constructor()
           ├─ EncodingLabel.which(label) でエンコーディング解決
           ├─ options.fatal 設定
           └─ options.ignoreBOM 設定
```

### データフロー図

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

TextEncoder.encode():
"Hello"            ───▶  encode8/encode16
(JS String)              ├─ Latin1/UTF16判定
                         └─ UTF-8変換
                                │
                                ▼
                         createUint8Array
                         └─ JSCメモリ割り当て  ───▶   Uint8Array

TextDecoder.decode():
Uint8Array         ───▶  decode()
(バイト列)               ├─ エンコーディング判定
                         │
                         ▼
                   UTF-8 path:
                         ├─ BOM除去
                         ├─ バッファ結合（stream時）
                         └─ toUTF16Alloc()
                                │
                                ▼
                         文字列生成               ───▶   string

ストリーミング:
chunk1             ───▶  decode(stream:true)
                         └─ 不完全バイトをバッファ
chunk2             ───▶  decode(stream:true)
                         └─ バッファ+新データ処理
chunk3             ───▶  decode(stream:false)
                         └─ フラッシュ            ───▶   完全文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TextEncoder.zig | `src/bun.js/webcore/TextEncoder.zig` | ソース | TextEncoder実装 |
| TextDecoder.zig | `src/bun.js/webcore/TextDecoder.zig` | ソース | TextDecoder実装 |
| EncodingLabel.zig | `src/bun.js/webcore/EncodingLabel.zig` | ソース | エンコーディングラベル定義 |
| encoding.zig | `src/bun.js/webcore/encoding.zig` | ソース | エンコーディングヘルパー |
| encoding.classes.ts | `src/bun.js/webcore/encoding.classes.ts` | 定義 | クラス定義 |
| TextEncoder.cpp | `src/bun.js/bindings/webcore/TextEncoder.cpp` | ソース | C++バインディング（未使用） |
| TextEncoderStreamEncoder.zig | `src/bun.js/webcore/TextEncoderStreamEncoder.zig` | ソース | ストリームエンコーダ |
| JSTextEncoder.cpp | `src/bun.js/bindings/webcore/JSTextEncoder.cpp` | ソース | JSバインディング |
