@@ -42,9 +42,6 @@ function anumber(n: number): void {
4242 if ( ! Number . isSafeInteger ( n ) ) throw new Error ( `invalid integer: ${ n } ` ) ;
4343}
4444
45- function aArr ( input : any [ ] ) {
46- if ( ! Array . isArray ( input ) ) throw new Error ( 'array expected' ) ;
47- }
4845function astrArr ( label : string , input : string [ ] ) {
4946 if ( ! isArrayOf ( true , input ) ) throw new Error ( `${ label } : array of strings expected` ) ;
5047}
@@ -80,15 +77,16 @@ function chain<T extends Chain & AsChain<T>>(...args: T): Coder<Input<First<T>>,
8077}
8178
8279/**
83- * Encodes integer radix representation to array of strings using alphabet and back.
84- * Could also be array of strings.
80+ * Encodes integer radix representation to Uint8Array of indexes in alphabet and back, with optional padding
8581 * @__NO_SIDE_EFFECTS__
8682 */
87- function alphabet ( letters : string | string [ ] ) : Coder < Uint8Array , string [ ] > {
83+ function alphabet ( letters : string , paddingBits : number = 0 , paddingChr = '=' ) : Coder < Uint8Array , string > {
8884 // mapping 1 to "b"
85+ astr ( 'alphabet' , letters ) ;
8986 const lettersA = typeof letters === 'string' ? letters . split ( '' ) : letters ;
9087 const len = lettersA . length ;
91- astrArr ( 'alphabet' , lettersA ) ;
88+ const paddingCode = paddingChr . codePointAt ( 0 ) ! ;
89+ if ( paddingChr . length !== 1 || paddingCode > 128 ) throw new Error ( 'Wrong padding char' ) ;
9290
9391 // mapping "b" to 1
9492 const indexes = new Int8Array ( 256 ) . fill ( - 1 ) ;
@@ -98,7 +96,7 @@ function alphabet(letters: string | string[]): Coder<Uint8Array, string[]> {
9896 indexes [ code ] = i ;
9997 } ) ;
10098 return {
101- encode : ( digits : Uint8Array ) : string [ ] => {
99+ encode : ( digits : Uint8Array ) : string => {
102100 abytes ( digits ) ;
103101 const out = [ ]
104102 for ( const i of digits ) {
@@ -108,69 +106,36 @@ function alphabet(letters: string | string[]): Coder<Uint8Array, string[]> {
108106 ) ;
109107 out . push ( letters [ i ] ! ) ;
110108 }
111- return out ;
109+ if ( paddingBits > 0 ) {
110+ while ( ( out . length * paddingBits ) % 8 ) out . push ( paddingChr ) ;
111+ }
112+ return out . join ( '' ) ;
112113 } ,
113- decode : ( input : string [ ] ) : Uint8Array => {
114- aArr ( input ) ;
115- const out = new Uint8Array ( input . length ) ;
114+ decode : ( str : string ) : Uint8Array => {
115+ astr ( 'alphabet.decode' , str ) ;
116+ let end = str . length ;
117+ if ( paddingBits > 0 ) {
118+ if ( ( end * paddingBits ) % 8 )
119+ throw new Error ( 'padding: invalid, string should have whole number of bytes' ) ;
120+ for ( ; end > 0 && str . charCodeAt ( end - 1 ) === paddingCode ; end -- ) {
121+ const last = end - 1 ;
122+ const byte = last * paddingBits ;
123+ if ( byte % 8 === 0 ) throw new Error ( 'padding: invalid, string has too much padding' ) ;
124+ }
125+ }
126+ const out = new Uint8Array ( end ) ;
116127 let at = 0
117- for ( const letter of input ) {
118- astr ( 'alphabet.decode' , letter ) ;
119- const c = letter . codePointAt ( 0 ) ! ;
128+ for ( let j = 0 ; j < end ; j ++ ) {
129+ const c = str . charCodeAt ( j ) ! ;
120130 const i = indexes [ c ] ! ;
121- if ( letter . length !== 1 || c > 127 || i < 0 ) throw new Error ( `Unknown letter: "${ letter } ". Allowed: ${ letters } ` ) ;
131+ if ( c > 127 || i < 0 ) throw new Error ( `Unknown letter: "${ String . fromCharCode ( c ) } ". Allowed: ${ letters } ` ) ;
122132 out [ at ++ ] = i ;
123133 }
124134 return out ;
125135 } ,
126136 } ;
127137}
128138
129- /**
130- * @__NO_SIDE_EFFECTS__
131- */
132- function join ( separator = '' ) : Coder < string [ ] , string > {
133- astr ( 'join' , separator ) ;
134- return {
135- encode : ( from ) => {
136- astrArr ( 'join.decode' , from ) ;
137- return from . join ( separator ) ;
138- } ,
139- decode : ( to ) => {
140- astr ( 'join.decode' , to ) ;
141- return to . split ( separator ) ;
142- } ,
143- } ;
144- }
145-
146- /**
147- * Pad strings array so it has integer number of bits
148- * @__NO_SIDE_EFFECTS__
149- */
150- function padding ( bits : number , chr = '=' ) : Coder < string [ ] , string [ ] > {
151- anumber ( bits ) ;
152- astr ( 'padding' , chr ) ;
153- return {
154- encode ( data : string [ ] ) : string [ ] {
155- astrArr ( 'padding.encode' , data ) ;
156- while ( ( data . length * bits ) % 8 ) data . push ( chr ) ;
157- return data ;
158- } ,
159- decode ( input : string [ ] ) : string [ ] {
160- astrArr ( 'padding.decode' , input ) ;
161- let end = input . length ;
162- if ( ( end * bits ) % 8 )
163- throw new Error ( 'padding: invalid, string should have whole number of bytes' ) ;
164- for ( ; end > 0 && input [ end - 1 ] === chr ; end -- ) {
165- const last = end - 1 ;
166- const byte = last * bits ;
167- if ( byte % 8 === 0 ) throw new Error ( 'padding: invalid, string has too much padding' ) ;
168- }
169- return input . slice ( 0 , end ) ;
170- } ,
171- } ;
172- }
173-
174139/**
175140 * @__NO_SIDE_EFFECTS__
176141 */
@@ -347,8 +312,8 @@ function checksum(
347312}
348313
349314// prettier-ignore
350- export const utils : { alphabet : typeof alphabet ; chain : typeof chain ; checksum : typeof checksum ; convertRadix : typeof convertRadix ; convertRadix2 : typeof convertRadix2 ; radix : typeof radix ; radix2 : typeof radix2 ; join : typeof join ; padding : typeof padding ; } = {
351- alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join , padding ,
315+ export const utils : { alphabet : typeof alphabet ; chain : typeof chain ; checksum : typeof checksum ; convertRadix : typeof convertRadix ; convertRadix2 : typeof convertRadix2 ; radix : typeof radix ; radix2 : typeof radix2 ; } = {
316+ alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2,
352317} ;
353318
354319// RFC 4648 aka RFC 3548
@@ -362,7 +327,7 @@ export const utils: { alphabet: typeof alphabet; chain: typeof chain; checksum:
362327 * // => '12AB'
363328 * ```
364329 */
365- export const base16 : BytesCoder = chain ( radix2 ( 4 ) , alphabet ( '0123456789ABCDEF' ) , join ( '' ) ) ;
330+ export const base16 : BytesCoder = chain ( radix2 ( 4 ) , alphabet ( '0123456789ABCDEF' ) ) ;
366331
367332/**
368333 * base32 encoding from RFC 4648. Has padding.
@@ -378,9 +343,7 @@ export const base16: BytesCoder = chain(radix2(4), alphabet('0123456789ABCDEF'),
378343 */
379344export const base32 : BytesCoder = chain (
380345 radix2 ( 5 ) ,
381- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' ) ,
382- padding ( 5 ) ,
383- join ( '' )
346+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' , 5 )
384347) ;
385348
386349/**
@@ -397,8 +360,7 @@ export const base32: BytesCoder = chain(
397360 */
398361export const base32nopad : BytesCoder = chain (
399362 radix2 ( 5 ) ,
400- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' ) ,
401- join ( '' )
363+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' )
402364) ;
403365/**
404366 * base32 encoding from RFC 4648. Padded. Compared to ordinary `base32`, slightly different alphabet.
@@ -413,9 +375,7 @@ export const base32nopad: BytesCoder = chain(
413375 */
414376export const base32hex : BytesCoder = chain (
415377 radix2 ( 5 ) ,
416- alphabet ( '0123456789ABCDEFGHIJKLMNOPQRSTUV' ) ,
417- padding ( 5 ) ,
418- join ( '' )
378+ alphabet ( '0123456789ABCDEFGHIJKLMNOPQRSTUV' , 5 )
419379) ;
420380
421381/**
@@ -431,8 +391,7 @@ export const base32hex: BytesCoder = chain(
431391 */
432392export const base32hexnopad : BytesCoder = chain (
433393 radix2 ( 5 ) ,
434- alphabet ( '0123456789ABCDEFGHIJKLMNOPQRSTUV' ) ,
435- join ( '' )
394+ alphabet ( '0123456789ABCDEFGHIJKLMNOPQRSTUV' )
436395) ;
437396/**
438397 * base32 encoding from RFC 4648. Doug Crockford's version.
@@ -448,7 +407,6 @@ export const base32hexnopad: BytesCoder = chain(
448407export const base32crockford : BytesCoder = chain (
449408 radix2 ( 5 ) ,
450409 alphabet ( '0123456789ABCDEFGHJKMNPQRSTVWXYZ' ) ,
451- join ( '' ) ,
452410 normalize ( ( s : string ) => s . toUpperCase ( ) . replace ( / O / g, '0' ) . replace ( / [ I L ] / g, '1' ) )
453411) ;
454412
@@ -489,9 +447,7 @@ export const base64: BytesCoder = hasBase64Builtin ? {
489447 decode ( s ) { return decodeBase64Builtin ( s , false ) ; } ,
490448} : chain (
491449 radix2 ( 6 ) ,
492- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ) ,
493- padding ( 6 ) ,
494- join ( '' )
450+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' , 6 )
495451) ;
496452/**
497453 * base64 from RFC 4648. No padding.
@@ -506,8 +462,7 @@ export const base64: BytesCoder = hasBase64Builtin ? {
506462 */
507463export const base64nopad : BytesCoder = chain (
508464 radix2 ( 6 ) ,
509- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ) ,
510- join ( '' )
465+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' )
511466) ;
512467
513468/**
@@ -528,9 +483,7 @@ export const base64url: BytesCoder = hasBase64Builtin ? {
528483 decode ( s ) { return decodeBase64Builtin ( s , true ) ; } ,
529484} : chain (
530485 radix2 ( 6 ) ,
531- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' ) ,
532- padding ( 6 ) ,
533- join ( '' )
486+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' , 6 )
534487) ;
535488
536489/**
@@ -546,14 +499,13 @@ export const base64url: BytesCoder = hasBase64Builtin ? {
546499 */
547500export const base64urlnopad : BytesCoder = chain (
548501 radix2 ( 6 ) ,
549- alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' ) ,
550- join ( '' )
502+ alphabet ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' )
551503) ;
552504
553505// base58 code
554506// -----------
555507const genBase58 = /* @__NO_SIDE_EFFECTS__ */ ( abc : string ) =>
556- chain ( radix ( 58 ) , alphabet ( abc ) , join ( '' ) ) ;
508+ chain ( radix ( 58 ) , alphabet ( abc ) ) ;
557509
558510/**
559511 * base58: base64 without ambigous characters +, /, 0, O, I, l.
@@ -642,8 +594,7 @@ export interface Bech32DecodedWithArray<Prefix extends string = string> {
642594}
643595
644596const BECH_ALPHABET : Coder < Uint8Array , string > = chain (
645- alphabet ( 'qpzry9x8gf2tvdw0s3jn54khce6mua7l' ) ,
646- join ( '' )
597+ alphabet ( 'qpzry9x8gf2tvdw0s3jn54khce6mua7l' )
647598) ;
648599
649600const POLYMOD_GENERATORS = [ 0x3b6a57b2 , 0x26508e6d , 0x1ea119fa , 0x3d4233dd , 0x2a1462b3 ] ;
@@ -822,7 +773,6 @@ export const hex: BytesCoder = hasHexBuiltin
822773 : chain (
823774 radix2 ( 4 ) ,
824775 alphabet ( '0123456789abcdef' ) ,
825- join ( '' ) ,
826776 normalize ( ( s : string ) => {
827777 if ( typeof s !== 'string' || s . length % 2 !== 0 )
828778 throw new TypeError (
0 commit comments