Skip to content

Commit 9bec28b

Browse files
committed
Accumulate codes
Bits muncher accummulates codes for a single call to String.fromCharCode non-pow-2 muncher uses map rather than reduce
1 parent 65a212e commit 9bec28b

File tree

1 file changed

+31
-32
lines changed

1 file changed

+31
-32
lines changed

src/lib/bits.ts

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5962
const 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

Comments
 (0)