@@ -41,19 +41,22 @@ const bitShifts = (chars: string): BitShifts => {
4141 if ( isPow2 ( chars . length ) ) return [ baseBitShift ]
4242
4343 return new Array ( nBitsPerChar )
44- . fill ( null )
45- . reduce ( ( acc , _n , ndx ) => {
46- acc . push ( ndx )
47- return acc
48- } , [ ] )
49- . slice ( 2 )
50- . reduce ( ( shifts : BitShifts , bit : number ) => {
51- if ( isBitZero ( chars . length , bit ) ) {
52- const shift : BitShift = [ chars . length | pow2 ( bit ) - 1 , nBitsPerChar - bit + 1 ]
53- return shifts . concat ( [ shift ] )
54- }
55- return shifts
56- } , [ baseBitShift ] )
44+ . fill ( null )
45+ . reduce ( ( acc , _n , ndx ) => {
46+ acc . push ( ndx )
47+ return acc
48+ } , [ ] )
49+ . slice ( 2 )
50+ . reduce (
51+ ( shifts : BitShifts , bit : number ) => {
52+ if ( isBitZero ( chars . length , bit ) ) {
53+ const shift : BitShift = [ chars . length | ( pow2 ( bit ) - 1 ) , nBitsPerChar - bit + 1 ]
54+ return shifts . concat ( [ shift ] )
55+ }
56+ return shifts
57+ } ,
58+ [ baseBitShift ]
59+ )
5760}
5861
5962const valueAt = ( lOffset : number , nBits : number , puidBytes : PuidBytes ) : number => {
@@ -149,29 +152,25 @@ export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunc
149152 const entropyBytes = new Uint8Array ( entropyBuffer )
150153
151154 const charsEncoder = encoder ( puidChars )
152- const puidEncoded = ( value : number ) => String . fromCharCode ( charsEncoder ( value ) )
153-
154155 const nChars = puidChars . length
155-
156+ const mapper = new Array ( puidLen ) . fill ( 0 ) . map ( ( zero , ndx ) => zero + ndx )
157+
156158 if ( isPow2 ( nChars ) ) {
157159 // When chars count is a power of 2, sliced bits always yield a valid char
158- const mapper = new Array ( puidLen ) . fill ( 0 ) . map ( ( zero , ndx ) => zero + ndx )
159-
160160 const bitsMuncher = ( ) => {
161161 fillEntropy ( entropyBits , entropyFunction )
162162 const entropyOffset = entropyBits [ 0 ]
163163 // eslint-disable-next-line functional/immutable-data
164164 entropyBits [ 0 ] = entropyOffset + nBitsPerPuid
165- return mapper . reduce ( ( puid : string , ndx : number ) => {
166- const value = valueAt ( entropyOffset + ndx * nBitsPerChar , nBitsPerChar , entropyBytes )
167- return puid + puidEncoded ( value )
168- } , '' )
165+ const codes = mapper . map ( ( ndx : number ) =>
166+ charsEncoder ( valueAt ( entropyOffset + ndx * nBitsPerChar , nBitsPerChar , entropyBytes ) )
167+ )
168+ return String . fromCharCode ( ... codes )
169169 }
170170
171171 return { success : bitsMuncher }
172172 }
173173
174-
175174 const nEntropyBits = 8 * entropyBytes . length
176175 const puidShifts = bitShifts ( puidChars )
177176
@@ -184,26 +183,26 @@ export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunc
184183 return [ false , shift || nBitsPerChar ]
185184 }
186185
187- const sliceBits = ( puid : string ) : string => {
188- if ( puid . length === puidLen ) {
189- // End recursion
190- return puid
191- }
192-
186+ const sliceValue = ( ) => {
193187 if ( nEntropyBits < entropyBits [ 0 ] + nBitsPerChar ) {
194188 fillEntropy ( entropyBits , entropyFunction )
195189 }
196190
197191 const slicedValue = valueAt ( entropyBits [ 0 ] , nBitsPerChar , entropyBytes )
198-
199192 const [ accept , shift ] = acceptValue ( slicedValue )
200193 // eslint-disable-next-line functional/immutable-data
201194 entropyBits [ 0 ] += shift
202195
203- return sliceBits ( accept ? puid + puidEncoded ( slicedValue ) : puid )
196+ if ( accept ) {
197+ return charsEncoder ( slicedValue )
198+ }
199+ return sliceValue ( )
204200 }
205201
206- const bitsMuncher = ( ) => sliceBits ( '' )
202+ const bitsMuncher = ( ) => {
203+ const codes = mapper . map ( ( ) => sliceValue ( ) )
204+ return String . fromCharCode ( ...codes )
205+ }
207206
208207 return { success : bitsMuncher }
209208}
0 commit comments