Skip to content

Commit 797d091

Browse files
committed
Compare hashing implementations
1 parent 61beee8 commit 797d091

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

flagsmith-engine/utils/hashing/index.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,51 @@ const md5 = (data: BinaryLike) => createHash('md5').update(data).digest('hex')
55
const makeRepeated = (arr: Array<any>, repeats: number) =>
66
Array.from({ length: repeats }, () => arr).flat();
77

8+
function h2d(s: any): string {
9+
function add(x: any, y: any) {
10+
var c = 0,
11+
r = [];
12+
var x = x.split('').map(Number);
13+
var y = y.split('').map(Number);
14+
while (x.length || y.length) {
15+
var s = (x.pop() || 0) + (y.pop() || 0) + c;
16+
r.unshift(s < 10 ? s : s - 10);
17+
c = s < 10 ? 0 : 1;
18+
}
19+
if (c) r.unshift(c);
20+
return r.join('');
21+
}
22+
23+
var dec = '0';
24+
s.split('').forEach(function (chr: any) {
25+
var n = parseInt(chr, 16);
26+
for (var t = 8; t; t >>= 1) {
27+
dec = add(dec, dec);
28+
if (n & t) dec = add(dec, '1');
29+
}
30+
});
31+
return dec;
32+
}
33+
34+
35+
import bigInt from 'big-integer'
36+
export function getHashedPercentateForObjIdsOld(objectIds: Array<any>, iterations = 1): number {
37+
let toHash = makeRepeated(objectIds, iterations).join(',');
38+
const hashedValue = md5(toHash);
39+
const hashedInt = bigInt(h2d(hashedValue));
40+
const value = (hashedInt.mod(9999).toJSNumber() / 9998) * 100;
41+
42+
// we ignore this for it's nearly impossible use case to catch
43+
/* istanbul ignore next */
44+
if (value === 100) {
45+
/* istanbul ignore next */
46+
return getHashedPercentateForObjIdsOld(objectIds, iterations + 1);
47+
}
48+
49+
return value;
50+
}
51+
52+
853
// https://stackoverflow.com/questions/12532871/how-to-convert-a-very-large-hex-number-to-decimal-in-javascript
954
/**
1055
* Given a list of object ids, get a floating point number between 0 and 1 based on

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"@types/semver": "^7.3.9",
7070
"@types/uuid": "^8.3.4",
7171
"@vitest/coverage-v8": "^2.1.2",
72+
"big-integer": "^1.6.52",
7273
"esbuild": "^0.14.25",
7374
"husky": "^7.0.4",
7475
"prettier": "^2.2.1",

tests/engine/unit/utils/utils.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
import { randomUUID as uuidv4 } from 'node:crypto';
2-
import { getHashedPercentateForObjIds } from '../../../../flagsmith-engine/utils/hashing/index.js';
2+
import {
3+
getHashedPercentateForObjIds,
4+
getHashedPercentateForObjIdsOld
5+
} from '../../../../flagsmith-engine/utils/hashing/index.js';
36

47
describe('getHashedPercentageForObjIds', () => {
8+
test('is equivalent to the previous implementation', () => {
9+
for (let i = 0; i < 10000; i++) {
10+
const data = [uuidv4()]
11+
const a = getHashedPercentateForObjIdsOld(data)
12+
const b = getHashedPercentateForObjIds(data)
13+
console.log(a, b)
14+
expect(a).toEqual(b)
15+
}
16+
})
17+
18+
519
it.each([
620
[[12, 93]],
721
[[uuidv4(), 99]],

0 commit comments

Comments
 (0)