序列化
| Number | Category | Status | Author | Organization | Created |
|---|---|---|---|---|---|
| 0008 | Standards Track | Proposal | Boyu Yang | Nervos Foundation | 2018-12-17 |
序列化
CKB 主要使用两种序列化格式: Molecule 和 JSON。
Molecule 是一种规范化的零拷贝序列化格式,其当前仍处于实验阶段,我们对其做了一些小修改。
JSON 主要通过 JSON-RPC 用于节点 RPC 服务中。
Molecule
概览
固定大小/动态大小
| 类型 | byte | array | struct | vector | table | option | union |
|---|---|---|---|---|---|---|---|
| 大小 | 固定 | 固定 | 固定 | 动态 | 动态 | 动态 | 动态 |
Memory Layout 内存布局
| Type | Header | Body |
|---|---|---|
| array | item-0 | item-1 | ... | item-N | |
| struct | field-0 | field-1 | ... | field-N | |
| fixvec | items-count | item-0 | item-1 | ... | item-N |
| dynvec | full-size | offset-0 | offset-1 | ... | offset-N | item-0 | item-1 | ... | item-N |
| table | full-size | offset-0 | offset-1 | ... | offset-N | field-0 | field-1 | ... | field-N |
| option | item or none (zero bytes) | |
| union | item-type-id | item |
- 头中的所有子项都会小端模式的32位无符号整数。
基本类型
byte 字节
The byte is a byte.
例子
00 is a byte.
复合类型
array
array 是一种固定大小的类型:固定大小的内部类型以及固定的长度。
array 的大小为内部类型的大小乘以 array 的长度。
序列化 array 只需要序列化其内部所有子项。
序列化数组没有开销,因为 array 连续存储所有子项,在两个相邻的子项之间没有额外的空间。
例子
如果我们定义数组 Byte3 [byte; 3];,我们要存储三个字节:第一个是01,第二个是02,最后一个是03,然后序列化得到的字节为: 01 02 03。
如果我们定义数组 Uint32 [byte; 4]; ,我们要用小端模式存储一个32位无符号整数 0x01020304 ,那么序列化得到的字节为 04 03 02 01:
如果我们定义数组 TwoUint32 [Uint32; 2];,我们要用小端模式存储两个32位无符号整数:第一个是 0x01020304,第二个是 0xabcde,那么序列化得到的字节为 04 03 02 01 de bc 0a 00。
struct 结构体
struct 是一种固定大小的类型:结构体中的所有字段都是固定大小,并且字段数量也固定。结构体的大小为所有字段大小的总和。
序列化一个结构体只需要序列化其中的所有字段。结构体中的字段按照各自声明的顺序存储。
序列化结构体没有开销,结构体连续存储所有字段,在两个相邻的子项之间没有额外的空间。
例子
如果我们定义结构体 OnlyAByte { f1: byte }, 我们想要存储一个字节 ab,那么序列化得到的字节为 ab。
如果我们定义结构体 ByteAndUint32 { f1: byte, f2: Uint32 }, 我们想要存储一个字节 ab 以及小端模式的32位无符号整数 0x010203 ,那么序列化得到的字节为 ab 03 02 01 00。
vectors 向量
向量有分:固定向量 fixvec 和动态向量 dynvec。
向量是固定还是动态取决于其内部子项的类型:如果内部子项为固定大小,那么为固定向量;反之则为动态向量。
fixvec 和dynvec 都属于动态大小类型。
fixvec - fixed vector 固定向量
序列化固定向量分两步:
- 以小端模式的32位无符号整数序列化其长度
- 序列化其所有子项
例子
如果我们定义向量 Bytes <byte>;:
- 空字节序列化得到的字节为
00 00 00 00(任何空固定向量的长度都为 0 ) 0x12序列化得到的字节为01 00 00 00, 12。0x1234567890abcdef序列化得到的字节为08 00 00 00, 12 34 56 78 90 ab cd ef。
如果我们定义向量 Uint32Vec <Uint32>;:
空
Uint32Vec序列化得到的字节为00 00 00 000x123序列化得到的字节为01 00 00 00, 23 01 00 00.[0x123, 0x456, 0x7890, 0xa, 0xbc, 0xdef]序列化得到的字节为:# there are 6 items06 00 00 00# six items23 01 00 00, 56 04 00 00, 90 78 00 00, 0a 00 00 00, bc 00 00 00, ef 0d 00 00
dynvec - dynamic vector 动态向量
序列化动态向量分三步:
- 以小端模式的32位无符号整数序列化完整大小
- 以小端模式的32位无符号整数序列化所有子项的偏移
- 序列化向量的所有子项
例子
如果我们定义向量 BytesVec <Bytes>;:
空向量
BytesVec序列化得到的字节为04 00 00 00(空动态向量的完整大小为 4 字节)[0x1234]序列化得到的字节为:# the full size is 14 bytes0e 00 00 00# one offset08 00 00 00# one item02 00 00 00 12 34[0x1234, 0x, 0x567, 0x89, 0xabcdef]序列化得到的字节为:# the full size is 52 (0x34) bytes34 00 00 00# five offsets (20 bytes in total)18 00 00 00, 1e 00 00 00, 22 00 00 00, 28 00 00 00, 2d 00 00 00# five items (28 bytes in total)02 00 00 00, 12 3400 00 00 00,02 00 00 00, 05 6701 00 00 00, 8903 00 00 00, ab cd ef
table 表
table 是一种动态大小的类型,可将它视为动态向量,只不过长度固定。
序列化步骤与动态向量一样:
- 以小端模式的32位无符号整数序列化完整大小
- 以小端模式的32位无符号整数序列化所有子项的偏移
- 按照字段各自声明的顺序,序列化其所有字段
例子
如果我们定义表格 MixedType { f1: Bytes, f2: byte, f3: Uint32, f4: Byte3, f5: Bytes }
序列化
MixedType { f1: 0x, f2: 0xab, f3: 0x123, f4: 0x456789, f5: 0xabcdef }得到的字节为:# the full size is 43 (0x2b) bytes2b 00 00 00# five offsets (20 bytes in total)18 00 00 00, 1c 00 00 00, 1d 00 00 00, 21 00 00 00, 24 00 00 00# five items (19 bytes in total)00 00 00 00ab23 01 00 0045 67 8903 00 00 00, ab cd ef
option 选项
option 是一种动态大小的类型
序列化 option 取决于其是否为空:
- 如果为空,则为 0 字节(大小为 0)
- 如果不为空,只需要序列化其内部子项(大小等于其内部子项的大小)
例子
如果我们定义选项 BytesVecOpt (BytesVec);
序列化
None得到的字节为空序列化
Some([])得到的字节为04 00 00 00.序列化
Some([0x])得到的字节为# the full size of BytesVec is 12 bytes0c 00 00 00# the offset of Bytes08 00 00 00# the length of Bytes00 00 00 00
union共同体
union 是一种动态大小的类型。
序列化 union 分两步:
- 以小端模式的32位无符号整数序列化 item-type-id,item-type-id 为内部子项的索引,从 0 开始。
- 序列化内部子项
例子
如果我们定义共同体 HybridBytes { Byte3, Bytes, BytesVec, BytesVecOpt }
序列化
Byte3 (0x123456)得到的字节为00 00 00 00, 12 34 56序列化
Bytes (0x)得到的字节为01 00 00 00, 00 00 00 00序列化
Bytes (0x123)得到的字节为01 00 00 00, 02 00 00 00, 01 23序列化
BytesVec ([])得到的字节为02 00 00 00, 04 00 00 00序列化
BytesVec ([0x])得到的字节为02 00 00 00, 0c 00 00 00, 08 00 00 00, 00 00 00 00序列化
BytesVec ([0x123])得到的字节为02 00 00 00, 0e 00 00 00, 08 00 00 00, 02 00 00 00, 01 23序列化
BytesVec ([0x123, 0x456])得到的字节为# Item Type Id02 00 00 00# the full size of BytesVec is 24 bytes18 00 00 00# two offsets of BytesVec (8 bytes in total)0c 00 00 00, 12 00 00 00,# two Bytes (12 bytes in total)02 00 00 00, 01 2302 00 00 00, 04 56序列化
BytesVecOpt (None)得到的字节为03 00 00 00序列化
BytesVecOpt (Some(([])))得到的字节为03 00 00 00, 04 00 00 00序列化
BytesVecOpt (Some(([0x])))得到的字节为03 00 00 00, 0c 00 00 00, 08 00 00 00, 00 00 00 00序列化
BytesVecOpt (Some(([0x123])))得到的字节为03 00 00 00, 0e 00 00 00, 08 00 00 00, 02 00 00 00, 01 23序列化
BytesVecOpt (Some(([0x123, 0x456])))得到的字节为# Item Type Id03 00 00 00# the full size of BytesVec is 24 bytes18 00 00 00# two offsets of BytesVec (8 bytes in total)0c 00 00 00, 12 00 00 00,# two Bytes (12 bytes in total)02 00 00 00, 01 2302 00 00 00, 04 56
CKB Docs