bson 6.0.0 → 6.1.0

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/bson.d.ts CHANGED
@@ -381,6 +381,26 @@ export declare class Decimal128 extends BSONValue {
381
381
  * @param representation - a numeric string representation.
382
382
  */
383
383
  static fromString(representation: string): Decimal128;
384
+ /**
385
+ * Create a Decimal128 instance from a string representation, allowing for rounding to 34
386
+ * significant digits
387
+ *
388
+ * @example Example of a number that will be rounded
389
+ * ```ts
390
+ * > let d = Decimal128.fromString('37.499999999999999196428571428571375')
391
+ * Uncaught:
392
+ * BSONError: "37.499999999999999196428571428571375" is not a valid Decimal128 string - inexact rounding
393
+ * at invalidErr (/home/wajames/js-bson/lib/bson.cjs:1402:11)
394
+ * at Decimal128.fromStringInternal (/home/wajames/js-bson/lib/bson.cjs:1633:25)
395
+ * at Decimal128.fromString (/home/wajames/js-bson/lib/bson.cjs:1424:27)
396
+ *
397
+ * > d = Decimal128.fromStringWithRounding('37.499999999999999196428571428571375')
398
+ * new Decimal128("37.49999999999999919642857142857138")
399
+ * ```
400
+ * @param representation - a numeric string representation.
401
+ */
402
+ static fromStringWithRounding(representation: string): Decimal128;
403
+ private static _fromString;
384
404
  /** Create a string representation of the raw Decimal128 value */
385
405
  toString(): string;
386
406
  toJSON(): Decimal128Extended;
@@ -1422,6 +1422,12 @@ class Decimal128 extends BSONValue {
1422
1422
  }
1423
1423
  }
1424
1424
  static fromString(representation) {
1425
+ return Decimal128._fromString(representation, { allowRounding: false });
1426
+ }
1427
+ static fromStringWithRounding(representation) {
1428
+ return Decimal128._fromString(representation, { allowRounding: true });
1429
+ }
1430
+ static _fromString(representation, options) {
1425
1431
  let isNegative = false;
1426
1432
  let sawSign = false;
1427
1433
  let sawRadix = false;
@@ -1542,44 +1548,117 @@ class Decimal128 extends BSONValue {
1542
1548
  }
1543
1549
  exponent = exponent - 1;
1544
1550
  }
