Binn仕様

June 2, 2023 · View on GitHub

フォーマット

各値は、4つの可能なパラメータで格納されます。

[type][size][count][data]

しかし、ほとんどはオプションです。すべての値で使用されるのはtypeパラメータだけです。以下は、基本データ型に使用されるパラメータのリストです。

boolean, null:
[type]

int, float (storage: byte, word, dword or qword):
[type][data]

string, blob:
[type][size][data]

list, object, map:
[type][size][count][data]

各パラメータは、多態的なサイズで格納できます。

パラメータサイズ
[type]1または2バイト
[size]1または4バイト
[count]1または4バイト
[data]nバイト

[Type]

各値は、データ型から始まるように格納されます。1バイトまたは2バイトを使用できます。最初のバイトは次のように分割されます。

 +-------- ストレージタイプ
 |  +----- サブタイプサイズ
 |  |  +-- サブタイプ
000 0 0000

ストレージ

最も重要な3ビットは、ストレージタイプに使用されます。データが使用するバイト数に関する情報が含まれています。ストレージタイプは、以下のいずれかになります。

  • 追加のバイトなし
  • 1バイト
  • ワード(2バイト、ビッグエンディアン)
  • ダブルワード(4バイト、ビッグエンディアン)
  • クワッドワード(8バイト、ビッグエンディアン)
  • 文字列(UTF-8、ヌル終端)
  • ブロブ
  • コンテナ

定数は以下の通りです。

ストレージビット16進数10進数
NOBYTES000 0 00000x000
BYTE001 0 00000x2032
WORD010 0 00000x4064
DWORD011 0 00000x6096
QWORD100 0 00000x80128
STRING101 0 00000xA0160
BLOB110 0 00000xC0192
CONTAINER111 0 00000xE0224

サブタイプサイズ

次のビットは、タイプが1バイトまたは2バイトを使用するかどうかを示します。

ビットが0の場合、タイプは1バイトのみを使用し、サブタイプは4ビット(0から15)です。

 +-------- ストレージタイプ
 |  +----- サブタイプサイズ
 |  |  +-- サブタイプ
000 0 0000

ビットが1の場合、タイプに別のバイトが使用され、サブタイプは12ビット(最大4096)です。

 +-------- ストレージタイプ
 |  +----- サブタイプサイズ
 |  |
000 1 0000  0000 0000
      |  サブタイプ   |
      +-------------+

サブタイプ

各ストレージには、最大4096のサブタイプがあります。それらは、そのストレージ空間に格納されている値の種類を保持します。

例: DWORDには、符号付き整数、符号なし整数、単精度浮動小数点数など、さまざまな値が含まれることがあります。ユーザー定義の型も含まれます。

以下は、基本データ型の値で、サブタイプが強調表示されています。

タイプストレージビット16進数10進数
NullNOBYTES0000 00000x000
TrueNOBYTES0000 00010x011
FalseNOBYTES0000 00100x022
UInt8BYTE0010 00000x2032
Int8BYTE0010 00010x2133
UInt16WORD0100 00000x4064
Int16WORD0100 00010x4165
UInt32DWORD0110 00000x6096
Int32DWORD0110 00010x6197
FloatDWORD0110 00100x6298
UInt64QWORD1000 00000x80128
Int64QWORD1000 00010x81129
DoubleQWORD1000 00100x82130
TextSTRING1010 00000xA0160
DateTimeSTRING1010 00010xA1161
DateSTRING1010 00100xA2162
TimeSTRING1010 00110xA3163
DecimalStrSTRING1010 01000xA4164
BlobBLOB1100 00000xC0192
ListCONTAINER1110 00000xE0224
MapCONTAINER1110 00010xE1225
ObjectCONTAINER1110 00100xE2226

ユーザー定義型

アプリケーションは、異なるDateTime型を使用し、値をDWORDまたはQWORDに格納できます。

ストレージ = QWORD (0x80)
サブタイプ = 5 (0x05) [未使用のものを選択]

タイプ DateTime = (0x80 | 0x05 => 0x85)

アプリケーションは、Binn構造の中にHTMLを送信し、プレーンテキストと区別するための型を定義できます。

ストレージ = STRING (0xA0)
サブタイプ = 9 (0x09) [未使用のものを選択]

タイプ HTML = (0xA0 | 0x09 => 0xA9)

サブタイプが15より大きい場合、新しいバイトを使用し、サブタイプサイズビットを設定する必要があります。

ストレージ = STRING (0xA000)
サブタイプサイズ = (0x0100)
サブタイプ = 21 (0x0015)

タイプ HTML = (0xA000 | 0x1000 | 0x0015 => 0xB015)

作成されたタイプパラメータは、ビッグエンディアンとして格納する必要があります。

[サイズ]

このパラメータは、文字列、BLOB、およびコンテナで使用されます。1バイトまたは4バイトを持つことができます。

サイズの最初のビットが0の場合、1バイトのみを使用します。したがって、データサイズが最大127(0x7F)バイトの場合、サイズパラメータは1バイトのみを使用します。

