bson 4.0.4 → 4.2.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 (90) hide show
  1. package/HISTORY.md +56 -1
  2. package/README.md +7 -9
  3. package/bower.json +1 -1
  4. package/bson.d.ts +983 -0
  5. package/dist/bson.browser.esm.js +7261 -5004
  6. package/dist/bson.browser.esm.js.map +1 -0
  7. package/dist/bson.browser.umd.js +7319 -5099
  8. package/dist/bson.browser.umd.js.map +1 -0
  9. package/dist/bson.bundle.js +8168 -9216
  10. package/dist/bson.bundle.js.map +1 -0
  11. package/dist/bson.esm.js +5643 -5409
  12. package/dist/bson.esm.js.map +1 -0
  13. package/etc/prepare.js +19 -0
  14. package/lib/binary.js +194 -377
  15. package/lib/binary.js.map +1 -0
  16. package/lib/bson.js +200 -243
  17. package/lib/bson.js.map +1 -0
  18. package/lib/code.js +36 -39
  19. package/lib/code.js.map +1 -0
  20. package/lib/constants.js +78 -203
  21. package/lib/constants.js.map +1 -0
  22. package/lib/db_ref.js +79 -79
  23. package/lib/db_ref.js.map +1 -0
  24. package/lib/decimal128.js +647 -760
  25. package/lib/decimal128.js.map +1 -0
  26. package/lib/double.js +61 -58
  27. package/lib/double.js.map +1 -0
  28. package/lib/ensure_buffer.js +22 -18
  29. package/lib/ensure_buffer.js.map +1 -0
  30. package/lib/extended_json.js +305 -322
  31. package/lib/extended_json.js.map +1 -0
  32. package/lib/float_parser.js +98 -104
  33. package/lib/float_parser.js.map +1 -0
  34. package/lib/int_32.js +45 -47
  35. package/lib/int_32.js.map +1 -0
  36. package/lib/long.js +876 -16
  37. package/lib/long.js.map +1 -0
  38. package/lib/map.js +123 -124
  39. package/lib/map.js.map +1 -0
  40. package/lib/max_key.js +21 -23
  41. package/lib/max_key.js.map +1 -0
  42. package/lib/min_key.js +21 -23
  43. package/lib/min_key.js.map +1 -0
  44. package/lib/objectid.js +264 -382
  45. package/lib/objectid.js.map +1 -0
  46. package/lib/parser/calculate_size.js +185 -224
  47. package/lib/parser/calculate_size.js.map +1 -0
  48. package/lib/parser/deserializer.js +543 -620
  49. package/lib/parser/deserializer.js.map +1 -0
  50. package/lib/parser/serializer.js +774 -918
  51. package/lib/parser/serializer.js.map +1 -0
  52. package/lib/parser/utils.js +81 -30
  53. package/lib/parser/utils.js.map +1 -0
  54. package/lib/regexp.js +54 -70
  55. package/lib/regexp.js.map +1 -0
  56. package/lib/symbol.js +40 -56
  57. package/lib/symbol.js.map +1 -0
  58. package/lib/timestamp.js +70 -95
  59. package/lib/timestamp.js.map +1 -0
  60. package/lib/uuid.js +48 -0
  61. package/lib/uuid.js.map +1 -0
  62. package/lib/validate_utf8.js +32 -33
  63. package/lib/validate_utf8.js.map +1 -0
  64. package/package.json +53 -31
  65. package/src/binary.ts +270 -0
  66. package/src/bson.ts +326 -0
  67. package/src/code.ts +57 -0
  68. package/src/constants.ts +104 -0
  69. package/src/db_ref.ts +115 -0
  70. package/src/decimal128.ts +801 -0
  71. package/src/double.ts +85 -0
  72. package/src/ensure_buffer.ts +26 -0
  73. package/src/extended_json.ts +395 -0
  74. package/src/float_parser.ts +152 -0
  75. package/src/int_32.ts +64 -0
  76. package/src/long.ts +1000 -0
  77. package/src/map.ts +139 -0
  78. package/src/max_key.ts +33 -0
  79. package/src/min_key.ts +33 -0
  80. package/src/objectid.ts +377 -0
  81. package/src/parser/calculate_size.ts +230 -0
  82. package/src/parser/deserializer.ts +655 -0
  83. package/src/parser/serializer.ts +1069 -0
  84. package/src/parser/utils.ts +93 -0
  85. package/src/regexp.ts +92 -0
  86. package/src/symbol.ts +57 -0
  87. package/src/timestamp.ts +103 -0
  88. package/src/uuid.ts +57 -0
  89. package/src/validate_utf8.ts +47 -0
  90. package/lib/fnv1a.js +0 -48
