1+ import {
2+ type Binary ,
3+ type BSONRegExp ,
4+ type BSONSymbol ,
5+ type Code ,
6+ type DBRef ,
7+ type Decimal128 ,
8+ type Double ,
9+ type Int32 ,
10+ type Long ,
11+ type MaxKey ,
12+ type MinKey ,
13+ type Timestamp
14+ } from 'bson' ;
115import { inspect , promisify } from 'util' ;
216import { isUint8Array } from 'util/types' ;
317
@@ -414,6 +428,20 @@ export interface LogConvertible extends Record<string, any> {
414428 toLog ( ) : Record < string , any > ;
415429}
416430
431+ type BSONObject =
432+ | BSONRegExp
433+ | BSONSymbol
434+ | Code
435+ | DBRef
436+ | Decimal128
437+ | Double
438+ | Int32
439+ | Long
440+ | MaxKey
441+ | MinKey
442+ | ObjectId
443+ | Timestamp
444+ | Binary ;
417445/** @internal */
418446export function stringifyWithMaxLen (
419447 value : any ,
@@ -432,36 +460,74 @@ export function stringifyWithMaxLen(
432460
433461 if ( typeof value === 'string' ) {
434462 currentLength += value . length ;
435- } else if ( typeof value === 'number' && Number . isInteger ( value ) ) {
436- currentLength += Math . ceil ( Math . log10 ( value ) ) ;
437463 } else if ( typeof value === 'number' || typeof value === 'bigint' ) {
438464 currentLength += String ( value ) . length ;
439465 } else if ( typeof value === 'boolean' ) {
440466 currentLength += value ? 4 : 5 ;
467+ } else if ( 'buffer' in value && isUint8Array ( value . buffer ) ) {
468+ // Handle binData
469+ currentLength += ( value . buffer . byteLength + value . buffer . byteLength * 0.5 ) | 0 ;
441470 } else if ( value != null && typeof value === 'object' && '_bsontype' in value ) {
442- if ( isUint8Array ( value . buffer ) ) {
443- currentLength += ( value . buffer . byteLength + value . buffer . byteLength * 0.5 ) | 0 ;
444- } else if ( value . _bsontype === 'Binary' ) {
445- currentLength += ( value . position + value . position * 0.3 ) | 0 ;
446- } else if ( value . _bsontype === 'Code' ) {
447- currentLength += value . code . length ;
448- } else if ( value . _bsontype === 'Decimal128' ) {
449- } else if ( value . _bsontype === 'Double' ) {
450- if ( 'value' in value ) currentLength += String ( value . value ) . length ;
451- } else if ( value . _bsontype === 'Int32' ) {
452- if ( 'value' in value ) currentLength += String ( value . value ) . length ;
453- } else if ( value . _bsontype === 'Long' ) {
454- currentLength += value . toString ;
455- } else if ( value . _bsontype === 'MaxKey' ) {
456- currentLength += 13 ;
457- } else if ( value . _bsontype === 'MinKey' ) {
471+ const v = value as BSONObject ;
472+ if ( v . _bsontype === 'Binary' ) {
473+ // This is an estimate based on the fact that the base64 is approximately 1.3x the length of
474+ // the actual binary sequence
475+ // Also accounting for stringified fields before the binary sequence and the fields after
476+ // the binary sequence
477+ currentLength += ( value . position + value . position * 0.3 + 22 + 17 ) | 0 ;
478+ } else if ( v . _bsontype === 'Code' ) {
479+ // TODO: Account for scope?
480+ currentLength += v . code . length + 10 + 12 + 3 ;
481+ } else if ( v . _bsontype === 'Decimal128' ) {
482+ // TODO: Is this worth doing here?
483+ currentLength += value . toExtendedJSON ( ) . length ;
484+ } else if ( v . _bsontype === 'Double' ) {
485+ if ( 'value' in v && typeof v . value === 'number' ) currentLength += String ( v . value ) . length ;
486+ } else if ( v . _bsontype === 'Int32' ) {
487+ if ( 'value' in v && typeof v . value === 'number' ) currentLength += String ( v . value ) . length ;
488+ } else if ( v . _bsontype === 'Long' ) {
489+ if ( 'toString' in v && typeof v . toString === 'function' ) {
490+ currentLength += v . toString ( ) . length ;
491+ }
492+ } else if ( v . _bsontype === 'MaxKey' || v . _bsontype === 'MinKey' ) {
458493 currentLength += 13 ;
459- } else if ( value . _bsontype === 'ObjectId' ) {
494+ } else if ( v . _bsontype === 'ObjectId' ) {
460495 currentLength += 35 ;
461- } else if ( value . _bsontype === 'BSONRegExp' ) {
462- } else if ( value . _bsontype === 'BSONSymbol' ) {
463- } else if ( value . _bsontype === 'Timestamp' ) {
464- } else if ( value . _bsontype === 'DBRef' ) {
496+ } else if (
497+ v . _bsontype === 'BSONRegExp' &&
498+ 'pattern' in v &&
499+ typeof v . pattern === 'string' &&
500+ 'options' in v &&
501+ typeof v . options === 'string'
502+ ) {
503+ currentLength += 34 + v . pattern . length + 14 + v . options . length ;
504+ } else if ( v . _bsontype === 'BSONSymbol' && 'value' in v && v . value === 'string' ) {
505+ currentLength += 12 + v . value . length + 2 ;
506+ } else if (
507+ v . _bsontype === 'Timestamp' &&
508+ 't' in v &&
509+ typeof v . t === 'string' &&
510+ 'i' in v &&
511+ typeof v . i === 'string'
512+ ) {
513+ currentLength += 19 + String ( v . t ) . length + 5 + String ( v . i ) . length + 2 ;
514+ } else if ( v . _bsontype === 'DBRef' ) {
515+ // account for $ref
516+ currentLength += 9 ;
517+ // account for collection
518+ if ( 'collection' in v ) {
519+ currentLength += v . collection . length + 1 ;
520+ }
521+
522+ // account for db if present
523+ if ( 'db' in v ) {
524+ currentLength += 8 + v . db ?. length + 2 ;
525+ }
526+
527+ // account for oid if present
528+ if ( 'oid' in v ) {
529+ currentLength += 35 ;
530+ }
465531 } else {
466532 }
467533 }
0 commit comments