bson 5.3.0 β 5.5.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/README.md +4 -11
- package/bson.d.ts +20 -0
- package/lib/bson.bundle.js +137 -86
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +137 -86
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +137 -86
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.rn.cjs +4159 -0
- package/lib/bson.rn.cjs.map +1 -0
- package/package.json +8 -7
- package/src/binary.ts +3 -2
- package/src/bson.ts +2 -2
- package/src/decimal128.ts +165 -84
- package/src/parser/deserializer.ts +8 -8
- package/src/timestamp.ts +7 -5
- package/src/utils/byte_utils.ts +1 -1
- package/src/utils/node_byte_utils.ts +3 -3
- package/src/utils/web_byte_utils.ts +2 -2
- package/vendor/base64/LICENSE-MIT.txt +20 -0
- package/vendor/base64/README.md +112 -0
- package/vendor/base64/base64.js +157 -0
- package/vendor/base64/package.json +43 -0
- package/vendor/text-encoding/LICENSE.md +237 -0
- package/vendor/text-encoding/README.md +111 -0
- package/vendor/text-encoding/index.js +9 -0
- package/vendor/text-encoding/lib/encoding-indexes.js +47 -0
- package/vendor/text-encoding/lib/encoding.js +3301 -0
- package/vendor/text-encoding/package.json +37 -0
- package/lib/binary.d.ts +0 -182
- package/lib/binary.d.ts.map +0 -1
- package/lib/bson.d.ts +0 -97
- package/lib/bson.d.ts.map +0 -1
- package/lib/bson_value.d.ts +0 -10
- package/lib/bson_value.d.ts.map +0 -1
- package/lib/code.d.ts +0 -32
- package/lib/code.d.ts.map +0 -1
- package/lib/constants.d.ts +0 -107
- package/lib/constants.d.ts.map +0 -1
- package/lib/db_ref.d.ts +0 -40
- package/lib/db_ref.d.ts.map +0 -1
- package/lib/decimal128.d.ts +0 -34
- package/lib/decimal128.d.ts.map +0 -1
- package/lib/double.d.ts +0 -35
- package/lib/double.d.ts.map +0 -1
- package/lib/error.d.ts +0 -50
- package/lib/error.d.ts.map +0 -1
- package/lib/extended_json.d.ts +0 -82
- package/lib/extended_json.d.ts.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.d.ts.map +0 -1
- package/lib/int_32.d.ts +0 -35
- package/lib/int_32.d.ts.map +0 -1
- package/lib/long.d.ts +0 -323
- package/lib/long.d.ts.map +0 -1
- package/lib/max_key.d.ts +0 -19
- package/lib/max_key.d.ts.map +0 -1
- package/lib/min_key.d.ts +0 -19
- package/lib/min_key.d.ts.map +0 -1
- package/lib/objectid.d.ts +0 -96
- package/lib/objectid.d.ts.map +0 -1
- package/lib/regexp.d.ts +0 -36
- package/lib/regexp.d.ts.map +0 -1
- package/lib/symbol.d.ts +0 -28
- package/lib/symbol.d.ts.map +0 -1
- package/lib/timestamp.d.ts +0 -66
- package/lib/timestamp.d.ts.map +0 -1
- package/lib/validate_utf8.d.ts +0 -10
- package/lib/validate_utf8.d.ts.map +0 -1
package/src/decimal128.ts
CHANGED
|
@@ -158,8 +158,35 @@ export class Decimal128 extends BSONValue {
|
|
|
158
158
|
* @param representation - a numeric string representation.
|
|
159
159
|
*/
|
|
160
160
|
static fromString(representation: string): Decimal128 {
|
|
161
|
+
return Decimal128._fromString(representation, { allowRounding: false });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Create a Decimal128 instance from a string representation, allowing for rounding to 34
|
|
166
|
+
* significant digits
|
|
167
|
+
*
|
|
168
|
+
* @example Example of a number that will be rounded
|
|
169
|
+
* ```ts
|
|
170
|
+
* > let d = Decimal128.fromString('37.499999999999999196428571428571375')
|
|
171
|
+
* Uncaught:
|
|
172
|
+
* BSONError: "37.499999999999999196428571428571375" is not a valid Decimal128 string - inexact rounding
|
|
173
|
+
* at invalidErr (/home/wajames/js-bson/lib/bson.cjs:1402:11)
|
|
174
|
+
* at Decimal128.fromStringInternal (/home/wajames/js-bson/lib/bson.cjs:1633:25)
|
|
175
|
+
* at Decimal128.fromString (/home/wajames/js-bson/lib/bson.cjs:1424:27)
|
|
176
|
+
*
|
|
177
|
+
* > d = Decimal128.fromStringWithRounding('37.499999999999999196428571428571375')
|
|
178
|
+
* new Decimal128("37.49999999999999919642857142857138")
|
|
179
|
+
* ```
|
|
180
|
+
* @param representation - a numeric string representation.
|
|
181
|
+
*/
|
|
182
|
+
static fromStringWithRounding(representation: string): Decimal128 {
|
|
183
|
+
return Decimal128._fromString(representation, { allowRounding: true });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private static _fromString(representation: string, options: { allowRounding: boolean }) {
|
|
161
187
|
// Parse state tracking
|
|
162
188
|
let isNegative = false;
|
|
189
|
+
let sawSign = false;
|
|
163
190
|
let sawRadix = false;
|
|
164
191
|
let foundNonZero = false;
|
|
165
192
|
|
|
@@ -180,15 +207,11 @@ export class Decimal128 extends BSONValue {
|
|
|
180
207
|
let nDigitsStored = 0;
|
|
181
208
|
// Insertion pointer for digits
|
|
182
209
|
let digitsInsert = 0;
|
|
183
|
-
// The index of the first non-zero digit
|
|
184
|
-
let firstDigit = 0;
|
|
185
210
|
// The index of the last digit
|
|
186
211
|
let lastDigit = 0;
|
|
187
212
|
|
|
188
213
|
// Exponent
|
|
189
214
|
let exponent = 0;
|
|
190
|
-
// loop index over array
|
|
191
|
-
let i = 0;
|
|
192
215
|
// The high 17 digits of the significand
|
|
193
216
|
let significandHigh = new Long(0, 0);
|
|
194
217
|
// The low 17 digits of the significand
|
|
@@ -241,6 +264,7 @@ export class Decimal128 extends BSONValue {
|
|
|
241
264
|
|
|
242
265
|
// Get the negative or positive sign
|
|
243
266
|
if (representation[index] === '+' || representation[index] === '-') {
|
|
267
|
+
sawSign = true;
|
|
244
268
|
isNegative = representation[index++] === '-';
|
|
245
269
|
}
|
|
246
270
|
|
|
@@ -263,7 +287,7 @@ export class Decimal128 extends BSONValue {
|
|
|
263
287
|
continue;
|
|
264
288
|
}
|
|
265
289
|
|
|
266
|
-
if (nDigitsStored <
|
|
290
|
+
if (nDigitsStored < MAX_DIGITS) {
|
|
267
291
|
if (representation[index] !== '0' || foundNonZero) {
|
|
268
292
|
if (!foundNonZero) {
|
|
269
293
|
firstNonZero = nDigitsRead;
|
|
@@ -307,11 +331,7 @@ export class Decimal128 extends BSONValue {
|
|
|
307
331
|
|
|
308
332
|
// Done reading input
|
|
309
333
|
// Find first non-zero digit in digits
|
|
310
|
-
firstDigit = 0;
|
|
311
|
-
|
|
312
334
|
if (!nDigitsStored) {
|
|
313
|
-
firstDigit = 0;
|
|
314
|
-
lastDigit = 0;
|
|
315
335
|
digits[0] = 0;
|
|
316
336
|
nDigits = 1;
|
|
317
337
|
nDigitsStored = 1;
|
|
@@ -320,7 +340,11 @@ export class Decimal128 extends BSONValue {
|
|
|
320
340
|
lastDigit = nDigitsStored - 1;
|
|
321
341
|
significantDigits = nDigits;
|
|
322
342
|
if (significantDigits !== 1) {
|
|
323
|
-
while (
|
|
343
|
+
while (
|
|
344
|
+
representation[
|
|
345
|
+
firstNonZero + significantDigits - 1 + Number(sawSign) + Number(sawRadix)
|
|
346
|
+
] === '0'
|
|
347
|
+
) {
|
|
324
348
|
significantDigits = significantDigits - 1;
|
|
325
349
|
}
|
|
326
350
|
}
|
|
@@ -331,7 +355,7 @@ export class Decimal128 extends BSONValue {
|
|
|
331
355
|
// to represent user input
|
|
332
356
|
|
|
333
357
|
// Overflow prevention
|
|
334
|
-
if (exponent <= radixPosition && radixPosition
|
|
358
|
+
if (exponent <= radixPosition && radixPosition > exponent + (1 << 14)) {
|
|
335
359
|
exponent = EXPONENT_MIN;
|
|
336
360
|
} else {
|
|
337
361
|
exponent = exponent - radixPosition;
|
|
@@ -341,11 +365,9 @@ export class Decimal128 extends BSONValue {
|
|
|
341
365
|
while (exponent > EXPONENT_MAX) {
|
|
342
366
|
// Shift exponent to significand and decrease
|
|
343
367
|
lastDigit = lastDigit + 1;
|
|
344
|
-
|
|
345
|
-
if (lastDigit - firstDigit > MAX_DIGITS) {
|
|
368
|
+
if (lastDigit >= MAX_DIGITS) {
|
|
346
369
|
// Check if we have a zero then just hard clamp, otherwise fail
|
|
347
|
-
|
|
348
|
-
if (digitsString.match(/^0+$/)) {
|
|
370
|
+
if (significantDigits === 0) {
|
|
349
371
|
exponent = EXPONENT_MAX;
|
|
350
372
|
break;
|
|
351
373
|
}
|
|
@@ -355,86 +377,146 @@ export class Decimal128 extends BSONValue {
|
|
|
355
377
|
exponent = exponent - 1;
|
|
356
378
|
}
|
|
357
379
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
380
|
+
if (options.allowRounding) {
|
|
381
|
+
while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
|
|
382
|
+
// Shift last digit. can only do this if < significant digits than # stored.
|
|
383
|
+
if (lastDigit === 0 && significantDigits < nDigitsStored) {
|
|
384
|
+
exponent = EXPONENT_MIN;
|
|
385
|
+
significantDigits = 0;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
365
388
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
389
|
+
if (nDigitsStored < nDigits) {
|
|
390
|
+
// adjust to match digits not stored
|
|
391
|
+
nDigits = nDigits - 1;
|
|
392
|
+
} else {
|
|
393
|
+
// adjust to round
|
|
394
|
+
lastDigit = lastDigit - 1;
|
|
395
|
+
}
|
|
373
396
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
397
|
+
if (exponent < EXPONENT_MAX) {
|
|
398
|
+
exponent = exponent + 1;
|
|
399
|
+
} else {
|
|
400
|
+
// Check if we have a zero then just hard clamp, otherwise fail
|
|
401
|
+
const digitsString = digits.join('');
|
|
402
|
+
if (digitsString.match(/^0+$/)) {
|
|
403
|
+
exponent = EXPONENT_MAX;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
invalidErr(representation, 'overflow');
|
|
382
407
|
}
|
|
383
|
-
invalidErr(representation, 'overflow');
|
|
384
408
|
}
|
|
385
|
-
}
|
|
386
409
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
410
|
+
// Round
|
|
411
|
+
// We've normalized the exponent, but might still need to round.
|
|
412
|
+
if (lastDigit + 1 < significantDigits) {
|
|
413
|
+
let endOfString = nDigitsRead;
|
|
414
|
+
|
|
415
|
+
// If we have seen a radix point, 'string' is 1 longer than we have
|
|
416
|
+
// documented with ndigits_read, so inc the position of the first nonzero
|
|
417
|
+
// digit and the position that digits are read to.
|
|
418
|
+
if (sawRadix) {
|
|
419
|
+
firstNonZero = firstNonZero + 1;
|
|
420
|
+
endOfString = endOfString + 1;
|
|
421
|
+
}
|
|
422
|
+
// if negative, we need to increment again to account for - sign at start.
|
|
423
|
+
if (sawSign) {
|
|
424
|
+
firstNonZero = firstNonZero + 1;
|
|
425
|
+
endOfString = endOfString + 1;
|
|
426
|
+
}
|
|
404
427
|
|
|
405
|
-
|
|
406
|
-
|
|
428
|
+
const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
|
|
429
|
+
let roundBit = 0;
|
|
430
|
+
|
|
431
|
+
if (roundDigit >= 5) {
|
|
432
|
+
roundBit = 1;
|
|
433
|
+
if (roundDigit === 5) {
|
|
434
|
+
roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
|
|
435
|
+
for (let i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
|
|
436
|
+
if (parseInt(representation[i], 10)) {
|
|
437
|
+
roundBit = 1;
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
407
443
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
444
|
+
if (roundBit) {
|
|
445
|
+
let dIdx = lastDigit;
|
|
446
|
+
|
|
447
|
+
for (; dIdx >= 0; dIdx--) {
|
|
448
|
+
if (++digits[dIdx] > 9) {
|
|
449
|
+
digits[dIdx] = 0;
|
|
450
|
+
|
|
451
|
+
// overflowed most significant digit
|
|
452
|
+
if (dIdx === 0) {
|
|
453
|
+
if (exponent < EXPONENT_MAX) {
|
|
454
|
+
exponent = exponent + 1;
|
|
455
|
+
digits[dIdx] = 1;
|
|
456
|
+
} else {
|
|
457
|
+
return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
415
461
|
break;
|
|
416
462
|
}
|
|
417
463
|
}
|
|
418
464
|
}
|
|
419
465
|
}
|
|
466
|
+
} else {
|
|
467
|
+
while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
|
|
468
|
+
// Shift last digit. can only do this if < significant digits than # stored.
|
|
469
|
+
if (lastDigit === 0) {
|
|
470
|
+
if (significantDigits === 0) {
|
|
471
|
+
exponent = EXPONENT_MIN;
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
420
474
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
for (; dIdx >= 0; dIdx--) {
|
|
425
|
-
if (++digits[dIdx] > 9) {
|
|
426
|
-
digits[dIdx] = 0;
|
|
475
|
+
invalidErr(representation, 'exponent underflow');
|
|
476
|
+
}
|
|
427
477
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
478
|
+
if (nDigitsStored < nDigits) {
|
|
479
|
+
if (
|
|
480
|
+
representation[nDigits - 1 + Number(sawSign) + Number(sawRadix)] !== '0' &&
|
|
481
|
+
significantDigits !== 0
|
|
482
|
+
) {
|
|
483
|
+
invalidErr(representation, 'inexact rounding');
|
|
437
484
|
}
|
|
485
|
+
// adjust to match digits not stored
|
|
486
|
+
nDigits = nDigits - 1;
|
|
487
|
+
} else {
|
|
488
|
+
if (digits[lastDigit] !== 0) {
|
|
489
|
+
invalidErr(representation, 'inexact rounding');
|
|
490
|
+
}
|
|
491
|
+
// adjust to round
|
|
492
|
+
lastDigit = lastDigit - 1;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (exponent < EXPONENT_MAX) {
|
|
496
|
+
exponent = exponent + 1;
|
|
497
|
+
} else {
|
|
498
|
+
invalidErr(representation, 'overflow');
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Round
|
|
503
|
+
// We've normalized the exponent, but might still need to round.
|
|
504
|
+
if (lastDigit + 1 < significantDigits) {
|
|
505
|
+
// If we have seen a radix point, 'string' is 1 longer than we have
|
|
506
|
+
// documented with ndigits_read, so inc the position of the first nonzero
|
|
507
|
+
// digit and the position that digits are read to.
|
|
508
|
+
if (sawRadix) {
|
|
509
|
+
firstNonZero = firstNonZero + 1;
|
|
510
|
+
}
|
|
511
|
+
// if saw sign, we need to increment again to account for - or + sign at start.
|
|
512
|
+
if (sawSign) {
|
|
513
|
+
firstNonZero = firstNonZero + 1;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
|
|
517
|
+
|
|
518
|
+
if (roundDigit !== 0) {
|
|
519
|
+
invalidErr(representation, 'inexact rounding');
|
|
438
520
|
}
|
|
439
521
|
}
|
|
440
522
|
}
|
|
@@ -449,8 +531,8 @@ export class Decimal128 extends BSONValue {
|
|
|
449
531
|
if (significantDigits === 0) {
|
|
450
532
|
significandHigh = Long.fromNumber(0);
|
|
451
533
|
significandLow = Long.fromNumber(0);
|
|
452
|
-
} else if (lastDigit
|
|
453
|
-
let dIdx =
|
|
534
|
+
} else if (lastDigit < 17) {
|
|
535
|
+
let dIdx = 0;
|
|
454
536
|
significandLow = Long.fromNumber(digits[dIdx++]);
|
|
455
537
|
significandHigh = new Long(0, 0);
|
|
456
538
|
|
|
@@ -459,7 +541,7 @@ export class Decimal128 extends BSONValue {
|
|
|
459
541
|
significandLow = significandLow.add(Long.fromNumber(digits[dIdx]));
|
|
460
542
|
}
|
|
461
543
|
} else {
|
|
462
|
-
let dIdx =
|
|
544
|
+
let dIdx = 0;
|
|
463
545
|
significandHigh = Long.fromNumber(digits[dIdx++]);
|
|
464
546
|
|
|
465
547
|
for (; dIdx <= lastDigit - 17; dIdx++) {
|
|
@@ -539,7 +621,6 @@ export class Decimal128 extends BSONValue {
|
|
|
539
621
|
// Return the new Decimal128
|
|
540
622
|
return new Decimal128(buffer);
|
|
541
623
|
}
|
|
542
|
-
|
|
543
624
|
/** Create a string representation of the raw Decimal128 value */
|
|
544
625
|
toString(): string {
|
|
545
626
|
// Note: bits in this routine are referred to starting at 0,
|
|
@@ -2,7 +2,7 @@ import { Binary, UUID } from '../binary';
|
|
|
2
2
|
import type { Document } from '../bson';
|
|
3
3
|
import { Code } from '../code';
|
|
4
4
|
import * as constants from '../constants';
|
|
5
|
-
import { DBRef, DBRefLike, isDBRefLike } from '../db_ref';
|
|
5
|
+
import { DBRef, type DBRefLike, isDBRefLike } from '../db_ref';
|
|
6
6
|
import { Decimal128 } from '../decimal128';
|
|
7
7
|
import { Double } from '../double';
|
|
8
8
|
import { BSONError } from '../error';
|
|
@@ -236,7 +236,7 @@ function deserializeObject(
|
|
|
236
236
|
if (i >= buffer.byteLength) throw new BSONError('Bad BSON Document: illegal CString');
|
|
237
237
|
|
|
238
238
|
// Represents the key
|
|
239
|
-
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer
|
|
239
|
+
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
|
|
240
240
|
|
|
241
241
|
// shouldValidateKey is true if the key should be validated, false otherwise
|
|
242
242
|
let shouldValidateKey = true;
|
|
@@ -476,7 +476,7 @@ function deserializeObject(
|
|
|
476
476
|
// If are at the end of the buffer there is a problem with the document
|
|
477
477
|
if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
|
|
478
478
|
// Return the C string
|
|
479
|
-
const source = ByteUtils.toUTF8(buffer
|
|
479
|
+
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
480
480
|
// Create the regexp
|
|
481
481
|
index = i + 1;
|
|
482
482
|
|
|
@@ -489,7 +489,7 @@ function deserializeObject(
|
|
|
489
489
|
// If are at the end of the buffer there is a problem with the document
|
|
490
490
|
if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
|
|
491
491
|
// Return the C string
|
|
492
|
-
const regExpOptions = ByteUtils.toUTF8(buffer
|
|
492
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
493
493
|
index = i + 1;
|
|
494
494
|
|
|
495
495
|
// For each option add the corresponding one for javascript
|
|
@@ -521,7 +521,7 @@ function deserializeObject(
|
|
|
521
521
|
// If are at the end of the buffer there is a problem with the document
|
|
522
522
|
if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
|
|
523
523
|
// Return the C string
|
|
524
|
-
const source = ByteUtils.toUTF8(buffer
|
|
524
|
+
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
525
525
|
index = i + 1;
|
|
526
526
|
|
|
527
527
|
// Get the start search index
|
|
@@ -533,7 +533,7 @@ function deserializeObject(
|
|
|
533
533
|
// If are at the end of the buffer there is a problem with the document
|
|
534
534
|
if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
|
|
535
535
|
// Return the C string
|
|
536
|
-
const regExpOptions = ByteUtils.toUTF8(buffer
|
|
536
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
537
537
|
index = i + 1;
|
|
538
538
|
|
|
539
539
|
// Set the object
|
|
@@ -678,7 +678,7 @@ function deserializeObject(
|
|
|
678
678
|
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
-
const namespace = ByteUtils.toUTF8(buffer
|
|
681
|
+
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
|
|
682
682
|
// Update parse index position
|
|
683
683
|
index = index + stringSize;
|
|
684
684
|
|
|
@@ -735,7 +735,7 @@ function getValidatedString(
|
|
|
735
735
|
end: number,
|
|
736
736
|
shouldValidateUtf8: boolean
|
|
737
737
|
) {
|
|
738
|
-
const value = ByteUtils.toUTF8(buffer
|
|
738
|
+
const value = ByteUtils.toUTF8(buffer, start, end);
|
|
739
739
|
// if utf8 validation is on, do the check
|
|
740
740
|
if (shouldValidateUtf8) {
|
|
741
741
|
for (let i = 0; i < value.length; i++) {
|
package/src/timestamp.ts
CHANGED
|
@@ -61,24 +61,26 @@ export class Timestamp extends LongWithoutOverridesClass {
|
|
|
61
61
|
if (typeof low.i !== 'number' && (typeof low.i !== 'object' || low.i._bsontype !== 'Int32')) {
|
|
62
62
|
throw new BSONError('Timestamp constructed from { t, i } must provide i as a number');
|
|
63
63
|
}
|
|
64
|
-
|
|
64
|
+
const t = Number(low.t);
|
|
65
|
+
const i = Number(low.i);
|
|
66
|
+
if (t < 0 || Number.isNaN(t)) {
|
|
65
67
|
throw new BSONError('Timestamp constructed from { t, i } must provide a positive t');
|
|
66
68
|
}
|
|
67
|
-
if (
|
|
69
|
+
if (i < 0 || Number.isNaN(i)) {
|
|
68
70
|
throw new BSONError('Timestamp constructed from { t, i } must provide a positive i');
|
|
69
71
|
}
|
|
70
|
-
if (
|
|
72
|
+
if (t > 0xffff_ffff) {
|
|
71
73
|
throw new BSONError(
|
|
72
74
|
'Timestamp constructed from { t, i } must provide t equal or less than uint32 max'
|
|
73
75
|
);
|
|
74
76
|
}
|
|
75
|
-
if (
|
|
77
|
+
if (i > 0xffff_ffff) {
|
|
76
78
|
throw new BSONError(
|
|
77
79
|
'Timestamp constructed from { t, i } must provide i equal or less than uint32 max'
|
|
78
80
|
);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
super(
|
|
83
|
+
super(i, t, true);
|
|
82
84
|
} else {
|
|
83
85
|
throw new BSONError(
|
|
84
86
|
'A Timestamp can only be constructed with: bigint, Long, or { t: number; i: number }'
|
package/src/utils/byte_utils.ts
CHANGED
|
@@ -26,7 +26,7 @@ export type ByteUtils = {
|
|
|
26
26
|
/** Create a Uint8Array containing utf8 code units from a string */
|
|
27
27
|
fromUTF8: (text: string) => Uint8Array;
|
|
28
28
|
/** Create a string from utf8 code units */
|
|
29
|
-
toUTF8: (buffer: Uint8Array) => string;
|
|
29
|
+
toUTF8: (buffer: Uint8Array, start: number, end: number) => string;
|
|
30
30
|
/** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
|
|
31
31
|
utf8ByteLength: (input: string) => number;
|
|
32
32
|
/** Encode UTF8 bytes generated from `source` string into `destination` at byteOffset. Returns the number of bytes encoded. */
|
|
@@ -5,7 +5,7 @@ type NodeJsBuffer = ArrayBufferView &
|
|
|
5
5
|
Uint8Array & {
|
|
6
6
|
write(string: string, offset: number, length: undefined, encoding: 'utf8'): number;
|
|
7
7
|
copy(target: Uint8Array, targetStart: number, sourceStart: number, sourceEnd: number): number;
|
|
8
|
-
toString: (this: Uint8Array, encoding: NodeJsEncoding) => string;
|
|
8
|
+
toString: (this: Uint8Array, encoding: NodeJsEncoding, start?: number, end?: number) => string;
|
|
9
9
|
equals: (this: Uint8Array, other: Uint8Array) => boolean;
|
|
10
10
|
};
|
|
11
11
|
type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
|
|
@@ -125,8 +125,8 @@ export const nodeJsByteUtils = {
|
|
|
125
125
|
return Buffer.from(text, 'utf8');
|
|
126
126
|
},
|
|
127
127
|
|
|
128
|
-
toUTF8(buffer: Uint8Array): string {
|
|
129
|
-
return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8');
|
|
128
|
+
toUTF8(buffer: Uint8Array, start: number, end: number): string {
|
|
129
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
|
|
130
130
|
},
|
|
131
131
|
|
|
132
132
|
utf8ByteLength(input: string): number {
|
|
@@ -172,8 +172,8 @@ export const webByteUtils = {
|
|
|
172
172
|
return new TextEncoder().encode(text);
|
|
173
173
|
},
|
|
174
174
|
|
|
175
|
-
toUTF8(uint8array: Uint8Array): string {
|
|
176
|
-
return new TextDecoder('utf8', { fatal: false }).decode(uint8array);
|
|
175
|
+
toUTF8(uint8array: Uint8Array, start: number, end: number): string {
|
|
176
|
+
return new TextDecoder('utf8', { fatal: false }).decode(uint8array.slice(start, end));
|
|
177
177
|
},
|
|
178
178
|
|
|
179
179
|
utf8ByteLength(input: string): number {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# base64 [](https://travis-ci.org/mathiasbynens/base64) [](https://coveralls.io/r/mathiasbynens/base64)
|
|
2
|
+
|
|
3
|
+
_base64_ is a robust base64 encoder/decoder that is fully compatible with [`atob()` and `btoa()`](https://html.spec.whatwg.org/multipage/webappapis.html#atob), written in JavaScript. The base64-encoding and -decoding algorithms it uses are fully [RFC 4648](https://tools.ietf.org/html/rfc4648#section-4) compliant.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Via [npm](https://www.npmjs.com/):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install base-64
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
In a browser:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script src="base64.js"></script>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
In [Narwhal](http://narwhaljs.org/), [Node.js](https://nodejs.org/), and [RingoJS](http://ringojs.org/):
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
var base64 = require('base-64');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
In [Rhino](http://www.mozilla.org/rhino/):
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
load('base64.js');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Using an AMD loader like [RequireJS](http://requirejs.org/):
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
require(
|
|
35
|
+
{
|
|
36
|
+
'paths': {
|
|
37
|
+
'base64': 'path/to/base64'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
['base64'],
|
|
41
|
+
function(base64) {
|
|
42
|
+
console.log(base64);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### `base64.version`
|
|
50
|
+
|
|
51
|
+
A string representing the semantic version number.
|
|
52
|
+
|
|
53
|
+
### `base64.encode(input)`
|
|
54
|
+
|
|
55
|
+
This function takes a byte string (the `input` parameter) and encodes it according to base64. The input data must be in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values `0x00` to `0xFF`. The `base64.encode()` function is designed to be fully compatible with [`btoa()` as described in the HTML Standard](https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-btoa).
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
var encodedData = base64.encode(input);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To base64-encode any Unicode string, [encode it as UTF-8 first](https://github.com/mathiasbynens/utf8.js#utf8encodestring):
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
var base64 = require('base-64');
|
|
65
|
+
var utf8 = require('utf8');
|
|
66
|
+
|
|
67
|
+
var text = 'foo Β© bar π baz';
|
|
68
|
+
var bytes = utf8.encode(text);
|
|
69
|
+
var encoded = base64.encode(bytes);
|
|
70
|
+
console.log(encoded);
|
|
71
|
+
// β 'Zm9vIMKpIGJhciDwnYyGIGJheg=='
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `base64.decode(input)`
|
|
75
|
+
|
|
76
|
+
This function takes a base64-encoded string (the `input` parameter) and decodes it. The return value is in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values `0x00` to `0xFF`. The `base64.decode()` function is designed to be fully compatible with [`atob()` as described in the HTML Standard](https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-atob).
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
var decodedData = base64.decode(encodedData);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To base64-decode UTF-8-encoded data back into a Unicode string, [UTF-8-decode it](https://github.com/mathiasbynens/utf8.js#utf8decodebytestring) after base64-decoding it:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
var encoded = 'Zm9vIMKpIGJhciDwnYyGIGJheg==';
|
|
86
|
+
var bytes = base64.decode(encoded);
|
|
87
|
+
var text = utf8.decode(bytes);
|
|
88
|
+
console.log(text);
|
|
89
|
+
// β 'foo Β© bar π baz'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Support
|
|
93
|
+
|
|
94
|
+
_base64_ is designed to work in at least Node.js v0.10.0, Narwhal 0.3.2, RingoJS 0.8-0.9, PhantomJS 1.9.0, Rhino 1.7RC4, as well as old and modern versions of Chrome, Firefox, Safari, Opera, and Internet Explorer.
|
|
95
|
+
|
|
96
|
+
## Unit tests & code coverage
|
|
97
|
+
|
|
98
|
+
After cloning this repository, run `npm install` to install the dependencies needed for development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
|
|
99
|
+
|
|
100
|
+
Once thatβs done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use `grunt test`.
|
|
101
|
+
|
|
102
|
+
To generate the code coverage report, use `grunt cover`.
|
|
103
|
+
|
|
104
|
+
## Author
|
|
105
|
+
|
|
106
|
+
| [](https://twitter.com/mathias "Follow @mathias on Twitter") |
|
|
107
|
+
|---|
|
|
108
|
+
| [Mathias Bynens](https://mathiasbynens.be/) |
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
_base64_ is available under the [MIT](https://mths.be/mit) license.
|