@alexgyver/bson 1.0.1 → 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 (2) hide show
  1. package/bson.js +90 -86
  2. package/package.json +1 -1
package/bson.js CHANGED
@@ -6,126 +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
-
21
- const BS_NEGATIVE = (1 << 4);
22
- const BS_BOOLEAN = (1 << 3);
23
17
 
24
18
  const BS_CONT_OBJ = (1 << 4);
25
19
  const BS_CONT_OPEN = (1 << 3);
20
+ const BS_NEGATIVE = (1 << 4);
21
+ const BS_BIN_PREFIX = "__BSON_BINARY";
26
22
 
27
- function u32toFloat(u32) {
28
- return new Float32Array(new Uint32Array([u32]).buffer)[0];
29
- }
30
23
  function unpack5(msb5, lsb) {
31
24
  return ((msb5 << 8) | lsb) >>> 0;
32
25
  }
33
- function makeBins(obj) {
26
+ function makeBins(obj, bins) {
34
27
  if (typeof obj !== 'object') return;
35
28
  for (let k in obj) {
36
29
  if (typeof obj[k] === "object" && obj[k] !== null) {
37
- makeBins(obj[k]);
30
+ makeBins(obj[k], bins);
38
31
  } else if (typeof obj[k] === "string" && obj[k].startsWith(BS_BIN_PREFIX)) {
39
32
  obj[k] = bins[obj[k].split('#')[1]];
40
33
  }
41
34
  }
42
35
  }
43
36
 
37
+ let bins = [];
38
+ let stack = [];
39
+ let keyf = true;
44
40
  let s = '';
45
- for (let i = 0; i < b.length; i++) {
46
- const type = b[i] & 0b11100000;
47
- const data = b[i] & 0b00011111;
48
-
49
- switch (type) {
50
- case BS_CONTAINER:
51
- if (data & BS_CONT_OPEN) {
52
- s += (data & BS_CONT_OBJ) ? '{' : '[';
53
- } else {
54
- if (s[s.length - 1] == ',') s = s.slice(0, -1);
55
- s += (data & BS_CONT_OBJ) ? '}' : ']';
56
- s += ',';
57
- }
58
- break;
59
-
60
- case BS_KEY_CODE:
61
- case BS_VAL_CODE:
62
- s += '"' + codes[unpack5(data, b[++i])] + '"';
63
- s += (type == BS_KEY_CODE) ? ':' : ',';
64
- break;
65
-
66
- case BS_KEY_STR:
67
- case BS_VAL_STR: {
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
- s += (type == BS_KEY_STR) ? ':' : ',';
78
- i += len - 1;
79
- } break;
80
-
81
- case BS_VAL_INT: {
82
- if (data & BS_BOOLEAN) {
83
- s += (data & 0b1) ? 'true' : 'false';
84
- } else {
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: {
85
81
  if (data & BS_NEGATIVE) s += '-';
86
- let len = data & 0b111;
82
+ let len = data & 0b1111;
87
83
  let v = BigInt(0);
88
84
  for (let j = 0; j < len; j++) {
89
85
  v |= BigInt(b[++i]) << BigInt(j * 8);
90
86
  }
91
87
  s += v;
92
- }
93
- s += ',';
94
- } break;
95
-
96
- case BS_VAL_FLOAT: {
97
- let v = 0;
98
- for (let j = 0; j < 4; j++) {
99
- v |= b[++i] << (j * 8);
100
- }
101
- let f = u32toFloat(v);
102
- if (isNaN(f)) {
103
- s += '"NaN"';
104
- } else if (!isFinite(f)) {
105
- s += '"Infinity"';
106
- } else {
107
- s += f.toFixed(data);
108
- }
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 {
109
117
  s += ',';
110
- } break;
111
-
112
- case BS_BINARY: {
113
- let len = unpack5(data, b[++i]);
114
- i++;
115
- s += '"' + BS_BIN_PREFIX + '#' + bins.length + '",';
116
- bins.push(b.slice(i, i + len));
117
- i += len - 1;
118
- } break;
118
+ }
119
119
  }
120
+ } catch (e) {
121
+ console.log(s);
122
+ throw new Error("BSON decode error");
120
123
  }
124
+
121
125
  if (s[s.length - 1] == ',') s = s.slice(0, -1);
122
126
 
123
127
  try {
124
128
  let obj = JSON.parse(s);
125
- if (bins.length) makeBins(obj);
129
+ if (bins.length) makeBins(obj, bins);
126
130
  return obj;
127
131
  } catch (e) {
128
132
  console.log(s);
129
- throw new Error("JSON error")
133
+ throw new Error("JSON parse error");
130
134
  }
131
135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexgyver/bson",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Decode BSON from BSON Arduino library",
5
5
  "main": "./bson.js",
6
6
  "module": "./bson.js",