Skip to content

Commit 6f2897f

Browse files
committed
Rework entropy bits offset tracking
1 parent 9bec28b commit 6f2897f

File tree

2 files changed

+35
-42
lines changed

2 files changed

+35
-42
lines changed

src/lib/bits.ts

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,6 @@ const bitShifts = (chars: string): BitShifts => {
5959
)
6060
}
6161

62-
const valueAt = (lOffset: number, nBits: number, puidBytes: PuidBytes): number => {
63-
const lByteNdx = floor(lOffset / 8)
64-
const lByte = puidBytes[lByteNdx]
65-
66-
const lBitNum = lOffset % 8
67-
// eslint-disable-next-line functional/no-let
68-
let rBitNum = lBitNum + nBits
69-
70-
if (rBitNum <= 8) {
71-
return ((lByte << lBitNum) & 0xff) >> (lBitNum + (8 - rBitNum))
72-
}
73-
rBitNum -= 8
74-
75-
const rByte = puidBytes[lByteNdx + 1]
76-
77-
const lValue = ((lByte << lBitNum) & 0xff) >> (lBitNum - rBitNum)
78-
const rValue = rByte >> (8 - rBitNum)
79-
80-
return lValue + rValue
81-
}
82-
8362
const entropyByBytes = (skipBytes: number, entropyBuffer: EntropyBuffer, sourceBytes: EntropyByBytes) => {
8463
const entropyBytes = new Uint8Array(entropyBuffer)
8564
const bytesLen = entropyBytes.length
@@ -100,21 +79,15 @@ const entropyByValues = (skipBytes: number, entropyBuffer: EntropyBuffer, source
10079
}
10180
}
10281

103-
const fillEntropy = (entropyBits: EntropyBits, entropyFunction: EntropyFunction) => {
104-
const [offset, entropyBuffer] = entropyBits
105-
82+
const fillEntropy = (entropyOffset: number, entropyBuffer: ArrayBuffer, entropyFunction: EntropyFunction): number => {
10683
const entropyBytes: PuidBytes = new Uint8Array(entropyBuffer)
10784

10885
const nEntropyBytes = entropyBytes.length
10986
const nEntropyBits = 8 * nEntropyBytes
11087

111-
// New offset
112-
// eslint-disable-next-line functional/immutable-data
113-
entropyBits[0] = offset % 8
114-
11588
const [byValues, entropySource] = entropyFunction
11689

117-
if (offset === nEntropyBits) {
90+
if (entropyOffset === nEntropyBits) {
11891
// No carry
11992
if (byValues) {
12093
entropyByValues(0, entropyBuffer, entropySource as EntropyByValues)
@@ -123,10 +96,10 @@ const fillEntropy = (entropyBits: EntropyBits, entropyFunction: EntropyFunction)
12396
}
12497
} else {
12598
// Handle carry
126-
const nUnusedBits = nEntropyBits - offset
99+
const nUnusedBits = nEntropyBits - entropyOffset
127100
const nUnusedBytes = ceil(nUnusedBits / 8)
128101

129-
const offsetByteNum = floor(offset / 8)
102+
const offsetByteNum = floor(entropyOffset / 8)
130103

131104
// Move unused bytes to the left
132105
const unusedBytes = new Uint8Array(entropyBuffer, offsetByteNum)
@@ -139,6 +112,29 @@ const fillEntropy = (entropyBits: EntropyBits, entropyFunction: EntropyFunction)
139112
entropyByBytes(nUnusedBytes, entropyBuffer, entropySource as EntropyByBytes)
140113
}
141114
}
115+
116+
return entropyOffset % 8
117+
}
118+
119+
const valueAt = (lOffset: number, nBits: number, puidBytes: PuidBytes): number => {
120+
const lByteNdx = floor(lOffset / 8)
121+
const lByte = puidBytes[lByteNdx]
122+
123+
const lBitNum = lOffset % 8
124+
// eslint-disable-next-line functional/no-let
125+
let rBitNum = lBitNum + nBits
126+
127+
if (rBitNum <= 8) {
128+
return ((lByte << lBitNum) & 0xff) >> (lBitNum + (8 - rBitNum))
129+
}
130+
rBitNum -= 8
131+
132+
const rByte = puidBytes[lByteNdx + 1]
133+
134+
const lValue = ((lByte << lBitNum) & 0xff) >> (lBitNum - rBitNum)
135+
const rValue = rByte >> (8 - rBitNum)
136+
137+
return lValue + rValue
142138
}
143139

144140
export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunction): PuidBitsMuncherResult => {
@@ -147,8 +143,9 @@ export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunc
147143
const nBytesPerPuid = ceil(nBitsPerPuid / 8)
148144

149145
const bufferLen = nBytesPerPuid + 1
146+
// eslint-disable-next-line functional/no-let
147+
let entropyOffset = 8 * bufferLen
150148
const entropyBuffer = new ArrayBuffer(bufferLen)
151-
const entropyBits: EntropyBits = [8 * bufferLen, entropyBuffer]
152149
const entropyBytes = new Uint8Array(entropyBuffer)
153150

154151
const charsEncoder = encoder(puidChars)
@@ -158,13 +155,11 @@ export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunc
158155
if (isPow2(nChars)) {
159156
// When chars count is a power of 2, sliced bits always yield a valid char
160157
const bitsMuncher = () => {
161-
fillEntropy(entropyBits, entropyFunction)
162-
const entropyOffset = entropyBits[0]
163-
// eslint-disable-next-line functional/immutable-data
164-
entropyBits[0] = entropyOffset + nBitsPerPuid
158+
entropyOffset = fillEntropy(entropyOffset, entropyBuffer, entropyFunction)
165159
const codes = mapper.map((ndx: number) =>
166160
charsEncoder(valueAt(entropyOffset + ndx * nBitsPerChar, nBitsPerChar, entropyBytes))
167161
)
162+
entropyOffset += nBitsPerPuid
168163
return String.fromCharCode(...codes)
169164
}
170165

@@ -184,14 +179,13 @@ export default (puidLen: number, puidChars: string, entropyFunction: EntropyFunc
184179
}
185180

186181
const sliceValue = () => {
187-
if (nEntropyBits < entropyBits[0] + nBitsPerChar) {
188-
fillEntropy(entropyBits, entropyFunction)
182+
if (nEntropyBits < entropyOffset + nBitsPerChar) {
183+
entropyOffset = fillEntropy(entropyOffset, entropyBuffer, entropyFunction)
189184
}
190185

191-
const slicedValue = valueAt(entropyBits[0], nBitsPerChar, entropyBytes)
186+
const slicedValue = valueAt(entropyOffset, nBitsPerChar, entropyBytes)
192187
const [accept, shift] = acceptValue(slicedValue)
193-
// eslint-disable-next-line functional/immutable-data
194-
entropyBits[0] += shift
188+
entropyOffset += shift
195189

196190
if (accept) {
197191
return charsEncoder(slicedValue)

src/types/puid.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ type PuidBitsMuncherResult = Either<PuidBitsMuncher>
3838
type PuidBitsSlicer = (puidBits: PuidBits) => number[]
3939
type PuidEncoder = (n: number) => number
4040

41-
type EntropyBits = [offset: number, buffer: EntropyBuffer]
4241
type EntropyBytes = Uint8Array
4342
type EntropyBuffer = ArrayBuffer
4443

0 commit comments

Comments
 (0)