1545
- while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
1546
- if (lastDigit === 0) {
1547
- if (significantDigits === 0) {
1551
+ if (options.allowRounding) {
1552
+ while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
1553
+ if (lastDigit === 0 && significantDigits < nDigitsStored) {
1548
1554
  exponent = EXPONENT_MIN;
1555
+ significantDigits = 0;
1549
1556
  break;
1550
1557
  }
1551
- invalidErr(representation, 'exponent underflow');
1552
- }
1553
- if (nDigitsStored < nDigits) {
1554
- if (representation[nDigits - 1 + Number(sawSign) + Number(sawRadix)] !== '0' &&
1555
- significantDigits !== 0) {
1556
- invalidErr(representation, 'inexact rounding');
1558
+ if (nDigitsStored < nDigits) {
1559
+ nDigits = nDigits - 1;
1557
1560
  }
1558
- nDigits = nDigits - 1;
1559
- }
1560
- else {
1561
- if (digits[lastDigit] !== 0) {
1562
- invalidErr(representation, 'inexact rounding');
1561
+ else {
1562
+ lastDigit = lastDigit - 1;
1563
+ }
1564
+ if (exponent < EXPONENT_MAX) {
1565
+ exponent = exponent + 1;
1566
+ }
1567
+ else {
1568
+ const digitsString = digits.join('');
1569
+ if (digitsString.match(/^0+$/)) {
1570
+ exponent = EXPONENT_MAX;
1571
+ break;
1572
+ }
1573
+ invalidErr(representation, 'overflow');
1563
1574
  }
1564
- lastDigit = lastDigit - 1;
1565
- }
1566
- if (exponent < EXPONENT_MAX) {
1567
- exponent = exponent + 1;
1568
1575
  }
1569
- else {
1570
- invalidErr(representation, 'overflow');
1576
+ if (lastDigit + 1 < significantDigits) {
1577
+ let endOfString = nDigitsRead;
1578
+ if (sawRadix) {
1579
+ firstNonZero = firstNonZero + 1;
1580
+ endOfString = endOfString + 1;
1581
+ }
1582
+ if (sawSign) {
1583
+ firstNonZero = firstNonZero + 1;
1584
+ endOfString = endOfString + 1;
1585
+ }
1586
+ const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
1587
+ let roundBit = 0;
1588
+ if (roundDigit >= 5) {
1589
+ roundBit = 1;
1590
+ if (roundDigit === 5) {
1591
+ roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
1592
+ for (let i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
1593
+ if (parseInt(representation[i], 10)) {
1594
+ roundBit = 1;
1595
+ break;
1596
+ }
1597
+ }
1598
+ }
1599
+ }
1600
+ if (roundBit) {
1601
+ let dIdx = lastDigit;
1602
+ for (; dIdx >= 0; dIdx--) {
1603
+ if (++digits[dIdx] > 9) {
1604
+ digits[dIdx] = 0;
1605
+ if (dIdx === 0) {
1606
+ if (exponent < EXPONENT_MAX) {
1607
+ exponent = exponent + 1;
1608
+ digits[dIdx] = 1;
1609
+ }
1610
+ else {
1611
+ return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
1612
+ }
1613
+ }
1614
+ }
1615
+ else {
1616
+ break;
1617
+ }
1618
+ }
1619
+ }
1571
1620
  }
1572
1621
  }
1573
- if (lastDigit + 1 < significantDigits) {
1574
- if (sawRadix) {
1575
- firstNonZero = firstNonZero + 1;
1576
- }
1577
- if (sawSign) {
1578
- firstNonZero = firstNonZero + 1;
1622
+ else {
1623
+ while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
1624
+ if (lastDigit === 0) {
1625
+ if (significantDigits === 0) {
1626
+ exponent = EXPONENT_MIN;
1627
+ break;
1628
+ }
1629
+ invalidErr(representation, 'exponent underflow');
1630
+ }
1631
+ if (nDigitsStored < nDigits) {
1632
+ if (representation[nDigits - 1 + Number(sawSign) + Number(sawRadix)] !== '0' &&
1633
+ significantDigits !== 0) {
1634
+ invalidErr(representation, 'inexact rounding');
1635
+ }
1636
+ nDigits = nDigits - 1;
1637
+ }
1638
+ else {
1639
+ if (digits[lastDigit] !== 0) {
1640
+ invalidErr(representation, 'inexact rounding');
1641
+ }
1642
+ lastDigit = lastDigit - 1;
1643
+ }
1644
+ if (exponent < EXPONENT_MAX) {
1645
+ exponent = exponent + 1;
1646
+ }
1647
+ else {
1648
+ invalidErr(representation, 'overflow');
1649
+ }
1579
1650
  }
1580
- const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
1581
- if (roundDigit !== 0) {
1582
- invalidErr(representation, 'inexact rounding');
1651
+ if (lastDigit + 1 < significantDigits) {
1652
+ if (sawRadix) {
1653
+ firstNonZero = firstNonZero + 1;
1654
+ }
1655
+ if (sawSign) {
1656
+ firstNonZero = firstNonZero + 1;
1657
+ }
1658
+ const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
1659
+ if (roundDigit !== 0) {
1660
+ invalidErr(representation, 'inexact rounding');
1661
+ }
1583
1662
  }
1584
1663
  }
1585
1664
  significandHigh = Long.fromNumber(0);
@@ -3090,13 +3169,16 @@ function serializeObjectId(buffer, key, value, index) {
3090
3169
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3091
3170
  index = index + numberOfWrittenBytes;
3092
3171
  buffer[index++] = 0;
3093
- if (isUint8Array(value.id)) {
3094
- buffer.set(value.id.subarray(0, 12), index);
3172
+ const idValue = value.id;
3173
+ if (isUint8Array(idValue)) {
3174
+ for (let i = 0; i < 12; i++) {
3175
+ buffer[index++] = idValue[i];
3176
+ }
3095
3177
  }
3096
3178
  else {
3097
3179
  throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3098
3180
  }
3099
- return index + 12;
3181
+ return index;
3100
3182
  }
3101
3183
  function serializeBuffer(buffer, key, value, index) {
3102
3184
  buffer[index++] = BSON_DATA_BINARY;