go-binary
google protocol buffer 爲多種語言提供了 自動序列化的 功能 此項目靈感來源於此 並借鑑了 protocol buffer 的實現
通常 protocol buffer 提供了 更完善的高質量的 實現 是最佳選擇 然 protocol buufer 對於嵌入式來說過於 龐大 此項目正式爲此而作
如果你需要一個 相對 簡單 高效 緊湊 且自動化的 多語言 序列化方案 且能夠在 嵌入式c 中使用 此項目或許是不錯的選擇
支持 語言列表
生成序列化代碼
自動化的序列化方案 原理很簡單
-
定義好 要序列化的 對象 此項目使用 js 定義對象
-
使用 工具 爲對象創建 對應語言的 序列化代碼
定義對象
bin/src 檔案夾下 有 詳細的 對象定義 示例
// 定義 包
const pkg = "types"
// import 其它包
const pkgZooAnimal = "zoo/animal"
// 註冊 types 型別
core.RegisterType(pkg, "types")
.register(1, "int16", core.int16)
.register([
{
id: 2,
name: "int32",
symbol: core.int32,
},
{
id: 3,
name: "int64",
symbol: core.int64,
},
])
.register(
{
id: 4,
name: "uint16",
symbol: core.uint16,
},
{
id: 5,
name: "uint32",
symbol: core.uint32,
},
{
id: 6,
name: "uint64",
symbol: core.uint64,
},
{
id: 7,
name: "float32",
symbol: core.float32,
},
{
id: 8,
name: "float64",
symbol: core.float64,
},
{
id: 9,
name: "b",
symbol: core.byte,
},
{
id: 10,
name: "ok",
symbol: core.bool,
},
{
id: 11,
name: "str",
symbol: core.string,
},
{
id: 12,
name: "cat",
symbol: core.UseSymbol(pkgZooAnimal, "cat"),
},
{
id: 13,
name: "dog",
symbol: core.UseSymbol(pkgZooAnimal, "dog"),
},
{
id: 14,
name: "pos",
symbol: core.UseSymbol(pkgZooAnimal, "pos"),
},
{
id: 21,
name: "int16s",
symbol: core.int16s,
},
{
id: 22,
name: "int32s",
symbol: core.int32s,
},
{
id: 23,
name: "int64s",
symbol: core.int64s,
},
{
id: 24,
name: "uint16s",
symbol: core.uint16s,
},
{
id: 25,
name: "uint32s",
symbol: core.uint32s,
},
{
id: 26,
name: "uint64s",
symbol: core.uint64s,
},
{
id: 27,
name: "float32s",
symbol: core.float32s,
},
{
id: 28,
name: "float64s",
symbol: core.float64s,
},
{
id: 29,
name: "bs",
symbol: core.bytes,
},
{
id: 30,
name: "oks",
symbol: core.bools,
},
{
id: 31,
name: "strs",
symbol: core.strings,
},
{
id: 32,
name: "cats",
symbol: core.UseSymbol(pkgZooAnimal, "cat", true),
},
{
id: 33,
name: "dogs",
symbol: core.UseSymbol(pkgZooAnimal, "dog", true),
},
{
id: 34,
name: "poss",
symbol: core.UseSymbol(pkgZooAnimal, "pos", true),
}
)
生成 代碼
$ ./bin/go-binary c -h
build *.js and generate c code
Usage:
go-binary c [flags]
Flags:
-c, --clean clean output directory (default true)
-d, --dst string build output directory
-h, --help help for c
-s, --src string source *.js directory
生成代碼的 指令的 大同小異 比如 下面指令 解析 ./bin/src 中的 js 定義 並爲 c 語言 生成代碼 輸出到 ~/project/c/src 檔案夾
./bin/go-binary c -s ./bin/src -d ~/project/c/src
如果要創建 c++ 代碼 只需要 將 go-binary c
替換爲 go-binary cpp
指令
--clean 默認爲 true 會將 目標檔案夾清空
序列化對象
-
每個可序列化的 對象 稱爲 Type 在定義檔案中 使用 RegisterType/RegisterEnum 註冊
-
RegisterType/RegisterEnum 會返回 對應的 Type 實例 通過 調用 register 函數 註冊 Field
在 定義好 序列化對象後 go-binary 會自動爲 Type 創建 對應語言的 內存對象 和 編碼/解碼對象
對於 枚舉 只支持 int16 的值
Field 支持的 數據類型
core.XXX 預定義了 內置支持的 數據類型 如下
- int16
- int32
- int64
- uint16
- uint32
- uint64
- float32
- float64
- byte
- bool
- string
- int16s
- int32s
- int64s
- uint16s
- uint32s
- uint64s
- float32s
- float64s
- bytes
- bools
- strings
core.UseSymbol 可以引用 自定義的 型別/枚舉 其定義如下
declare namespace core {
function UseType(pkg: string, typeName: string, repeat?: boolean): Symbol;
}
編碼 方案
-
Type 由多個 Field 組成
Field0+Field1+Field2+...FieldN
-
Field 由 tag+val 組成
- tag 是一個 uint16,最高 3bit爲 writetype 是 寫入類型, 其它bit是 id
- val 是 field 對應的值
writetype 不同 則 val 存儲 方式 也不同
writetype |
val |
1 |
1 字節的 byte bool |
2 |
2字節的 int16 uint16 enum |
3 |
4字節的 float32 int32 uint32 |
4 |
8字節的 float64 int64 uint64 |
5 |
2字節長度 + bytes strings type repeat |
6 |
2字節 bit 長度 + bit repeat |
repeat
對於 已知 長度的 型別 repeat 的內容是 多個 型別數據 順序排列的 數組
對於 未知長度的 型別 repeat 內容是 多個 uint16長度+數據 形式的 數組 (每個 uint16 指定了 後續數據長度)
對於 bit repeat 則是一個 uint16的 bit 長度 + byte數組 的形式
命名規範
- 名稱只能是 英文字母 和 數字 和特定分隔符
- 包名 使用 / 作爲分隔符
- Type/Field 名稱 使用 _ 作爲 分隔符
- 每個單詞 必須是以英文字母開始
- 名稱不區分大小寫