active: true
derived: false
gherkin: |
  Feature: Custom type registration
    Scenario: Registering custom encoders and decoders
      Given a custom Python type
      When register or register_type is called with a code and conversion functions
      Then the type can be safely serialized and deserialized by the MsgpackSerializer
groups:
- SERIAL
header: |
  カスタム型登録
level: 2.13
links:
- ARCH005: f7IpeWL9LR7SQ3LP4FNILP4SUho1yMVkYhHP8_dKm8Y=
normative: true
ref: ''
reviewed: 8SbtALw18uXNF-e3isaTGtrntgRaXCf_qCYm32RhK2M=
text: |
  ## インターフェース

  ```python
  def register(
      code: int,
      encoder: Callable[[Any], Any],
      decoder: Callable[[Any], Any],
  ) -> Callable: ... # デコレータ形式

  def register_type(
      type_class: Type,
      code: int,
      encoder: Callable[[Any], Any],
      decoder: Callable[[Any], Any],
  ) -> None: ...
  ```

  ## 振る舞い

  1. **重複チェック**: 同一コードまたは同一クラスが既に登録されていないか確認
  2. **CoW更新**: 現在のレジストリ辞書をコピーし、新しいエントリを追加した後に参照を差し替える
  3. **世代更新**: `_registry_generation` をインクリメントし、全スレッドのLRUキャッシュを無効化対象とする

  ## パラメータ詳細

  | パラメータ | 制限 | 説明 |
  |---|---|---|
  | `code` | `0` 〜 `127` | MessagePack ExtType のユーザー定義領域コード |
  | `encoder` | 引数1、戻り値シリアライズ可能 | オブジェクトをプリミティブ構造へ変換する関数 |
  | `decoder` | 引数1、戻り値オブジェクト | プリミティブ構造からオブジェクトを復元する関数 |

  ## エラーハンドリング

  - **コード重複**: `ValueError` を送出し、レジストリの破損を防ぐ
  - **範囲外コード**: 128以上のコードを指定した場合は `ValueError`

  ## エッジケース

  - **継承**: 基底クラスを登録すると、サブクラスも自動的にそのエンコーダを使用する（オーバーライド可能）

  ## 設計判断

  標準では対応できないユーザー定義のクラス（Pandas DataFrameやPydanticモデル等）を、MessagePack経由で安全にシリアライズ・デシリアライズするための登録インターフェースを提供するため。
