11import { ExtensionCodecType } from "./ExtensionCodec" ;
2- import { Decoder , State } from "./Decoder" ;
3- import { utf8DecodeJs } from "./utils/utf8" ;
2+ import { Decoder } from "./Decoder" ;
43
54export type DecodeOptions = Partial <
65 Readonly < {
@@ -36,133 +35,6 @@ export type DecodeOptions = Partial<
3635
3736export const defaultDecodeOptions : DecodeOptions = { } ;
3837
39- interface KeyCacheRecord {
40- readonly bytes : Uint8Array ;
41- readonly key : string ;
42- hits : number ;
43- }
44-
45- class CachedKeyDecoder {
46- private readonly caches : Array < Array < KeyCacheRecord > > ;
47-
48- constructor ( private readonly maxKeyLength : number = 32 ) {
49- this . caches = new Array < Array < KeyCacheRecord > > ( this . maxKeyLength + 1 ) ;
50- }
51-
52- public get ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string | null {
53- const chunks = this . caches [ byteLength ] ;
54-
55- if ( chunks ) {
56- return this . findKey ( bytes , inputOffset , byteLength , chunks ) ;
57- } else {
58- return null ;
59- }
60- }
61-
62- private findKey (
63- bytes : Uint8Array ,
64- inputOffset : number ,
65- byteLength : number ,
66- chunks : Array < KeyCacheRecord > ,
67- ) : string | null {
68- let prevHits = 0 ;
69- const chunksLength = chunks . length ;
70- const halfLength = byteLength / 2 ;
71- const endPosition = inputOffset + byteLength ;
72- FIND_CHUNK: for ( let i = 0 ; i < chunksLength ; i ++ ) {
73- const chunk = chunks [ i ] ;
74-
75- if ( i > 0 && prevHits < chunk . hits ) {
76- // Sort chunks by number of hits
77- // in order to improve search speed for most used keys
78- const prevChunk = chunks [ i - 1 ] ;
79- chunks [ i ] = prevChunk ;
80- chunks [ i - 1 ] = chunk ;
81- prevHits = prevChunk . hits ;
82- } else {
83- prevHits = chunk . hits ;
84- }
85-
86- for ( let j = 0 ; j < halfLength ; j ++ ) {
87- if ( chunk . bytes [ j ] !== bytes [ inputOffset + j ] ) {
88- continue FIND_CHUNK;
89- }
90-
91- if ( chunk . bytes [ byteLength - j - 1 ] !== bytes [ endPosition - j - 1 ] ) {
92- continue FIND_CHUNK;
93- }
94- }
95-
96- chunk . hits ++ ;
97-
98- return chunk . key ;
99- }
100-
101- return null ;
102- }
103-
104- public cache ( bytes : Uint8Array , value : string ) {
105- let chunks : Array < KeyCacheRecord > = this . caches [ bytes . length ] ;
106-
107- if ( ! chunks ) {
108- chunks = [ ] ;
109- this . caches [ bytes . length ] = chunks ;
110- }
111-
112- chunks . push ( {
113- bytes : bytes ,
114- key : value ,
115- hits : 1 ,
116- } ) ;
117- }
118-
119- public decode ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string {
120- let value = this . get ( bytes , inputOffset , byteLength ) ;
121-
122- if ( ! value ) {
123- value = utf8DecodeJs ( bytes , inputOffset , byteLength ) ;
124- const stringsBytes = bytes . slice ( inputOffset , inputOffset + byteLength ) ;
125- this . cache ( stringsBytes , value ) ;
126- }
127-
128- return value ;
129- }
130- }
131-
132- class CustomDecoder extends Decoder {
133- private readonly maxCachedKeyLength = 32 ;
134- public cachedKeyDecoder = new CachedKeyDecoder ( this . maxCachedKeyLength ) ;
135-
136- public decodeUtf8String ( byteLength : number , headerOffset : number ) : string {
137- let isKey = false ;
138- const canBeDecodedAsKey = byteLength > 0 && byteLength < this . maxCachedKeyLength ;
139-
140- if ( canBeDecodedAsKey && this . stack . length > 0 ) {
141- const state = this . stack [ this . stack . length - 1 ] ;
142-
143- isKey = state . type === State . MAP_KEY ;
144- }
145-
146- if ( isKey && canBeDecodedAsKey ) {
147- const offset = this . pos + headerOffset ;
148- const value = this . cachedKeyDecoder . decode ( this . bytes , offset , byteLength ) ;
149- this . pos += headerOffset + byteLength ;
150- return value ;
151- } else {
152- return super . decodeUtf8String ( byteLength , headerOffset ) ;
153- }
154- }
155- }
156-
157- const sharedDecoder = new CustomDecoder (
158- defaultDecodeOptions . extensionCodec ,
159- defaultDecodeOptions . maxStrLength ,
160- defaultDecodeOptions . maxBinLength ,
161- defaultDecodeOptions . maxArrayLength ,
162- defaultDecodeOptions . maxMapLength ,
163- defaultDecodeOptions . maxExtLength ,
164- ) ;
165-
16638/**
16739 * It decodes a MessagePack-encoded buffer.
16840 *
@@ -172,18 +44,14 @@ export function decode(
17244 buffer : ArrayLike < number > | ArrayBuffer ,
17345 options : DecodeOptions = defaultDecodeOptions ,
17446) : unknown {
175- const decoder =
176- options === defaultDecodeOptions
177- ? sharedDecoder
178- : new CustomDecoder (
179- options . extensionCodec ,
180- options . maxStrLength ,
181- options . maxBinLength ,
182- options . maxArrayLength ,
183- options . maxMapLength ,
184- options . maxExtLength ,
185- ) ;
186-
47+ const decoder = new Decoder (
48+ options . extensionCodec ,
49+ options . maxStrLength ,
50+ options . maxBinLength ,
51+ options . maxArrayLength ,
52+ options . maxMapLength ,
53+ options . maxExtLength ,
54+ ) ;
18755 decoder . setBuffer ( buffer ) ; // decodeSync() requires only one buffer
18856 return decoder . decodeOneSync ( ) ;
18957}
0 commit comments