@@ -0,0 +1,801 @@
1
+ import { Buffer } from 'buffer';
2
+ import { Long } from './long';
3
+
4
+ const PARSE_STRING_REGEXP = /^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/;
5
+ const PARSE_INF_REGEXP = /^(\+|-)?(Infinity|inf)$/i;
6
+ const PARSE_NAN_REGEXP = /^(\+|-)?NaN$/i;
7
+
8
+ const EXPONENT_MAX = 6111;
9
+ const EXPONENT_MIN = -6176;
10
+ const EXPONENT_BIAS = 6176;
11
+ const MAX_DIGITS = 34;
12
+
13
+ // Nan value bits as 32 bit values (due to lack of longs)
14
+ const NAN_BUFFER = [
15
+ 0x7c,
16
+ 0x00,
17
+ 0x00,
18
+ 0x00,
19
+ 0x00,
20
+ 0x00,
21
+ 0x00,
22
+ 0x00,
23
+ 0x00,
24
+ 0x00,
25
+ 0x00,
26
+ 0x00,
27
+ 0x00,
28
+ 0x00,
29
+ 0x00,
30
+ 0x00
31
+ ].reverse();
32
+ // Infinity value bits 32 bit values (due to lack of longs)
33
+ const INF_NEGATIVE_BUFFER = [
34
+ 0xf8,
35
+ 0x00,
36
+ 0x00,
37
+ 0x00,
38
+ 0x00,
39
+ 0x00,
40
+ 0x00,
41
+ 0x00,
42
+ 0x00,
43
+ 0x00,
44
+ 0x00,
45
+ 0x00,
46
+ 0x00,
47
+ 0x00,
48
+ 0x00,
49
+ 0x00
50
+ ].reverse();
51
+ const INF_POSITIVE_BUFFER = [
52
+ 0x78,
53
+ 0x00,
54
+ 0x00,
55
+ 0x00,
56
+ 0x00,
57
+ 0x00,
58
+ 0x00,
59
+ 0x00,
60
+ 0x00,
61
+ 0x00,
62
+ 0x00,
63
+ 0x00,
64
+ 0x00,
65
+ 0x00,
66
+ 0x00,
67
+ 0x00
68
+ ].reverse();
69
+
70
+ const EXPONENT_REGEX = /^([-+])?(\d+)?$/;
71
+
72
+ // Extract least significant 5 bits
73
+ const COMBINATION_MASK = 0x1f;
74
+ // Extract least significant 14 bits
75
+ const EXPONENT_MASK = 0x3fff;
76
+ // Value of combination field for Inf
77
+ const COMBINATION_INFINITY = 30;
78
+ // Value of combination field for NaN
79
+ const COMBINATION_NAN = 31;
80
+
81
+ // Detect if the value is a digit
82
+ function isDigit(value: string): boolean {
83
+ return !isNaN(parseInt(value, 10));
84
+ }
85
+
86
+ // Divide two uint128 values
87
+ function divideu128(value: { parts: [number, number, number, number] }) {
88
+ const DIVISOR = Long.fromNumber(1000 * 1000 * 1000);
89
+ let _rem = Long.fromNumber(0);
90
+
91
+ if (!value.parts[0] && !value.parts[1] && !value.parts[2] && !value.parts[3]) {
92
+ return { quotient: value, rem: _rem };
93
+ }
94
+
95
+ for (let i = 0; i <= 3; i++) {
96
+ // Adjust remainder to match value of next dividend
97
+ _rem = _rem.shiftLeft(32);
98
+ // Add the divided to _rem
99
+ _rem = _rem.add(new Long(value.parts[i], 0));
100
+ value.parts[i] = _rem.div(DIVISOR).low;
101
+ _rem = _rem.modulo(DIVISOR);
102
+ }
103
+
104
+ return { quotient: value, rem: _rem };
105
+ }
106
+
107
+ // Multiply two Long values and return the 128 bit value
108
+ function multiply64x2(left: Long, right: Long): { high: Long; low: Long } {
109
+ if (!left && !right) {
110
+ return { high: Long.fromNumber(0), low: Long.fromNumber(0) };
111
+ }
112
+
113
+ const leftHigh = left.shiftRightUnsigned(32);
114
+ const leftLow = new Long(left.getLowBits(), 0);
115
+ const rightHigh = right.shiftRightUnsigned(32);
116
+ const rightLow = new Long(right.getLowBits(), 0);
117
+
118
+ let productHigh = leftHigh.multiply(rightHigh);
119
+ let productMid = leftHigh.multiply(rightLow);
120
+ const productMid2 = leftLow.multiply(rightHigh);
121
+ let productLow = leftLow.multiply(rightLow);
122
+
123
+ productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
124
+ productMid = new Long(productMid.getLowBits(), 0)
125
+ .add(productMid2)
126
+ .add(productLow.shiftRightUnsigned(32));
127
+
128
+ productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
129
+ productLow = productMid.shiftLeft(32).add(new Long(productLow.getLowBits(), 0));
130
+
131
+ // Return the 128 bit result
132
+ return { high: productHigh, low: productLow };
133
+ }
134
+
135
+ function lessThan(left: Long, right: Long): boolean {
136
+ // Make values unsigned
137
+ const uhleft = left.high >>> 0;
138
+ const uhright = right.high >>> 0;
139
+
140
+ // Compare high bits first
141
+ if (uhleft < uhright) {
142
+ return true;
143
+ } else if (uhleft === uhright) {
144
+ const ulleft = left.low >>> 0;
145
+ const ulright = right.low >>> 0;
146
+ if (ulleft < ulright) return true;
147
+ }
148
+
149
+ return false;
150
+ }
151
+
152
+ function invalidErr(string: string, message: string) {
153
+ throw new TypeError(`"${string}" is not a valid Decimal128 string - ${message}`);
154
+ }
155
+
156
+ /** @public */
157
+ export interface Decimal128Extended {
158
+ $numberDecimal: string;
159
+ }
160
+
161
+ /**
162
+ * A class representation of the BSON Decimal128 type.
163
+ * @public
164
+ */
165
+ export class Decimal128 {
166
+ _bsontype!: 'Decimal128';
167
+
168
+ readonly bytes: Buffer;
169
+
170
+ /** @param bytes - a buffer containing the raw Decimal128 bytes in little endian order */
171
+ constructor(bytes: Buffer) {
172
+ this.bytes = bytes;
173
+ }
174
+
175
+ /**
176
+ * Create a Decimal128 instance from a string representation
177
+ *
178
+ * @param representation - a numeric string representation.
179
+ */
180
+ static fromString(representation: string): Decimal128 {
181
+ // Parse state tracking
182
+ let isNegative = false;
183
+ let sawRadix = false;
184
+ let foundNonZero = false;
185
+
186
+ // Total number of significant digits (no leading or trailing zero)
187
+ let significantDigits = 0;
188
+ // Total number of significand digits read
189
+ let nDigitsRead = 0;
190
+ // Total number of digits (no leading zeros)
191
+ let nDigits = 0;
192
+ // The number of the digits after radix
193
+ let radixPosition = 0;
194
+ // The index of the first non-zero in *str*
195
+ let firstNonZero = 0;
196
+
197
+ // Digits Array
198
+ const digits = [0];
199
+ // The number of digits in digits
200
+ let nDigitsStored = 0;
201
+ // Insertion pointer for digits
202
+ let digitsInsert = 0;
203
+ // The index of the first non-zero digit
204
+ let firstDigit = 0;
205
+ // The index of the last digit
206
+ let lastDigit = 0;
207
+
208
+ // Exponent
209
+ let exponent = 0;
210
+ // loop index over array
211
+ let i = 0;
212
+ // The high 17 digits of the significand
213
+ let significandHigh = new Long(0, 0);
214
+ // The low 17 digits of the significand
215
+ let significandLow = new Long(0, 0);
216
+ // The biased exponent
217
+ let biasedExponent = 0;
218
+
219
+ // Read index
220
+ let index = 0;
221
+
222
+ // Naively prevent against REDOS attacks.
223
+ // TODO: implementing a custom parsing for this, or refactoring the regex would yield
224
+ // further gains.
225
+ if (representation.length >= 7000) {
226
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
227
+ }
228
+
229
+ // Results
230
+ const stringMatch = representation.match(PARSE_STRING_REGEXP);
231
+ const infMatch = representation.match(PARSE_INF_REGEXP);
232
+ const nanMatch = representation.match(PARSE_NAN_REGEXP);
233
+
234
+ // Validate the string
235
+ if ((!stringMatch && !infMatch && !nanMatch) || representation.length === 0) {
236
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
237
+ }
238
+
239
+ if (stringMatch) {
240
+ // full_match = stringMatch[0]
241
+ // sign = stringMatch[1]
242
+
243
+ const unsignedNumber = stringMatch[2];
244
+ // stringMatch[3] is undefined if a whole number (ex "1", 12")
245
+ // but defined if a number w/ decimal in it (ex "1.0, 12.2")
246
+
247
+ const e = stringMatch[4];
248
+ const expSign = stringMatch[5];
249
+ const expNumber = stringMatch[6];
250
+
251
+ // they provided e, but didn't give an exponent number. for ex "1e"
252
+ if (e && expNumber === undefined) invalidErr(representation, 'missing exponent power');
253
+
254
+ // they provided e, but didn't give a number before it. for ex "e1"
255
+ if (e && unsignedNumber === undefined) invalidErr(representation, 'missing exponent base');
256
+
257
+ if (e === undefined && (expSign || expNumber)) {
258
+ invalidErr(representation, 'missing e before exponent');
259
+ }
260
+ }
261
+
262
+ // Get the negative or positive sign
263
+ if (representation[index] === '+' || representation[index] === '-') {
264
+ isNegative = representation[index++] === '-';
265
+ }
266
+
267
+ // Check if user passed Infinity or NaN
268
+ if (!isDigit(representation[index]) && representation[index] !== '.') {
269
+ if (representation[index] === 'i' || representation[index] === 'I') {
270
+ return new Decimal128(Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
271
+ } else if (representation[index] === 'N') {
272
+ return new Decimal128(Buffer.from(NAN_BUFFER));
273
+ }
274
+ }
275
+
276
+ // Read all the digits
277
+ while (isDigit(representation[index]) || representation[index] === '.') {
278
+ if (representation[index] === '.') {
279
+ if (sawRadix) invalidErr(representation, 'contains multiple periods');
280
+
281
+ sawRadix = true;
282
+ index = index + 1;
283
+ continue;
284
+ }
285
+
286
+ if (nDigitsStored < 34) {
287
+ if (representation[index] !== '0' || foundNonZero) {
288
+ if (!foundNonZero) {
289
+ firstNonZero = nDigitsRead;
290
+ }
291
+
292
+ foundNonZero = true;
293
+
294
+ // Only store 34 digits
295
+ digits[digitsInsert++] = parseInt(representation[index], 10);
296
+ nDigitsStored = nDigitsStored + 1;
297
+ }
298
+ }
299
+
300
+ if (foundNonZero) nDigits = nDigits + 1;
301
+ if (sawRadix) radixPosition = radixPosition + 1;
302
+
303
+ nDigitsRead = nDigitsRead + 1;
304
+ index = index + 1;
305
+ }
306
+
307
+ if (sawRadix && !nDigitsRead)
308
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
309
+
310
+ // Read exponent if exists
311
+ if (representation[index] === 'e' || representation[index] === 'E') {
312
+ // Read exponent digits
313
+ const match = representation.substr(++index).match(EXPONENT_REGEX);
314
+
315
+ // No digits read
316
+ if (!match || !match[2]) return new Decimal128(Buffer.from(NAN_BUFFER));
317
+
318
+ // Get exponent
319
+ exponent = parseInt(match[0], 10);
320
+
321
+ // Adjust the index
322
+ index = index + match[0].length;
323
+ }
324
+
325
+ // Return not a number
326
+ if (representation[index]) return new Decimal128(Buffer.from(NAN_BUFFER));
327
+
328
+ // Done reading input
329
+ // Find first non-zero digit in digits
330
+ firstDigit = 0;
331
+
332
+ if (!nDigitsStored) {
333
+ firstDigit = 0;
334
+ lastDigit = 0;
335
+ digits[0] = 0;
336
+ nDigits = 1;
337
+ nDigitsStored = 1;
338
+ significantDigits = 0;
339
+ } else {
340
+ lastDigit = nDigitsStored - 1;
341
+ significantDigits = nDigits;
342
+ if (significantDigits !== 1) {
343
+ while (representation[firstNonZero + significantDigits - 1] === '0') {
344
+ significantDigits = significantDigits - 1;
345
+ }
346
+ }
347
+ }
348
+
349
+ // Normalization of exponent
350
+ // Correct exponent based on radix position, and shift significand as needed
351
+ // to represent user input
352
+
353
+ // Overflow prevention
354
+ if (exponent <= radixPosition && radixPosition - exponent > 1 << 14) {
355
+ exponent = EXPONENT_MIN;
356
+ } else {
357
+ exponent = exponent - radixPosition;
358
+ }
359
+
360
+ // Attempt to normalize the exponent
361
+ while (exponent > EXPONENT_MAX) {
362
+ // Shift exponent to significand and decrease
363
+ lastDigit = lastDigit + 1;
364
+
365
+ if (lastDigit - firstDigit > MAX_DIGITS) {
366
+ // Check if we have a zero then just hard clamp, otherwise fail
367
+ const digitsString = digits.join('');
368
+ if (digitsString.match(/^0+$/)) {
369
+ exponent = EXPONENT_MAX;
370
+ break;
371
+ }
372
+
373
+ invalidErr(representation, 'overflow');
374
+ }
375
+ exponent = exponent - 1;
376
+ }
377
+
378
+ while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
379
+ // Shift last digit. can only do this if < significant digits than # stored.
380
+ if (lastDigit === 0 && significantDigits < nDigitsStored) {
381
+ exponent = EXPONENT_MIN;
382
+ significantDigits = 0;
383
+ break;
384
+ }
385
+
386
+ if (nDigitsStored < nDigits) {
387
+ // adjust to match digits not stored
388
+ nDigits = nDigits - 1;
389
+ } else {
390
+ // adjust to round
391
+ lastDigit = lastDigit - 1;
392
+ }
393
+
394
+ if (exponent < EXPONENT_MAX) {
395
+ exponent = exponent + 1;
396
+ } else {
397
+ // Check if we have a zero then just hard clamp, otherwise fail
398
+ const digitsString = digits.join('');
399
+ if (digitsString.match(/^0+$/)) {
400
+ exponent = EXPONENT_MAX;
401
+ break;
402
+ }
403
+ invalidErr(representation, 'overflow');
404
+ }
405
+ }
406
+
407
+ // Round
408
+ // We've normalized the exponent, but might still need to round.
409
+ if (lastDigit - firstDigit + 1 < significantDigits) {
410
+ let endOfString = nDigitsRead;
411
+
412
+ // If we have seen a radix point, 'string' is 1 longer than we have
413
+ // documented with ndigits_read, so inc the position of the first nonzero
414
+ // digit and the position that digits are read to.
415
+ if (sawRadix) {
416
+ firstNonZero = firstNonZero + 1;
417
+ endOfString = endOfString + 1;
418
+ }
419
+ // if negative, we need to increment again to account for - sign at start.
420
+ if (isNegative) {
421
+ firstNonZero = firstNonZero + 1;
422
+ endOfString = endOfString + 1;
423
+ }
424
+
425
+ const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
426
+ let roundBit = 0;
427
+
428
+ if (roundDigit >= 5) {
429
+ roundBit = 1;
430
+ if (roundDigit === 5) {
431
+ roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
432
+ for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
433
+ if (parseInt(representation[i], 10)) {
434
+ roundBit = 1;
435
+ break;
436
+ }
437
+ }
438
+ }
439
+ }
440
+
441
+ if (roundBit) {
442
+ let dIdx = lastDigit;
443
+
444
+ for (; dIdx >= 0; dIdx--) {
445
+ if (++digits[dIdx] > 9) {
446
+ digits[dIdx] = 0;
447
+
448
+ // overflowed most significant digit
449
+ if (dIdx === 0) {
450
+ if (exponent < EXPONENT_MAX) {
451
+ exponent = exponent + 1;
452
+ digits[dIdx] = 1;
453
+ } else {
454
+ return new Decimal128(
455
+ Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER)
456
+ );
457
+ }
458
+ }
459
+ }
460
+ }
461
+ }
462
+ }
463
+
464
+ // Encode significand
465
+ // The high 17 digits of the significand
466
+ significandHigh = Long.fromNumber(0);
467
+ // The low 17 digits of the significand
468
+ significandLow = Long.fromNumber(0);
469
+
470
+ // read a zero
471
+ if (significantDigits === 0) {
472
+ significandHigh = Long.fromNumber(0);
473
+ significandLow = Long.fromNumber(0);
474
+ } else if (lastDigit - firstDigit < 17) {
475
+ let dIdx = firstDigit;
476
+ significandLow = Long.fromNumber(digits[dIdx++]);
477
+ significandHigh = new Long(0, 0);
478
+
479
+ for (; dIdx <= lastDigit; dIdx++) {
480
+ significandLow = significandLow.multiply(Long.fromNumber(10));
481
+ significandLow = significandLow.add(Long.fromNumber(digits[dIdx]));
482
+ }
483
+ } else {
484
+ let dIdx = firstDigit;
485
+ significandHigh = Long.fromNumber(digits[dIdx++]);
486
+
487
+ for (; dIdx <= lastDigit - 17; dIdx++) {
488
+ significandHigh = significandHigh.multiply(Long.fromNumber(10));
489
+ significandHigh = significandHigh.add(Long.fromNumber(digits[dIdx]));
490
+ }
491
+
492
+ significandLow = Long.fromNumber(digits[dIdx++]);
493
+
494
+ for (; dIdx <= lastDigit; dIdx++) {
495
+ significandLow = significandLow.multiply(Long.fromNumber(10));
496
+ significandLow = significandLow.add(Long.fromNumber(digits[dIdx]));
497
+ }
498
+ }
499
+
500
+ const significand = multiply64x2(significandHigh, Long.fromString('100000000000000000'));
501
+ significand.low = significand.low.add(significandLow);
502
+
503
+ if (lessThan(significand.low, significandLow)) {
504
+ significand.high = significand.high.add(Long.fromNumber(1));
505
+ }
506
+
507
+ // Biased exponent
508
+ biasedExponent = exponent + EXPONENT_BIAS;
509
+ const dec = { low: Long.fromNumber(0), high: Long.fromNumber(0) };
510
+
511
+ // Encode combination, exponent, and significand.
512
+ if (
513
+ significand.high.shiftRightUnsigned(49).and(Long.fromNumber(1)).equals(Long.fromNumber(1))
514
+ ) {
515
+ // Encode '11' into bits 1 to 3
516
+ dec.high = dec.high.or(Long.fromNumber(0x3).shiftLeft(61));
517
+ dec.high = dec.high.or(
518
+ Long.fromNumber(biasedExponent).and(Long.fromNumber(0x3fff).shiftLeft(47))
519
+ );
520
+ dec.high = dec.high.or(significand.high.and(Long.fromNumber(0x7fffffffffff)));
521
+ } else {
522
+ dec.high = dec.high.or(Long.fromNumber(biasedExponent & 0x3fff).shiftLeft(49));
523
+ dec.high = dec.high.or(significand.high.and(Long.fromNumber(0x1ffffffffffff)));
524
+ }
525
+
526
+ dec.low = significand.low;
527
+
528
+ // Encode sign
529
+ if (isNegative) {
530
+ dec.high = dec.high.or(Long.fromString('9223372036854775808'));
531
+ }
532
+
533
+ // Encode into a buffer
534
+ const buffer = Buffer.alloc(16);
535
+ index = 0;
536
+
537
+ // Encode the low 64 bits of the decimal
538
+ // Encode low bits
539
+ buffer[index++] = dec.low.low & 0xff;
540
+ buffer[index++] = (dec.low.low >> 8) & 0xff;
541
+ buffer[index++] = (dec.low.low >> 16) & 0xff;
542
+ buffer[index++] = (dec.low.low >> 24) & 0xff;
543
+ // Encode high bits
544
+ buffer[index++] = dec.low.high & 0xff;
545
+ buffer[index++] = (dec.low.high >> 8) & 0xff;
546
+ buffer[index++] = (dec.low.high >> 16) & 0xff;
547
+ buffer[index++] = (dec.low.high >> 24) & 0xff;
548
+
549
+ // Encode the high 64 bits of the decimal
550
+ // Encode low bits
551
+ buffer[index++] = dec.high.low & 0xff;
552
+ buffer[index++] = (dec.high.low >> 8) & 0xff;
553
+ buffer[index++] = (dec.high.low >> 16) & 0xff;
554
+ buffer[index++] = (dec.high.low >> 24) & 0xff;
555
+ // Encode high bits
556
+ buffer[index++] = dec.high.high & 0xff;
557
+ buffer[index++] = (dec.high.high >> 8) & 0xff;
558
+ buffer[index++] = (dec.high.high >> 16) & 0xff;
559
+ buffer[index++] = (dec.high.high >> 24) & 0xff;
560
+
561
+ // Return the new Decimal128
562
+ return new Decimal128(buffer);
563
+ }
564
+
565
+ /** Create a string representation of the raw Decimal128 value */
566
+ toString(): string {
567
+ // Note: bits in this routine are referred to starting at 0,
568
+ // from the sign bit, towards the coefficient.
569
+
570
+ // decoded biased exponent (14 bits)
571
+ let biased_exponent;
572
+ // the number of significand digits
573
+ let significand_digits = 0;
574
+ // the base-10 digits in the significand
575
+ const significand = new Array<number>(36);
576
+ for (let i = 0; i < significand.length; i++) significand[i] = 0;
577
+ // read pointer into significand
578
+ let index = 0;
579
+
580
+ // true if the number is zero
581
+ let is_zero = false;
582
+
583
+ // the most significant significand bits (50-46)
584
+ let significand_msb;
585
+ // temporary storage for significand decoding
586
+ let significand128: { parts: [number, number, number, number] } = { parts: [0, 0, 0, 0] };
587
+ // indexing variables
588
+ let j, k;
589
+
590
+ // Output string
591
+ const string: string[] = [];
592
+
593
+ // Unpack index
594
+ index = 0;
595
+
596
+ // Buffer reference
597
+ const buffer = this.bytes;
598
+
599
+ // Unpack the low 64bits into a long
600
+ // bits 96 - 127
601
+ const low =
602
+ buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
603
+ // bits 64 - 95
604
+ const midl =
605
+ buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
606
+
607
+ // Unpack the high 64bits into a long
608
+ // bits 32 - 63
609
+ const midh =
610
+ buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
611
+ // bits 0 - 31
612
+ const high =
613
+ buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
614
+
615
+ // Unpack index
616
+ index = 0;
617
+
618
+ // Create the state of the decimal
619
+ const dec = {
620
+ low: new Long(low, midl),
621
+ high: new Long(midh, high)
622
+ };
623
+
624
+ if (dec.high.lessThan(Long.ZERO)) {
625
+ string.push('-');
626
+ }
627
+
628
+ // Decode combination field and exponent
629
+ // bits 1 - 5
630
+ const combination = (high >> 26) & COMBINATION_MASK;
631
+
632
+ if (combination >> 3 === 3) {
633
+ // Check for 'special' values
634
+ if (combination === COMBINATION_INFINITY) {
635
+ return string.join('') + 'Infinity';
636
+ } else if (combination === COMBINATION_NAN) {
637
+ return 'NaN';
638
+ } else {
639
+ biased_exponent = (high >> 15) & EXPONENT_MASK;
640
+ significand_msb = 0x08 + ((high >> 14) & 0x01);
641
+ }
642
+ } else {
643
+ significand_msb = (high >> 14) & 0x07;
644
+ biased_exponent = (high >> 17) & EXPONENT_MASK;
645
+ }
646
+
647
+ // unbiased exponent
648
+ const exponent = biased_exponent - EXPONENT_BIAS;
649
+
650
+ // Create string of significand digits
651
+
652
+ // Convert the 114-bit binary number represented by
653
+ // (significand_high, significand_low) to at most 34 decimal
654
+ // digits through modulo and division.
655
+ significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
656
+ significand128.parts[1] = midh;
657
+ significand128.parts[2] = midl;
658
+ significand128.parts[3] = low;
659
+
660
+ if (
661
+ significand128.parts[0] === 0 &&
662
+ significand128.parts[1] === 0 &&
663
+ significand128.parts[2] === 0 &&
664
+ significand128.parts[3] === 0
665
+ ) {
666
+ is_zero = true;
667
+ } else {
668
+ for (k = 3; k >= 0; k--) {
669
+ let least_digits = 0;
670
+ // Perform the divide
671
+ const result = divideu128(significand128);
672
+ significand128 = result.quotient;
673
+ least_digits = result.rem.low;
674
+
675
+ // We now have the 9 least significant digits (in base 2).
676
+ // Convert and output to string.
677
+ if (!least_digits) continue;
678
+
679
+ for (j = 8; j >= 0; j--) {
680
+ // significand[k * 9 + j] = Math.round(least_digits % 10);
681
+ significand[k * 9 + j] = least_digits % 10;
682
+ // least_digits = Math.round(least_digits / 10);
683
+ least_digits = Math.floor(least_digits / 10);
684
+ }
685
+ }
686
+ }
687
+
688
+ // Output format options:
689
+ // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd
690
+ // Regular - ddd.ddd
691
+
692
+ if (is_zero) {
693
+ significand_digits = 1;
694
+ significand[index] = 0;
695
+ } else {
696
+ significand_digits = 36;
697
+ while (!significand[index]) {
698
+ significand_digits = significand_digits - 1;
699
+ index = index + 1;
700
+ }
701
+ }
702
+
703
+ // the exponent if scientific notation is used
704
+ const scientific_exponent = significand_digits - 1 + exponent;
705
+
706
+ // The scientific exponent checks are dictated by the string conversion
707
+ // specification and are somewhat arbitrary cutoffs.
708
+ //
709
+ // We must check exponent > 0, because if this is the case, the number
710
+ // has trailing zeros. However, we *cannot* output these trailing zeros,
711
+ // because doing so would change the precision of the value, and would
712
+ // change stored data if the string converted number is round tripped.
713
+ if (scientific_exponent >= 34 || scientific_exponent <= -7 || exponent > 0) {
714
+ // Scientific format
715
+
716
+ // if there are too many significant digits, we should just be treating numbers
717
+ // as + or - 0 and using the non-scientific exponent (this is for the "invalid
718
+ // representation should be treated as 0/-0" spec cases in decimal128-1.json)
719
+ if (significand_digits > 34) {
720
+ string.push(`${0}`);
721
+ if (exponent > 0) string.push('E+' + exponent);
722
+ else if (exponent < 0) string.push('E' + exponent);
723
+ return string.join('');
724
+ }
725
+
726
+ string.push(`${significand[index++]}`);
727
+ significand_digits = significand_digits - 1;
728
+
729
+ if (significand_digits) {
730
+ string.push('.');
731
+ }
732
+
733
+ for (let i = 0; i < significand_digits; i++) {
734
+ string.push(`${significand[index++]}`);
735
+ }
736
+
737
+ // Exponent
738
+ string.push('E');
739
+ if (scientific_exponent > 0) {
740
+ string.push('+' + scientific_exponent);
741
+ } else {
742
+ string.push(`${scientific_exponent}`);
743
+ }
744
+ } else {
745
+ // Regular format with no decimal place
746
+ if (exponent >= 0) {
747
+ for (let i = 0; i < significand_digits; i++) {
748
+ string.push(`${significand[index++]}`);
749
+ }
750
+ } else {
751
+ let radix_position = significand_digits + exponent;
752
+
753
+ // non-zero digits before radix
754
+ if (radix_position > 0) {
755
+ for (let i = 0; i < radix_position; i++) {
756
+ string.push(`${significand[index++]}`);
757
+ }
758
+ } else {
759
+ string.push('0');
760
+ }
761
+
762
+ string.push('.');
763
+ // add leading zeros after radix
764
+ while (radix_position++ < 0) {
765
+ string.push('0');
766
+ }
767
+
768
+ for (let i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) {
769
+ string.push(`${significand[index++]}`);
770
+ }
771
+ }
772
+ }
773
+
774
+ return string.join('');
775
+ }
776
+
777
+ toJSON(): Decimal128Extended {
778
+ return { $numberDecimal: this.toString() };
779
+ }
780
+
781
+ /** @internal */
782
+ toExtendedJSON(): Decimal128Extended {
783
+ return { $numberDecimal: this.toString() };
784
+ }
785
+
786
+ /** @internal */
787
+ static fromExtendedJSON(doc: Decimal128Extended): Decimal128 {
788
+ return Decimal128.fromString(doc.$numberDecimal);
789
+ }
790
+
791
+ /** @internal */
792
+ [Symbol.for('nodejs.util.inspect.custom')](): string {
793
+ return this.inspect();
794
+ }
795
+
796
+ inspect(): string {
797
+ return `Decimal128("${this.toString()}")`;
798
+ }
799
+ }
800
+
801
+ Object.defineProperty(Decimal128.prototype, '_bsontype', { value: 'Decimal128' });