@@ -297,7 +297,19 @@ export class Encoder<ContextType = undefined> {
297
297
if ( ext != null ) {
298
298
this . encodeExtension ( ext ) ;
299
299
} else if ( Array . isArray ( object ) ) {
300
- this . encodeArray ( object , depth ) ;
300
+ // We need to peek the first element to determine if it's an array or a map.
301
+ const firstElement = object [ 0 ] ;
302
+
303
+ if (
304
+ firstElement != null &&
305
+ typeof firstElement === "object" &&
306
+ "key" in firstElement &&
307
+ "value" in firstElement
308
+ ) {
309
+ this . encodeMapArray ( object as [ { key : string | number ; value : unknown } ] , depth ) ;
310
+ } else {
311
+ this . encodeArray ( object , depth ) ;
312
+ }
301
313
} else if ( ArrayBuffer . isView ( object ) ) {
302
314
this . encodeBinary ( object ) ;
303
315
} else if ( typeof object === "object" ) {
@@ -350,18 +362,6 @@ export class Encoder<ContextType = undefined> {
350
362
}
351
363
}
352
364
353
- private countWithoutUndefined ( object : Record < string , unknown > , keys : ReadonlyArray < string > ) : number {
354
- let count = 0 ;
355
-
356
- for ( const key of keys ) {
357
- if ( object [ key ] !== undefined ) {
358
- count ++ ;
359
- }
360
- }
361
-
362
- return count ;
363
- }
364
-
365
365
private encodeMap ( object : Record < string , unknown > , depth : number ) {
366
366
const keys = Object . keys ( object ) ;
367
367
if ( this . sortKeys ) {
@@ -395,6 +395,39 @@ export class Encoder<ContextType = undefined> {
395
395
}
396
396
}
397
397
398
+ private encodeMapArray ( object : [ { key : string | number ; value : unknown } ] , depth : number ) {
399
+ const keys = object . map ( ( pair ) => pair . key ) ;
400
+ if ( this . sortKeys ) {
401
+ keys . sort ( ) ;
402
+ }
403
+
404
+ const size = keys . length ;
405
+
406
+ if ( size < 16 ) {
407
+ // fixmap
408
+ this . writeU8 ( 0x80 + size ) ;
409
+ } else if ( size < 0x10000 ) {
410
+ // map 16
411
+ this . writeU8 ( 0xde ) ;
412
+ this . writeU16 ( size ) ;
413
+ } else if ( size < 0x100000000 ) {
414
+ // map 32
415
+ this . writeU8 ( 0xdf ) ;
416
+ this . writeU32 ( size ) ;
417
+ } else {
418
+ throw new Error ( `Too large map object: ${ size } ` ) ;
419
+ }
420
+
421
+ for ( const pair of object ) {
422
+ const value = pair . value ;
423
+
424
+ if ( ! ( this . ignoreUndefined && value === undefined ) ) {
425
+ this . encodeString ( pair . key . toString ( ) ) ;
426
+ this . doEncode ( value , depth + 1 ) ;
427
+ }
428
+ }
429
+ }
430
+
398
431
private encodeExtension ( ext : ExtData ) {
399
432
const size = ext . data . length ;
400
433
if ( size === 1 ) {
0 commit comments