3. Specification of the CBOR Encoding (CBORエンコーディング仕様)
CBORデータ項目 (Data Item、セクション2) は、このセクションで説明されているように、整形式のエンコードされたデータ項目を含むバイト列にエンコードされるか、またはそこからデコードされます。エンコーディングは、初期バイトによってインデックス付けされた付録Bの表7に要約されています。エンコーダは整形式のエンコードされたデータ項目のみを生成しなければなりません (MUST)。デコーダが整形式のエンコードされたCBORデータ項目ではない入力に遭遇した場合、デコードされたデータ項目を返してはなりません (MUST NOT) (これは、破損したエンコードされたCBORデータ項目から何らかの情報を提供できる診断および回復ツールの有用性を損なうものではありません)。
各エンコードされたデータ項目の初期バイト (Initial Byte) には、主タイプ (Major Type、上位3ビット、セクション3.1で説明) と追加情報 (Additional Information、下位5ビット) に関する情報が含まれています。いくつかの例外を除き、追加情報の値は、符号なし整数「引数」(Argument) をロードする方法を説明します。
24未満: 引数の値は追加情報の値です。
24、25、26、または27: 引数の値は、それぞれ後続の1、2、4、または8バイトにネットワークバイトオーダーで格納されます。主タイプ7および追加情報値25、26、27の場合、これらのバイトは整数引数として使用されず、浮動小数点値として使用されます (セクション3.3を参照)。
28、29、30: これらの値はCBORフォーマットの将来の追加のために予約されています。現在のバージョンのCBORでは、エンコードされた項目は整形式ではありません。
31: 引数値は導出されません。主タイプが0、1、または6の場合、エンコードされた項目は整形式ではありません。主タイプ2から5の場合、項目の長さは不定 (Indefinite) であり、主タイプ7の場合、このバイトはデータ項目をまったく構成せず、不定長の項目を終了します。これらはすべてセクション3.2で説明されています。
初期バイトと引数を構築するために消費された追加バイトは、総称してデータ項目のヘッド (Head) と呼ばれます。
この引数の意味は主タイプに依存します。たとえば、主タイプ0では、引数はデータ項目自体の値です (主タイプ1では、データ項目の値は引数から計算されます); 主タイプ2および3では、後続の文字列データのバイト長を示します; 主タイプ4および5では、含まれるデータ項目の数を決定するために使用されます。
エンコードされたバイトシーケンスがデータ項目の終了前に終了する場合、その項目は整形式ではありません。最も外側のエンコードされた項目をデコードした後、エンコードされたバイトシーケンスにまだバイトが残っている場合、そのエンコーディングは単一の整形式のCBOR項目ではありません。アプリケーションに応じて、デコーダはエンコーディングを不正形式と見なすか、残りのバイトの開始位置をアプリケーションに通知するだけです。
CBORデコーダ実装は、初期バイトの256個すべての定義された値を含むジャンプテーブル (Jump Table) に基づくことができます (表7)。制約された実装のデコーダは、初期バイトと後続バイトの構造を使用して、よりコンパクトなコードを実装できます (その大まかな外観については付録Cを参照)。
3.1. Major Types (主タイプ)
以下に、主タイプとタイプ関連の追加情報および他のバイトを示します。
主タイプ0 (Major type 0):
0..2^64-1 (両端を含む) の範囲の符号なし整数 (Unsigned Integer)。エンコードされた項目の値は引数そのものです。たとえば、整数10は単一バイト0b000_01010 (主タイプ0、追加情報10) として表されます。整数500は0b000_11001 (主タイプ0、追加情報25) に続いて2バイト0x01f4、つまり10進数の500となります。
主タイプ1 (Major type 1):
-2^64..-1 (両端を含む) の範囲の負の整数 (Negative Integer)。項目の値は-1から引数を引いたものです。たとえば、整数-500は0b001_11001 (主タイプ1、追加情報25) に続いて2バイト0x01f3、つまり10進数の499となります。
主タイプ2 (Major type 2):
バイト列 (Byte String)。文字列のバイト数は引数と等しくなります。たとえば、長さ5のバイト列は、初期バイト0b010_00101 (主タイプ2、長さを示す追加情報5) に続いて5バイトのバイナリコンテンツが続きます。長さ500のバイト列には、3つの初期バイト0b010_11001 (主タイプ2、2バイト長を示す追加情報25) に続いて長さ500を示す2バイト0x01f4、その後500バイトのバイナリコンテンツが続きます。
主タイプ3 (Major type 3):
UTF-8 [RFC3629] でエンコードされたテキスト列 (Text String、セクション2)。文字列のバイト数は引数と等しくなります。無効なUTF-8シーケンスを含む文字列は整形式ですが無効です (セクション1.2)。このタイプは、人間が読めるテキストを解釈または表示する必要があるシステムに提供され、非構造化バイトと指定された文字セット (Unicode) およびエンコーディング (UTF-8) を持つテキストを区別できます。JSONなどの形式とは異なり、このタイプのUnicode文字はエスケープされることはありません。したがって、改行文字 (U+000A) は常に文字列内でバイト0x0aとして表され、バイト0x5c6e (文字「\」と「n」) または0x5c7530303061 (文字「\」、「u」、「0」、「0」、「0」、および「a」) としては表されません。
主タイプ4 (Major type 4):
データ項目の配列 (Array)。他の形式では、配列はリスト (List)、シーケンス (Sequence)、またはタプル (Tuple) とも呼ばれます (「CBORシーケンス」は若干異なるもので、[RFC8742]を参照)。引数は配列内のデータ項目の数です。配列内の項目はすべて同じタイプである必要はありません。たとえば、任意のタイプの10個の項目を含む配列の初期バイトは0b100_01010 (主タイプ4、長さを示す追加情報10) で、その後に残りの10個の項目が続きます。
主タイプ5 (Major type 5):
データ項目ペアのマップ (Map)。マップはテーブル (Table)、辞書 (Dictionary)、ハッシュ (Hash)、またはオブジェクト (Object、JSONの場合) とも呼ばれます。マップはデータ項目ペアで構成され、各ペアにはキー (Key) が含まれ、その後に値 (Value) が続きます。引数はマップ内のデータ項目ペアの数です。たとえば、9つのペアを含むマップの初期バイトは0b101_01001 (主タイプ5、ペア数を示す追加情報9) で、その後に残りの18個の項目が続きます。最初の項目は最初のキー、2番目の項目は最初の値、3番目の項目は2番目のキー、というように続きます。マップ内の項目はペアで出現するため、その総数は常に偶数です。奇数個の項目を含むマップ (最後のキーデータ項目の後に値データがない) は整形式ではありません。重複したキーを持つマップは整形式である可能性がありますが、有効ではなく、不確定なデコードにつながります。セクション5.6も参照してください。
主タイプ6 (Major type 6):
タグ付きデータ項目 (Tagged Data Item、「タグ」)、そのタグ番号 (Tag Number) は0..2^64-1 (両端を含む) の範囲の整数であり、引数であり、その囲まれたデータ項目 (タグコンテンツ、Tag Content) はヘッドの後の単一のエンコードされたデータ項目です。セクション3.4を参照してください。
主タイプ7 (Major type 7):
浮動小数点数と単純値、および「break」停止コード。セクション3.3を参照してください。
これら8つの主タイプは、データ項目の初期バイトの256個の可能な値のどれが使用されているかを示す単純な表を形成します (表7)。
主タイプ6と7では、多くの可能な値が将来の仕様のために予約されています。これらの値の詳細については、セクション9を参照してください。
表1は、セクション3.2を一時的に無視して、CBORで定義された主タイプを要約しています。この表の数字Nは引数を表します。
+============+=======================+=========================+
| 主タイプ | 意味 | コンテンツ |
+============+=======================+=========================+
| 0 | 符号なし整数 N | - |
+------------+-----------------------+-------------------------+
| 1 | 負の整数 -1-N | - |
+------------+-----------------------+-------------------------+
| 2 | バイト列 | Nバイト |
+------------+-----------------------+-------------------------+
| 3 | テキスト列 | Nバイト (UTF-8テキスト) |
+------------+-----------------------+-------------------------+
| 4 | 配列 | Nデータ項目 (要素) |
+------------+-----------------------+-------------------------+
| 5 | マップ | 2Nデータ項目 |
| | | (キー/値ペア) |
+------------+-----------------------+-------------------------+
| 6 | 番号Nのタグ | 1データ項目 |
+------------+-----------------------+-------------------------+
| 7 | 単純値/浮動小数点 | - |
+------------+-----------------------+-------------------------+
表1: CBOR主タイプの固定長使用の概要 (N = 引数)
3.2. Indefinite Lengths for Some Major Types (一部の主タイプの不定長)
4つのCBOR項目 (配列、マップ、バイト列、テキスト列) は、追加情報値31を使用して不定長 (Indefinite Length) でエンコードできます。これは、配列またはマップ内の項目数または文字列の合計長がわかる前にその項目のエンコードを開始する必要がある場合に便利です (データ項目の全コンテンツがわかる前にデータ項目の送信を開始する機能は、そのデータ項目内で「ストリーミング」(Streaming) と呼ばれることがよくあります)。
不定長配列とマップは、不定長文字列 (バイト列とテキスト列) とは異なる方法で処理されます。
3.2.1. The "break" Stop Code (「break」停止コード)
「break」停止コードは、主タイプ7および追加情報値31 (0b111_11111) でエンコードされます。これ自体はデータ項目ではありません。不定長項目を閉じるための構文的特徴にすぎません。
「break」停止コードがデータ項目が予期される位置に出現するが、不定長文字列、配列、またはマップの直接内ではない場合 (たとえば、固定長配列またはマップの直接内) -- 含まれている項目は整形式ではありません。
3.2.2. Indefinite-Length Arrays and Maps (不定長配列とマップ)
不定長配列とマップは、それらの主タイプと追加情報値31で指定され、配列の場合は任意の長さのゼロ個以上の項目のシーケンス、マップの場合はキー/値ペアのシーケンスが続き、最後に「break」停止コード (セクション3.2.1) で終了します。言い換えれば、不定長配列とマップは他の配列とマップと同じように見えますが、追加情報値31で始まり、「break」停止コードで終わる点が異なります。
3.2.3. Indefinite-Length Byte Strings and Text Strings (不定長バイト列とテキスト列)
不定長文字列のエンコード方法:
- 主タイプバイト (追加情報値31) + ゼロ個以上の固定長文字列ブロック + 「break」停止コード
- 最終データ項目はすべてのブロックの連結です
- ブロック間に不定長文字列をネストすることはできません
- テキスト列の各ブロックはUnicodeコードポイント境界で開始する必要があります (UTF-8バイトはブロック間で分割できません)
例:
5F -- 不定長バイト列開始
44 -- 長さ4のバイト列
aabbccdd -- バイトコンテンツ
43 -- 長さ3のバイト列
eeff99 -- バイトコンテンツ
FF -- 「break」
デコード結果: 単一の7バイトのバイト列0xaabbccddeeff99
3.2.4. Summary of Indefinite-Length Use of Major Types (不定長使用の要約)
表2: 主タイプの不定長使用 (追加情報 = 31)
| 主タイプ | 意味 | 「break」前のコンテンツ |
|---|---|---|
| 0 | (不整形式) | - |
| 1 | (不整形式) | - |
| 2 | バイト列 | 固定長バイト列 |
| 3 | テキスト列 | 固定長テキスト列 |
| 4 | 配列 | データ項目 (要素) |
| 5 | マップ | データ項目 (キー/値ペア) |
| 6 | (不整形式) | - |
| 7 | 「break」停止コード | - |
重要なポイント:
- 主タイプ0、1、6は不定長をサポートしていません
- 主タイプ2-5は不定長エンコーディングをサポートしています
- 不定長はストリーミングを可能にし、合計長がわかる前にエンコードを開始できます
3.3. Floating-Point Numbers and Values with No Content (浮動小数点数とコンテンツなし値)
主タイプ7の特別な用途:
主タイプ7は浮動小数点数と単純値をエンコードするために使用されます。
単純値 (Simple Values):
false(20)、true(21)、null(22)、undefined(23)- 追加情報0-19: 未割り当ての単純値
- 追加情報24: 1バイト単純値拡張 (値32-255)
浮動小数点エンコーディング:
- 追加情報25: 半精度浮動小数点数 (IEEE 754 binary16、2バイト)
- 追加情報26: 単精度浮動小数点数 (IEEE 754 binary32、4バイト)
- 追加情報27: 倍精度浮動小数点数 (IEEE 754 binary64、8バイト)
特殊値の例:
false: 0xF4true: 0xF5null: 0xF6undefined: 0xF7- 浮動小数点数0.0: 0xF90000 (半精度) または0xFA00000000 (単精度)
設計上の考慮事項:
- エンコードサイズを最適化するための複数の精度オプションを提供
- IEEE 754のすべての特殊値 (NaN、Infinityなど) をサポート
- 単純値は一般的なブール値とnull値にコンパクトなエンコーディングを提供
3.4. Tagging of Items (項目のタグ付け)
タグメカニズム (Tags) はデータ項目にセマンティック情報を追加するために使用されます。
タグ構造:
- 主タイプ6 + タグ番号 (引数として) + タグコンテンツ (1つのデータ項目)
- タグ番号範囲: 0から2^64-1
標準タグの例:
| タグ番号 | セマンティクス | 例 |
|---|---|---|
| 0 | RFC 3339日時文字列 | "2013-03-21T20:04:00Z" |
| 1 | Unixタイムスタンプ (エポック秒) | 1363896240 |
| 2 | 正の大数 (Positive Bignum) | 18446744073709551616 |
| 3 | 負の大数 (Negative Bignum) | -18446744073709551617 |
| 4 | 10進分数 | [e, m] は m×10^e を意味 |
| 5 | 大浮動小数点数 (Bigfloat) | [e, m] は m×2^e を意味 |
3.4.1-3.4.6 タグタイプの詳細
日時タグ (0と1):
- タグ0: テキスト形式の日時 (RFC 3339形式)
- タグ1: 数値形式のタイムスタンプ (Unixエポック秒)
大数タグ (2と3):
- 64ビット整数範囲を超える数値を表現するため
- タグコンテンツはビッグエンディアン順で数値を表すバイト列
数値拡張タグ (4と5):
- 10進分数: 10進数の正確な表現
- 大浮動小数点数: 任意精度の2進浮動小数点数
その他のよく使用されるタグ:
- タグ21-23: base64エンコーディングヒント
- タグ24: エンコードされたCBORデータ項目
- タグ32: URI
- タグ55799: 自己記述CBOR識別
拡張性:
- タグはIANAレジストリによって管理されます
- アプリケーションはプライベートタグを定義できます (競合を避ける)
- デコーダは選択的にタグをサポートでき、未知のタグはアプリケーションに渡すことができます
第3章の要約:
この章では、次を含むCBORの完全なエンコーディング仕様を定義しています:
- 8つの主タイプのエンコーディング規則
- 不定長エンコーディングメカニズム
- 浮動小数点数と単純値の表現
- タグ拡張システム
これらの設計により、CBORはコンパクトかつ柔軟になり、IoTおよび制約された環境での使用に適しています。