Skip to content

Latest commit

 

History

History
335 lines (254 loc) · 8.9 KB

spec-zh.md

File metadata and controls

335 lines (254 loc) · 8.9 KB

Binn 规范

格式

每个值都有 4 个可能的参数存储:

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

但大多数是可选的。所有值中只有类型参数是必须的。以下是基本数据类型的参数列表:

布尔值,空值:
[type]

整数,浮点数(存储:字节,字,双字,四字):
[type][data]

字符串,二进制大对象(BLOB):
[type][size][data]

列表,对象,映射:
[type][size][count][data]

每个参数可以用多态大小存储:

参数 大小
[type] 1 或 2 字节
[size] 1 或 4 字节
[count] 1 或 4 字节
[data] n 字节

[类型]

每个值的存储都从数据类型开始。它可以使用 1 或 2 个字节。第一个字节分为以下几部分:

 +-------- 存储类型
 |  +----- 子类型大小
 |  |  +-- 子类型
000 0 0000

存储

最高的 3 位用于存储类型。它包含了数据将使用多少字节的信息。存储类型可以是以下任意一种:

  • 无额外字节
  • 1 字节
  • 字(2 字节,大端)
  • 双字(4 字节,大端)
  • 四字(8 字节,大端)
  • 字符串(UTF-8,空终止)
  • 二进制大对象(BLOB)
  • 容器

常量如下:

存储 十六进制 十进制
NOBYTES 000 0 0000 0x00 0
BYTE 001 0 0000 0x20 32
WORD 010 0 0000 0x40 64
DWORD 011 0 0000 0x60 96
QWORD 100 0 0000 0x80 128
STRING 101 0 0000 0xA0 160
BLOB 110 0 0000 0xC0 192
CONTAINER 111 0 0000 0xE0 224

子类型大小

下一位表示类型使用 1 个还是 2 个字节。

如果该位为 0,则类型只使用 1 个字节,子类型有 4 位(0 到 15)

 +-------- 存储类型
 |  +----- 子类型大小
 |  |  +-- 子类型
000 0 0000

当该位为 1 时,类型使用另一个字节,子类型有 12 位(最多 4096)

 +-------- 存储类型
 |  +----- 子类型大小
 |  |
000 1 0000  0000 0000
      |  子类型   |
      +-------------+

子类型

每个存储可以有多达 4096 个子类型。它们表示存储在该存储空间中的值的类型。

**示例:**一个双字可以包含有符号整数、无符号整数、单精度浮点数等等...甚至还可以包含用户定义的类型

以下是基本数据类型的值,子类型已突出显示:

类型 存储 十六进制 十进制
Null NOBYTES 0000 0000 0x00 0
True NOBYTES 0000 0001 0x01 1
False NOBYTES 0000 0010 0x02 2
UInt8 BYTE 0010 0000 0x20 32
Int8 BYTE 0010 0001 0x21 33
UInt16 WORD 0100 0000 0x40 64
Int16 WORD 0100 0001 0x41 65
UInt32 DWORD 0110 0000 0x60 96
Int32 DWORD 0110 0001 0x61 97
Float DWORD 0110 0010 0x62 98
UInt64 QWORD 1000 0000 0x80 128
Int64 QWORD 1000 0001 0x81 129
Double QWORD 1000 0010 0x82 130
Text STRING 1010 0000 0xA0 160
DateTime STRING 1010 0001 0xA1 161
Date STRING 1010 0010 0xA2 162
Time STRING 1010 0011 0xA3 163
DecimalStr STRING 1010 0100 0xA4 164
Blob BLOB 1100 0000 0xC0 192
List CONTAINER 1110 0000 0xE0 224
Map CONTAINER 1110 0001 0xE1 225
Object CONTAINER 1110 0010 0xE2 226

用户定义类型

应用程序可以使用不同的 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)

创建的类型参数必须以大端方式存储。

[大小]

此参数用于字符串、二进制大对象和容器。它可以有1个或4个字节。

如果大小的第一个比特为0,则只使用1个字节。因此,当数据大小最多为127(0x7F)字节时,大小参数将只使用1个字节。

否则,将使用一个4字节大小的参数,其中最高有效位为1。这使我们的上限为2 GigaBytes(0x7FFFFFFF)。

数据大小 大小参数使用
<= 127字节 1字节
> 127字节 4字节

如果使用4个字节存储较小的大小,没有问题。读取器必须接受两者。

对于字符串,大小参数不包括空终止符。

对于容器,大小参数包括类型参数。它存储整个结构的大小。

**注意:**在2.0之前的版本中,二进制大对象的大小仅使用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字节长。

键存储在键长度之前,使用单字节表示键长度。

计数参数通知容器内的键/值对数量。

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

限制

类型 最小值 最大值
整数 INT64_MIN UINT64_MAX
浮点数 IEEE 754
字符串 0 2 GB
二进制大对象 0 2 GB
容器 4 2 GB

关联数组

键类型 最小值 最大值
数字 INT32_MIN INT32_MAX
文本 0 255字节

子类型:每种存储类型最多可达4096个

示例结构

一个类似于{"hello":"world"}的json数据序列化为:

Binn: (17字节)

  \xE2           // [类型] 对象(容器)
  \x11           // [大小] 容器总大小
  \x01           // [计数] 键/值对
  \x05hello      // 键
  \xA0           // [类型] = 字符串
  \x05           // [大小]
  world\x00      // [数据](空终止)

3个整数的列表:

Json: (14字节)

[123, -456, 789]

Binn: (11字节)

  \xE0           // [类型] 列表(容器)
  \x0B           // [大小] 容器总大小
  \x03           // [计数] 项目
  \x20           // [类型] = uint8
  \x7B           // [数据] (123)
  \x41           // [类型] = int16
  \xFE\x38       // [数据] (-456)
  \x40           // [类型] = uint16
  \x03\x15       // [数据] (789)

列表中的映射:

Json: (25字节)

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

Binn: (26字节)

 \xE1             // [类型] 映射(容器)
 \x1A             // [大小] 容器总大小
 \x02             // [计数] 键/值对
 \x00\x00\x00\x01 // 键
 \xA0             // [类型] = 字符串
 \x03             // [大小]
 add\x00          // [数据](空终止)
 \x00\x00\x00\x02 // 键
 \xE0             // [类型] 列表(容器)
 \x09             // [大小] 容器总大小
 \x02             // [计数] 项目
 \x41             // [类型] = int16
 \xCF\xC7         // [数据] (-12345)
 \x40             // [类型] = uint16
 \x1A\x85         // [数据] (6789)

对象列表:

Json: (47字节)

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

Binn: (43字节)

 \xE0           // [类型] 列表(容器)
 \x2B           // [大小] 容器总大小
 \x02           // [计数] 项目

 \xE2           // [类型] 对象(容器)
 \x14           // [大小] 容器总大小
 \x02           // [计数] 键/值对

 \x02id         // 键
 \x20           // [类型] = uint8
 \x01           // [数据] (1)

 \x04name       // 键
 \xA0           // [类型] = 字符串
 \x04           // [大小]
 John\x00       // [数据](空终止)

 \xE2           // [类型] 对象(容器)
 \x14           // [大小] 容器总大小
 \x02           // [计数] 键/值对

 \x02id         // 键
 \x20           // [类型] = uint8
 \x02           // [数据] (2)

 \x04name       // 键
 \xA0           // [类型] = 字符串
 \x04           // [大小]
 Eric\x00       // [数据](空终止)