それ以外の場合、最上位ビットが1の4バイトのサイズパラメータが使用されます。これにより、上限が2ギガバイト(0x7FFFFFFF)になります。

データサイズサイズパラメータの使用
<= 127バイト1バイト
> 127バイト4バイト

小さなサイズが4バイトで格納されていても問題ありません。リーダーはどちらも受け入れる必要があります。

文字列の場合、サイズパラメータにはヌル終端子が含まれません。

コンテナの場合、サイズパラメータにはタイプパラメータが含まれます。これにより、構造全体のサイズが格納されます。

注: バージョン2.0より前では、BLOBのサイズは4バイトでのみ格納され、1バイトのサイズには対応していません。

[カウント]

このパラメータは、コンテナ内のアイテム数を通知するために、コンテナでのみ使用されます。サイズパラメータとまったく同じ形式で、1バイトまたは4バイトを持つことができます。

カウントカウントパラメータの使用
<= 127アイテム1バイト
> 127アイテム4バイト

コンテナ

リスト

リストは、値を次々に格納するコンテナです。

カウントパラメータは、コンテナ内の値の数を通知します。

[123, "test", 2.5, true]

マップ

マップは、整数をキーとして使用する連想配列です。

キーは、符号付き整数として読み取られるビッグエンディアンのDWORD(4バイト)を使用して格納されます。

現在の制限は、INT32_MINからINT32_MAXまでですが、必要に応じて増やすことができます。

カウントパラメータは、コンテナ内のキー/値のペアの数を通知します。

{1: 10, 5: "the value", 7: true}

オブジェクト

オブジェクトは、テキストをキーとして使用する連想配列です。

キーはヌル終端されず、上限は255バイトです。

キーは、キーの長さを示す1バイトを前に付けて格納されます。

カウントパラメータは、コンテナ内のキー/値のペアの数を通知します。

{"id": 1, "name": "John", "points": 30.5, "active": true}

制限

タイプ最小最大
整数INT64_MINUINT64_MAX
浮動小数点数IEEE 754
文字列02 GB
BLOB02 GB
コンテナ42 GB

連想配列

キータイプ最小最大
数値INT32_MININT32_MAX
テキスト0255バイト

サブタイプ: 各ストレージタイプに対して最大4096

例の構造

例えば、{"hello":"world"}のようなJSONデータは次のようにシリアル化されます。

Binn: (17バイト)

  \xE2           // [type] オブジェクト(コンテナ)
  \x11           // [size] コンテナの合計サイズ
  \x01           // [count] キー/値のペア
  \x05hello      // キー
  \xA0           // [type] = 文字列
  \x05           // [size]
  world\x00      // [data] (ヌル終端)

3つの整数のリスト:

Json: (14バイト)

[123, -456, 789]

Binn: (11バイト)

  \xE0           // [type] リスト(コンテナ)
  \x0B           // [size] コンテナの合計サイズ
  \x03           // [count] アイテム
  \x20           // [type] = uint8
  \x7B           // [data] (123)
  \x41           // [type] = int16
  \xFE\x38       // [data] (-456)
  \x40           // [type] = uint16
  \x03\x15       // [data] (789)

マップ内のリスト:

Json: (25バイト)

{1: "add", 2: [-12345, 6789]}

Binn: (26バイト)

 \xE1             // [type] マップ(コンテナ)
 \x1A             // [size] コンテナの合計サイズ
 \x02             // [count] キー/値のペア
 \x00\x00\x00\x01 // キー
 \xA0             // [type] = 文字列
 \x03             // [size]
 add\x00          // [data] (ヌル終端)
 \x00\x00\x00\x02 // キー
 \xE0             // [type] リスト(コンテナ)
 \x09             // [size] コンテナの合計サイズ
 \x02             // [count] アイテム
 \x41             // [type] = int16
 \xCF\xC7         // [data] (-12345)
 \x40             // [type] = uint16
 \x1A\x85         // [data] (6789)

オブジェクトのリスト:

Json: (47バイト)

[ {"id": 1, "name": "John"}, {"id": 2, "name": "Eric"} ]

Binn: (43バイト)

 \xE0           // [type] リスト(コンテナ)
 \x2B           // [size] コンテナの合計サイズ
 \x02           // [count] アイテム

 \xE2           // [type] オブジェクト(コンテナ)
 \x14           // [size] コンテナの合計サイズ
 \x02           // [count] キー/値のペア

 \x02id         // キー
 \x20           // [type] = uint8
 \x01           // [data] (1)

 \x04name       // キー
 \xA0           // [type] = 文字列
 \x04           // [size]
 John\x00       // [data] (ヌル終端)

 \xE2           // [type] オブジェクト(コンテナ)
 \x14           // [size] コンテナの合計サイズ
 \x02           // [count] キー/値のペア

 \x02id         // キー
 \x20           // [type] = uint8
 \x02           // [data] (2)

 \x04name       // キー
 \xA0           // [type] = 文字列
 \x04           // [size]
 Eric\x00       // [data] (ヌル終端)