mirror of
https://github.com/nvms/prsm.git
synced 2025-12-17 08:30:53 +00:00
75 lines
1.7 KiB
TypeScript
75 lines
1.7 KiB
TypeScript
import long from "long";
|
|
|
|
export default class ID {
|
|
private static MAX_INT32 = 2_147_483_647;
|
|
private static MULTIPLIER = 4_294_967_296;
|
|
|
|
static alphabet: string =
|
|
"23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_";
|
|
static prime: number = 1_125_812_041;
|
|
static inverse: number = 348_986_105;
|
|
static random: number = 998_048_641;
|
|
|
|
static get base(): number {
|
|
return ID.alphabet.length;
|
|
}
|
|
|
|
private static shorten(id: number): string {
|
|
let result = "";
|
|
|
|
while (id > 0) {
|
|
result = ID.alphabet[id % ID.base] + result;
|
|
id = Math.floor(id / ID.base);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static unshorten(str: string): number {
|
|
let result = 0;
|
|
|
|
for (let i = 0; i < str.length; i++) {
|
|
result = result * ID.base + ID.alphabet.indexOf(str[i]);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static encode = (num: number): string => {
|
|
if (num > ID.MAX_INT32) {
|
|
throw new Error(
|
|
`Number (${num}) is too large to encode. MAX_INT32 is ${ID.MAX_INT32}`,
|
|
);
|
|
}
|
|
|
|
const n: long = long.fromInt(num);
|
|
|
|
return ID.shorten(
|
|
n
|
|
.multiply(ID.prime)
|
|
.and(long.fromInt(ID.MAX_INT32))
|
|
.xor(ID.random)
|
|
.toInt(),
|
|
);
|
|
};
|
|
|
|
static decode = (str: string): number => {
|
|
const n: long = long.fromInt(ID.unshorten(str));
|
|
|
|
return n
|
|
.xor(ID.random)
|
|
.multiply(ID.inverse)
|
|
.and(long.fromInt(ID.MAX_INT32))
|
|
.toInt();
|
|
};
|
|
|
|
static randomizeAlphabet(): void {
|
|
const array = ID.alphabet.split('');
|
|
for (let i = array.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[array[i], array[j]] = [array[j], array[i]];
|
|
}
|
|
ID.alphabet = array.join('');
|
|
}
|
|
}
|