RFC 8949 CBOR: Concise Binary Object Representation,這是一種輕量的二進位資料格式,可簡單理解為一種二進位的 JSON,設計目的是最小化處理程式碼,最小化訊息位元組大小。另外在 RFC 9052, 9053 CBOR Object Signing and Encryption (COSE) 制定了要如何對 CBOR 資料進行資料簽章與加密的方法。
online test
可到這兩個網頁進行線上測試
測試時可以發現,不管是整數,字串,都有對應的編碼。甚至是 JSON 字串,也有對應的 Map (key-value pair) 的編碼方式
CBOR
header 有兩個資訊,前 3 bits 是 Major Type,後 5 個 bits 是 Additional Information
字節(byte)數 | 1 byte (CBOR Data Item Header) | 動態長度 | 動態長度 | |
---|---|---|---|---|
結構 | Major Type | Additional Information | Payload Length(可選) | Data Payload(可選) |
bit | 3 Bits | 5 Bits | 動態長度 | 動態長度 |
CBOR 有八種 Major Type
首位元組的 lower 5 bits 在不同的主類型表示長度(除主類型 0 和主類型 1),如果長度指示不足,則依次使用後續位元組。
Major Type | Name | content |
---|---|---|
0 | unsigned integer | - |
1 | negative integer | - |
2 | byte string | N bytes |
3 | text string | N bytes (UTF-8 text) |
4 | array of data items | N data items |
5 | map of pairs of data items | 2N data items (key/value pairs) |
6 | tag of number N | 1 data item |
7 | simple/float | - |
比較特別的是 Major Type 6 裡面定義了 date time
0xC0 定義了 text-based date/time,0xC1 定義了 epoch-based date/time
還有 Major Type 7 裡面的
- False 編碼後 0xF4
- True 編碼後 0xF5
- Null 編碼後 0b1110_0000 + 0b0001_01110 (22) = 0xF6
implementation
CBOR — Concise Binary Object Representation | Implementations
這邊列出了不同程式語言的 CBOR 實作 library
這邊用 js 測試
<html>
<script src="https://cdn.jsdelivr.net/npm/cbor-js@0.1.0/cbor.min.js"></script>
<script>
function hex(buffer) {
var s = '', h = '0123456789ABCDEF';
(new Uint8Array(buffer)).forEach((v) => { s += h[v >> 4] + h[v & 15]; });
return s;
}
function test0() {
console.log("");
console.log("test0 unsigned integer");
var initial = 1000;
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =" + initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =" + decoded);
}
function test1() {
console.log("");
console.log("test1 negative integer");
var initial = -1000;
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =" + initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =" + decoded);
}
function test2() {
console.log("");
console.log("test2 byte string");
var initial = new Uint8Array([0, 1, 2, 3]);
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test3() {
console.log("");
console.log("test3 text string");
var initial = "text string";
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test4() {
console.log("");
console.log("test4 array");
var initial = [1, "2"];
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test5() {
console.log("");
console.log("test5 map");
var initial = { Hello: "World" };
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test6() {
console.log("");
console.log("test6 float");
var initial = 3.1415;
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test7() {
console.log("");
console.log("test7 true");
var initial = true;
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
function test8() {
console.log("");
console.log("test8 null");
var initial = null;
var encoded = CBOR.encode(initial);
var decoded = CBOR.decode(encoded);
console.log("initial =", initial);
console.log("encoded hex=", hex(encoded));
console.log("decoded =", decoded);
}
test0();
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
</script>
</html>
結果
test0 unsigned integer
initial =1000
encoded hex= 1903E8
decoded =1000
test1 negative integer
initial =-1000
encoded hex= 3903E7
decoded =-1000
test2 byte string
initial = Uint8Array(4) [0, 1, 2, 3, buffer: ArrayBuffer(4), byteLength: 4, byteOffset: 0, length: 4, Symbol(Symbol.toStringTag): 'Uint8Array']
encoded hex= 4400010203
decoded = Uint8Array(4) [0, 1, 2, 3, buffer: ArrayBuffer(5), byteLength: 4, byteOffset: 1, length: 4, Symbol(Symbol.toStringTag): 'Uint8Array']
test3 text string
initial = text string
encoded hex= 6B7465787420737472696E67
decoded = text string
test4 array
initial = (2) [1, '2']
encoded hex= 82016132
decoded = (2) [1, '2']
test5 map
initial = {Hello: 'World'}
encoded hex= A16548656C6C6F65576F726C64
decoded = {Hello: 'World'}
test6 float
initial = 3.1415
encoded hex= FB400921CAC083126F
decoded = 3.1415
test7 true
initial = true
encoded hex= F5
decoded = true
test8 null
initial = null
encoded hex= F6
decoded = null
沒有留言:
張貼留言