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.
Files changed (69) hide show
  1. package/README.md +4 -11
  2. package/bson.d.ts +20 -0
  3. package/lib/bson.bundle.js +137 -86
  4. package/lib/bson.bundle.js.map +1 -1
  5. package/lib/bson.cjs +137 -86
  6. package/lib/bson.cjs.map +1 -1
  7. package/lib/bson.mjs +137 -86
  8. package/lib/bson.mjs.map +1 -1
  9. package/lib/bson.rn.cjs +4159 -0
  10. package/lib/bson.rn.cjs.map +1 -0
  11. package/package.json +8 -7
  12. package/src/binary.ts +3 -2
  13. package/src/bson.ts +2 -2
  14. package/src/decimal128.ts +165 -84
  15. package/src/parser/deserializer.ts +8 -8
  16. package/src/timestamp.ts +7 -5
  17. package/src/utils/byte_utils.ts +1 -1
  18. package/src/utils/node_byte_utils.ts +3 -3
  19. package/src/utils/web_byte_utils.ts +2 -2
  20. package/vendor/base64/LICENSE-MIT.txt +20 -0
  21. package/vendor/base64/README.md +112 -0
  22. package/vendor/base64/base64.js +157 -0
  23. package/vendor/base64/package.json +43 -0
  24. package/vendor/text-encoding/LICENSE.md +237 -0
  25. package/vendor/text-encoding/README.md +111 -0
  26. package/vendor/text-encoding/index.js +9 -0
  27. package/vendor/text-encoding/lib/encoding-indexes.js +47 -0
  28. package/vendor/text-encoding/lib/encoding.js +3301 -0
  29. package/vendor/text-encoding/package.json +37 -0
  30. package/lib/binary.d.ts +0 -182
  31. package/lib/binary.d.ts.map +0 -1
  32. package/lib/bson.d.ts +0 -97
  33. package/lib/bson.d.ts.map +0 -1
  34. package/lib/bson_value.d.ts +0 -10
  35. package/lib/bson_value.d.ts.map +0 -1
  36. package/lib/code.d.ts +0 -32
  37. package/lib/code.d.ts.map +0 -1
  38. package/lib/constants.d.ts +0 -107
  39. package/lib/constants.d.ts.map +0 -1
  40. package/lib/db_ref.d.ts +0 -40
  41. package/lib/db_ref.d.ts.map +0 -1
  42. package/lib/decimal128.d.ts +0 -34
  43. package/lib/decimal128.d.ts.map +0 -1
  44. package/lib/double.d.ts +0 -35
  45. package/lib/double.d.ts.map +0 -1
  46. package/lib/error.d.ts +0 -50
  47. package/lib/error.d.ts.map +0 -1
  48. package/lib/extended_json.d.ts +0 -82
  49. package/lib/extended_json.d.ts.map +0 -1
  50. package/lib/index.d.ts +0 -4
  51. package/lib/index.d.ts.map +0 -1
  52. package/lib/int_32.d.ts +0 -35
  53. package/lib/int_32.d.ts.map +0 -1
  54. package/lib/long.d.ts +0 -323
  55. package/lib/long.d.ts.map +0 -1
  56. package/lib/max_key.d.ts +0 -19
  57. package/lib/max_key.d.ts.map +0 -1
  58. package/lib/min_key.d.ts +0 -19
  59. package/lib/min_key.d.ts.map +0 -1
  60. package/lib/objectid.d.ts +0 -96
  61. package/lib/objectid.d.ts.map +0 -1
  62. package/lib/regexp.d.ts +0 -36
  63. package/lib/regexp.d.ts.map +0 -1
  64. package/lib/symbol.d.ts +0 -28
  65. package/lib/symbol.d.ts.map +0 -1
  66. package/lib/timestamp.d.ts +0 -66
  67. package/lib/timestamp.d.ts.map +0 -1
  68. package/lib/validate_utf8.d.ts +0 -10
  69. 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 < 34) {
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 (digits[firstNonZero + significantDigits - 1] === 0) {
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 - exponent > 1 << 14) {
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
- const digitsString = digits.join('');
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
- while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
359
- // Shift last digit. can only do this if < significant digits than # stored.
360
- if (lastDigit === 0 && significantDigits < nDigitsStored) {
361
- exponent = EXPONENT_MIN;
362
- significantDigits = 0;
363
- break;
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
- if (nDigitsStored < nDigits) {
367
- // adjust to match digits not stored
368
- nDigits = nDigits - 1;
369
- } else {
370
- // adjust to round
371
- lastDigit = lastDigit - 1;
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
- if (exponent < EXPONENT_MAX) {
375
- exponent = exponent + 1;
376
- } else {
377
- // Check if we have a zero then just hard clamp, otherwise fail
378
- const digitsString = digits.join('');
379
- if (digitsString.match(/^0+$/)) {
380
- exponent = EXPONENT_MAX;
381
- break;
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
- // Round
388
- // We've normalized the exponent, but might still need to round.
389
- if (lastDigit - firstDigit + 1 < significantDigits) {
390
- let endOfString = nDigitsRead;
391
-
392
- // If we have seen a radix point, 'string' is 1 longer than we have
393
- // documented with ndigits_read, so inc the position of the first nonzero
394
- // digit and the position that digits are read to.
395
- if (sawRadix) {
396
- firstNonZero = firstNonZero + 1;
397
- endOfString = endOfString + 1;
398
- }
399
- // if negative, we need to increment again to account for - sign at start.
400
- if (isNegative) {
401
- firstNonZero = firstNonZero + 1;
402
- endOfString = endOfString + 1;
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
- const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
406
- let roundBit = 0;
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
- if (roundDigit >= 5) {
409
- roundBit = 1;
410
- if (roundDigit === 5) {
411
- roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
412
- for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
413
- if (parseInt(representation[i], 10)) {
414
- roundBit = 1;
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
- if (roundBit) {
422
- let dIdx = lastDigit;
423
-
424
- for (; dIdx >= 0; dIdx--) {
425
- if (++digits[dIdx] > 9) {
426
- digits[dIdx] = 0;
475
+ invalidErr(representation, 'exponent underflow');
476
+ }
427
477
 
428
- // overflowed most significant digit
429
- if (dIdx === 0) {
430
- if (exponent < EXPONENT_MAX) {
431
- exponent = exponent + 1;
432
- digits[dIdx] = 1;
433
- } else {
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 - firstDigit < 17) {
453
- let dIdx = firstDigit;
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 = firstDigit;
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.subarray(index, i));
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.subarray(index, i));
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.subarray(index, i));
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.subarray(index, i));
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.subarray(index, i));
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.subarray(index, index + stringSize - 1));
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.subarray(start, end));
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
- if (low.t < 0) {
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 (low.i < 0) {
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 (low.t > 0xffff_ffff) {
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 (low.i > 0xffff_ffff) {
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(low.i.valueOf(), low.t.valueOf(), true);
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 }'
@@ -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 [![Build status](https://travis-ci.org/mathiasbynens/base64.svg?branch=master)](https://travis-ci.org/mathiasbynens/base64) [![Code coverage status](http://img.shields.io/coveralls/mathiasbynens/base64/master.svg)](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
+ | [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](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.