@@ -62,40 +62,56 @@ function chain<T extends Chain & AsChain<T>>(...args: T): Coder<Input<First<T>>,
6262 return { encode, decode } ;
6363}
6464
65+ // Their length (number of non-default args) is 0 per spec, which native engines follow
66+ // Slow text-encoding polyfill that we want to avoid has length = 2
67+ const nativeDecoder = globalThis . TextDecoder && globalThis . TextDecoder . length === 0 ? new TextDecoder ( ) : null ;
68+
6569/**
6670 * Encodes integer radix representation in Uint8Array to a string in alphabet and back, with optional padding
6771 * @__NO_SIDE_EFFECTS__
6872 */
6973function alphabet ( letters : string , paddingBits : number = 0 , paddingChr = '=' ) : Coder < Uint8Array , string > {
7074 // mapping 1 to "b"
7175 astr ( 'alphabet' , letters ) ;
72- const lettersA = letters . split ( '' ) ;
73- const len = lettersA . length ;
76+ const letterChars = letters . split ( '' ) ;
77+ const len = letterChars . length ;
7478 const paddingCode = paddingChr . codePointAt ( 0 ) ! ;
7579 if ( paddingChr . length !== 1 || paddingCode > 128 ) throw new Error ( 'Wrong padding char' ) ;
7680
7781 // mapping "b" to 1
7882 const indexes = new Int8Array ( 256 ) . fill ( - 1 ) ;
79- lettersA . forEach ( ( l , i ) => {
83+ const letterCodes = new Int8Array ( 256 ) . fill ( - 1 ) ;
84+ letterChars . forEach ( ( l , i ) => {
8085 const code = l . codePointAt ( 0 ) ! ;
8186 if ( code > 127 || indexes [ code ] !== - 1 ) throw new Error ( `Non-ascii or duplicate symbol: "${ l } "` ) ;
8287 indexes [ code ] = i ;
88+ letterCodes [ i ] = code ;
8389 } ) ;
8490 return {
8591 encode : ( digits : Uint8Array ) : string => {
8692 abytes ( digits ) ;
87- const out = [ ]
88- for ( const i of digits ) {
89- if ( i >= len )
90- throw new Error (
91- `alphabet.encode: digit index outside alphabet "${ i } ". Allowed: ${ letters } `
92- ) ;
93- out . push ( lettersA [ i ] ! ) ;
93+ let out
94+ const length = digits . length
95+ if ( nativeDecoder ) {
96+ const codes = new Uint8Array ( length ) ;
97+ for ( let i = 0 ; i < length ; i ++ ) {
98+ const c = letterCodes [ digits [ i ] ! ] ! ;
99+ if ( c < 0 ) throw new Error ( `alphabet.encode: digit index outside alphabet "${ digits [ i ] } ". Allowed: ${ letters } ` ) ;
100+ codes [ i ] = c ;
101+ }
102+ out = nativeDecoder . decode ( codes ) ;
103+ } else {
104+ const acc = [ ]
105+ for ( const d of digits ) {
106+ if ( d >= len ) throw new Error ( `alphabet.encode: digit index outside alphabet "${ d } ". Allowed: ${ letters } ` ) ;
107+ acc . push ( letterChars [ d ] ! ) ;
108+ }
109+ out = acc . join ( '' ) ;
94110 }
95111 if ( paddingBits > 0 ) {
96- while ( ( out . length * paddingBits ) % 8 ) out . push ( paddingChr ) ;
112+ while ( ( out . length * paddingBits ) % 8 ) out += paddingChr ;
97113 }
98- return out . join ( '' ) ;
114+ return out ;
99115 } ,
100116 decode : ( str : string ) : Uint8Array => {
101117 astr ( 'alphabet.decode' , str ) ;
0 commit comments