@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.
Files changed (3) hide show
  1. package/README.md +18 -1
  2. package/bson.js +96 -85
  3. 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 BS_KEY_CODE = (0 << 5);
12
- const BS_KEY_STR = (1 << 5);
13
- const BS_VAL_CODE = (2 << 5);
14
- const BS_VAL_STR = (3 << 5);
15
- const BS_VAL_INT = (4 << 5);
16
- const BS_VAL_FLOAT = (5 << 5);
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
- for (let i = 0; i < b.length; i++) {
43
- const type = b[i] & 0b11100000;
44
- const data = b[i] & 0b00011111;
45
-
46
- switch (type) {
47
- case BS_CONTAINER:
48
- if (data & BS_CONT_OPEN) {
49
- s += (data & BS_CONT_OBJ) ? '{' : '[';
50
- } else {
51
- if (s[s.length - 1] == ',') s = s.slice(0, -1);
52
- s += (data & BS_CONT_OBJ) ? '}' : ']';
53
- s += ',';
54
- }
55
- break;
56
-
57
- case BS_KEY_CODE:
58
- case BS_VAL_CODE:
59
- s += '"' + codes[unpack5(data, b[++i])] + '"';
60
- s += (type == BS_KEY_CODE) ? ':' : ',';
61
- break;
62
-
63
- case BS_KEY_STR:
64
- case BS_VAL_STR: {
65
- let len = unpack5(data, b[++i]);
66
- i++;
67
- let txt = new TextDecoder().decode(b.slice(i, i + len));
68
- txt = txt.replaceAll(/([^\\])\\([^\"\\nrt])/ig, "$1\\\\$2")
69
- .replaceAll(/\t/ig, "\\t")
70
- .replaceAll(/\n/ig, "\\n")
71
- .replaceAll(/\r/ig, "\\r")
72
- .replaceAll(/([^\\])(")/ig, '$1\\"');
73
- s += '"' + txt + '"';
74
- s += (type == BS_KEY_STR) ? ':' : ',';
75
- i += len - 1;
76
- } break;
77
-
78
- case BS_VAL_INT: {
79
- if (data & 0b10000) s += '-';
80
- let len = data & 0b01111;
81
- let v = BigInt(0);
82
- for (let j = 0; j < len; j++) {
83
- v |= BigInt(b[++i]) << BigInt(j * 8);
84
- }
85
- s += v;
86
- s += ',';
87
- } break;
88
-
89
- case BS_VAL_FLOAT: {
90
- let v = 0;
91
- for (let j = 0; j < 4; j++) {
92
- v |= b[++i] << (j * 8);
93
- }
94
- let f = u32toFloat(v);
95
- if (isNaN(f)) {
96
- s += '"NaN"';
97
- } else if (!isFinite(f)) {
98
- s += '"Infinity"';
99
- } else {
100
- s += f.toFixed(data);
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
- } break;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alexgyver/bson",
3
- "version": "1.0.0",
4
- "description": "Decode BSON from GSON Arduino library",
3
+ "version": "1.0.2",
4
+ "description": "Decode BSON from BSON Arduino library",
5
5
  "main": "./bson.js",
6
6
  "module": "./bson.js",
7
7
  "types": "./bson.js",