|
1 | | -const codes = [ |
2 | | - 'id', |
3 | | - 'type', |
4 | | - 'content', |
5 | | - 'group', |
6 | | - 'menu', |
7 | | - 'buttons', |
8 | | - |
9 | | - 'build', |
10 | | - 'reload', |
11 | | - 'update', |
12 | | - 'ping', |
13 | | - 'granted', |
14 | | - 'fs', |
15 | | - 'error', |
16 | | - 'gzip', |
17 | | - 'used', |
18 | | - 'total', |
19 | | - |
20 | | - 'label', |
21 | | - 'title', |
22 | | - 'text', |
23 | | - 'value', |
24 | | - 'color', |
25 | | - 'min', |
26 | | - 'max', |
27 | | - 'step', |
28 | | - 'unit', |
29 | | - |
30 | | - 'input', |
31 | | - 'pass', |
32 | | - 'select', |
33 | | - 'slider', |
34 | | - 'toggle', |
35 | | - 'time', |
36 | | - 'date', |
37 | | - 'datetime', |
38 | | - 'button', |
39 | | - 'paragraph', |
40 | | - 'confirm', |
41 | | - 'led', |
42 | | -]; |
43 | | - |
44 | | -export default function decodeBson(b) { |
| 1 | +export default function decodeBson(b, codes = []) { |
45 | 2 | if (!b || !(b instanceof Uint8Array)) return null; |
46 | 3 | if (!b.length) return {}; |
| 4 | + let bins = []; |
47 | 5 |
|
48 | 6 | const BS_KEY_CODE = (0 << 5); |
49 | 7 | const BS_KEY_STR = (1 << 5); |
50 | 8 | const BS_VAL_CODE = (2 << 5); |
51 | 9 | const BS_VAL_STR = (3 << 5); |
52 | 10 | const BS_VAL_INT = (4 << 5); |
53 | 11 | const BS_VAL_FLOAT = (5 << 5); |
54 | | - const BS_CONT_OPEN = (6 << 5); |
55 | | - const BS_CONT_CLOSE = (7 << 5); |
56 | | - const BS_CONT_OBJ = (1); |
57 | | - const BS_CONT_ARR = (0); |
| 12 | + const BS_CONTAINER = (6 << 5); |
| 13 | + const BS_BINARY = (7 << 5); |
| 14 | + const BS_BIN_PREFIX = "__BSON_BINARY"; |
| 15 | + |
| 16 | + const BS_CONT_OBJ = (1 << 4); |
| 17 | + const BS_CONT_OPEN = (1 << 3); |
58 | 18 |
|
59 | 19 | function ieee32ToFloat(intval) { |
60 | 20 | var fval = 0.0; |
@@ -83,21 +43,31 @@ export default function decodeBson(b) { |
83 | 43 | function unpack5(msb5, lsb) { |
84 | 44 | return ((msb5 << 8) | lsb) >>> 0; |
85 | 45 | } |
| 46 | + function makeBins(obj) { |
| 47 | + if (typeof obj !== 'object') return; |
| 48 | + for (let k in obj) { |
| 49 | + if (typeof obj[k] === "object" && obj[k] !== null) { |
| 50 | + makeBins(obj[k]); |
| 51 | + } else if (typeof obj[k] === "string" && obj[k].startsWith(BS_BIN_PREFIX)) { |
| 52 | + obj[k] = bins[obj[k].split('#')[1]]; |
| 53 | + } |
| 54 | + } |
| 55 | + } |
86 | 56 |
|
87 | 57 | let s = ''; |
88 | 58 | for (let i = 0; i < b.length; i++) { |
89 | 59 | const type = b[i] & 0b11100000; |
90 | 60 | const data = b[i] & 0b00011111; |
91 | 61 |
|
92 | 62 | switch (type) { |
93 | | - case BS_CONT_CLOSE: |
94 | | - if (s[s.length - 1] == ',') s = s.slice(0, -1); |
95 | | - s += (data == BS_CONT_OBJ) ? '}' : ']'; |
96 | | - s += ','; |
97 | | - break; |
98 | | - |
99 | | - case BS_CONT_OPEN: |
100 | | - s += (data == BS_CONT_OBJ) ? '{' : '['; |
| 63 | + case BS_CONTAINER: |
| 64 | + if (data & BS_CONT_OPEN) { |
| 65 | + s += (data & BS_CONT_OBJ) ? '{' : '['; |
| 66 | + } else { |
| 67 | + if (s[s.length - 1] == ',') s = s.slice(0, -1); |
| 68 | + s += (data & BS_CONT_OBJ) ? '}' : ']'; |
| 69 | + s += ','; |
| 70 | + } |
101 | 71 | break; |
102 | 72 |
|
103 | 73 | case BS_KEY_CODE: |
@@ -140,12 +110,22 @@ export default function decodeBson(b) { |
140 | 110 | s += ieee32ToFloat(v).toFixed(data); |
141 | 111 | s += ','; |
142 | 112 | } break; |
| 113 | + |
| 114 | + case BS_BINARY: { |
| 115 | + let len = unpack5(data, b[++i]); |
| 116 | + i++; |
| 117 | + s += '"' + BS_BIN_PREFIX + '#' + bins.length + '",'; |
| 118 | + bins.push(b.slice(i, i + len)); |
| 119 | + i += len - 1; |
| 120 | + } break; |
143 | 121 | } |
144 | 122 | } |
145 | 123 | if (s[s.length - 1] == ',') s = s.slice(0, -1); |
146 | 124 |
|
147 | 125 | try { |
148 | | - return JSON.parse(s); |
| 126 | + let obj = JSON.parse(s); |
| 127 | + makeBins(obj); |
| 128 | + return obj; |
149 | 129 | } catch (e) { |
150 | 130 | throw new Error("JSON error") |
151 | 131 | } |
|
0 commit comments