mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-03 05:55:03 +01:00
feat(utils): stringToIntegerInRange
This commit is contained in:
committed by
karliatto
parent
d51c2b94f3
commit
6d9116d6bd
26
packages/utils/src/getIntegerInRangeFromString.ts
Normal file
26
packages/utils/src/getIntegerInRangeFromString.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
*
|
||||
* @param input - any string
|
||||
* @param max - max number not included for the range, if 100 is provided the range will be 0 to 99, if 101, then range is 0 to 100
|
||||
* @returns number
|
||||
* @see https://stackoverflow.com/questions/6122571/simple-non-secure-hash-function-for-javascript
|
||||
*/
|
||||
export const getIntegerInRangeFromString = (input: string, max: number): number => {
|
||||
let hash = 0;
|
||||
if (input.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Non secure but fash hash function with browser compatibility
|
||||
// https://stackoverflow.com/questions/6122571/simple-non-secure-hash-function-for-javascript
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const char = input.charCodeAt(i);
|
||||
hash = (hash << 5) - hash + char;
|
||||
// Convert to 32bit integer.
|
||||
hash |= 0;
|
||||
}
|
||||
|
||||
// The result of `x % n` is always in the range `-(n-1)` to `n-1`.
|
||||
// Taking the absolute value ensures it's in the range 0 to max.
|
||||
return Math.abs(hash % max);
|
||||
};
|
||||
@@ -58,3 +58,4 @@ export * from './typedObjectKeys';
|
||||
export * from './urlToOnion';
|
||||
export * from './zip';
|
||||
export * from './removeTrailingSlashes';
|
||||
export * from './getIntegerInRangeFromString';
|
||||
|
||||
33
packages/utils/tests/getIntegerInRangeFromString.test.ts
Normal file
33
packages/utils/tests/getIntegerInRangeFromString.test.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { getIntegerInRangeFromString } from '../src/getIntegerInRangeFromString';
|
||||
|
||||
describe('getIntegerInRangeFromString', () => {
|
||||
it('should always produce the same number for the same string input', () => {
|
||||
const input = '47A2176AC04E609FD0E9811A';
|
||||
const result1 = getIntegerInRangeFromString(input, 101);
|
||||
const result2 = getIntegerInRangeFromString(input, 101);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
it('should always be deterministic in producing a number from same input', () => {
|
||||
const input = 'z';
|
||||
const result1 = getIntegerInRangeFromString(input, 101);
|
||||
expect(result1).toBe(21);
|
||||
});
|
||||
|
||||
it('should return a number between 0 and 100 for various inputs', () => {
|
||||
const inputs = [
|
||||
'z',
|
||||
'', // It should work with empty string as well.
|
||||
'a-much-longer-string-to-test-just-to-test-that-something-like-this-will-also-work',
|
||||
'47A2176AC04E609FD0E9811A',
|
||||
'!@#$%^&*()-and-some-other-characters-ěščřžýáíé',
|
||||
'another-device-id-456',
|
||||
];
|
||||
|
||||
inputs.forEach(input => {
|
||||
const result = getIntegerInRangeFromString(input, 101);
|
||||
expect(result).toBeGreaterThanOrEqual(0);
|
||||
expect(result).toBeLessThan(101);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user