@alexgyver/bson 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/bson.js +96 -85
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
1
|
# bson.js
|
|
2
|
-
|
|
2
|
+
Распаковщик бинарного JSON для библиотеки [BSON](https://github.com/GyverLibs/BSON).
|
|
3
|
+
|
|
4
|
+
> npm i @alexgyver/bson
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
const codes = [
|
|
8
|
+
'some',
|
|
9
|
+
'string',
|
|
10
|
+
'constants',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
let json;
|
|
14
|
+
const res = await fetch(...);
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
json = decodeBson(new Uint8Array(await res.arrayBuffer()), codes);
|
|
18
|
+
} catch (e) { }
|
|
19
|
+
```
|
package/bson.js
CHANGED
|
@@ -6,119 +6,130 @@
|
|
|
6
6
|
export default function decodeBson(b, codes = []) {
|
|
7
7
|
if (!b || !(b instanceof Uint8Array)) return null;
|
|
8
8
|
if (!b.length) return {};
|
|
9
|
-
let bins = [];
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
10
|
+
const BS_STRING = (0 << 5);
|
|
11
|
+
const BS_BOOLEAN = (1 << 5);
|
|
12
|
+
const BS_INTEGER = (2 << 5);
|
|
13
|
+
const BS_FLOAT = (3 << 5);
|
|
14
|
+
const BS_CODE = (4 << 5);
|
|
15
|
+
const BS_BINARY = (5 << 5);
|
|
17
16
|
const BS_CONTAINER = (6 << 5);
|
|
18
|
-
const BS_BINARY = (7 << 5);
|
|
19
|
-
const BS_BIN_PREFIX = "__BSON_BINARY";
|
|
20
17
|
|
|
21
18
|
const BS_CONT_OBJ = (1 << 4);
|
|
22
19
|
const BS_CONT_OPEN = (1 << 3);
|
|
20
|
+
const BS_NEGATIVE = (1 << 4);
|
|
21
|
+
const BS_BIN_PREFIX = "__BSON_BINARY";
|
|
23
22
|
|
|
24
|
-
function u32toFloat(u32) {
|
|
25
|
-
return new Float32Array(new Uint32Array([u32]).buffer)[0];
|
|
26
|
-
}
|
|
27
23
|
function unpack5(msb5, lsb) {
|
|
28
24
|
return ((msb5 << 8) | lsb) >>> 0;
|
|
29
25
|
}
|
|
30
|
-
function makeBins(obj) {
|
|
26
|
+
function makeBins(obj, bins) {
|
|
31
27
|
if (typeof obj !== 'object') return;
|
|
32
28
|
for (let k in obj) {
|
|
33
29
|
if (typeof obj[k] === "object" && obj[k] !== null) {
|
|
34
|
-
makeBins(obj[k]);
|
|
30
|
+
makeBins(obj[k], bins);
|
|
35
31
|
} else if (typeof obj[k] === "string" && obj[k].startsWith(BS_BIN_PREFIX)) {
|
|
36
32
|
obj[k] = bins[obj[k].split('#')[1]];
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
36
|
|
|
37
|
+
let bins = [];
|
|
38
|
+
let stack = [];
|
|
39
|
+
let keyf = true;
|
|
41
40
|
let s = '';
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.
|
|
72
|
-
.replaceAll(/([^\\])(")/ig,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
for (let i = 0; i < b.length; i++) {
|
|
44
|
+
const type = b[i] & 0b11100000;
|
|
45
|
+
const data = b[i] & 0b00011111;
|
|
46
|
+
|
|
47
|
+
switch (type) {
|
|
48
|
+
|
|
49
|
+
case BS_CONTAINER:
|
|
50
|
+
if (data & BS_CONT_OPEN) {
|
|
51
|
+
let t = (data & BS_CONT_OBJ) ? '{' : '[';
|
|
52
|
+
s += t;
|
|
53
|
+
stack.push(t);
|
|
54
|
+
} else {
|
|
55
|
+
if (s[s.length - 1] == ',') s = s.slice(0, -1);
|
|
56
|
+
let t = (data & BS_CONT_OBJ) ? '}' : ']';
|
|
57
|
+
s += t + ',';
|
|
58
|
+
stack.pop();
|
|
59
|
+
}
|
|
60
|
+
keyf = true;
|
|
61
|
+
continue;
|
|
62
|
+
|
|
63
|
+
case BS_CODE:
|
|
64
|
+
s += '"' + codes[unpack5(data, b[++i])] + '"';
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
case BS_STRING: {
|
|
68
|
+
let len = unpack5(data, b[++i]);
|
|
69
|
+
i++;
|
|
70
|
+
let txt = new TextDecoder().decode(b.slice(i, i + len));
|
|
71
|
+
txt = txt.replaceAll(/([^\\])\\([^\"\\nrt])/ig, "$1\\\\$2")
|
|
72
|
+
.replaceAll(/\t/ig, "\\t")
|
|
73
|
+
.replaceAll(/\n/ig, "\\n")
|
|
74
|
+
.replaceAll(/\r/ig, "\\r")
|
|
75
|
+
.replaceAll(/([^\\])(")/ig, '$1\\"');
|
|
76
|
+
s += '"' + txt + '"';
|
|
77
|
+
i += len - 1;
|
|
78
|
+
} break;
|
|
79
|
+
|
|
80
|
+
case BS_INTEGER: {
|
|
81
|
+
if (data & BS_NEGATIVE) s += '-';
|
|
82
|
+
let len = data & 0b1111;
|
|
83
|
+
let v = BigInt(0);
|
|
84
|
+
for (let j = 0; j < len; j++) {
|
|
85
|
+
v |= BigInt(b[++i]) << BigInt(j * 8);
|
|
86
|
+
}
|
|
87
|
+
s += v;
|
|
88
|
+
} break;
|
|
89
|
+
|
|
90
|
+
case BS_BOOLEAN:
|
|
91
|
+
s += (data & 0b1) ? 'true' : 'false';
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
case BS_FLOAT: {
|
|
95
|
+
let v = 0;
|
|
96
|
+
for (let j = 0; j < 4; j++) {
|
|
97
|
+
v |= b[++i] << (j * 8);
|
|
98
|
+
}
|
|
99
|
+
let f = new Float32Array(new Uint32Array([v]).buffer)[0];
|
|
100
|
+
s += (isNaN(f) || !isFinite(f)) ? 'null' : f.toFixed(data);
|
|
101
|
+
} break;
|
|
102
|
+
|
|
103
|
+
case BS_BINARY: {
|
|
104
|
+
let len = unpack5(data, b[++i]);
|
|
105
|
+
i++;
|
|
106
|
+
s += '"' + BS_BIN_PREFIX + '#' + bins.length + '"';
|
|
107
|
+
bins.push(b.slice(i, i + len));
|
|
108
|
+
i += len - 1;
|
|
109
|
+
} break;
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (stack[stack.length - 1] === '{') {
|
|
114
|
+
s += keyf ? ':' : ',';
|
|
115
|
+
keyf = !keyf;
|
|
116
|
+
} else {
|
|
102
117
|
s += ',';
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
case BS_BINARY: {
|
|
106
|
-
let len = unpack5(data, b[++i]);
|
|
107
|
-
i++;
|
|
108
|
-
s += '"' + BS_BIN_PREFIX + '#' + bins.length + '",';
|
|
109
|
-
bins.push(b.slice(i, i + len));
|
|
110
|
-
i += len - 1;
|
|
111
|
-
} break;
|
|
118
|
+
}
|
|
112
119
|
}
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.log(s);
|
|
122
|
+
throw new Error("BSON decode error");
|
|
113
123
|
}
|
|
124
|
+
|
|
114
125
|
if (s[s.length - 1] == ',') s = s.slice(0, -1);
|
|
115
126
|
|
|
116
127
|
try {
|
|
117
128
|
let obj = JSON.parse(s);
|
|
118
|
-
if (bins.length) makeBins(obj);
|
|
129
|
+
if (bins.length) makeBins(obj, bins);
|
|
119
130
|
return obj;
|
|
120
131
|
} catch (e) {
|
|
121
132
|
console.log(s);
|
|
122
|
-
throw new Error("JSON error")
|
|
133
|
+
throw new Error("JSON parse error");
|
|
123
134
|
}
|
|
124
135
|
}
|
package/package.json
CHANGED