Created
August 12, 2022 08:09
-
-
Save DonovanDMC/69a073a01b63bcb769b4c0b9af3a3353 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Snowflake { | |
static readonly BITS = { | |
EPOCH: 41, | |
MACHINE_ID: 10, | |
SEQUENCE: 12, | |
UNUSED: 1 | |
}; | |
static readonly EPOCH = Date.parse("2022-01-01T00:00:00.000Z"); | |
static readonly MACHINE_ID = 0; | |
static readonly MAX_MACHINE_ID = Math.pow(2, Snowflake.BITS.MACHINE_ID); | |
static readonly MAX_SEQUENCE = Math.pow(2, Snowflake.BITS.SEQUENCE); | |
static SEQUENCE = 0; | |
private static binaryToId(bin: string): string { | |
let dec = ""; | |
while (bin.length > 50) { | |
const high = parseInt(bin.slice(0, -32), 2); | |
const low = parseInt((high % 10).toString(2) + bin.slice(-32), 2); | |
dec = (low % 10).toString() + dec; | |
bin = | |
Math.floor(high / 10).toString(2) + | |
Math.floor(low / 10) | |
.toString(2) | |
.padStart(32, "0"); | |
} | |
let b = parseInt(bin, 2); | |
while (b > 0) { | |
dec = (b % 10).toString() + dec; | |
b = Math.floor(b / 10); | |
} | |
return dec; | |
} | |
private static idToBinary(id: string) { | |
let bin = ""; | |
let high = Number(id.slice(0, -10)) || 0; | |
let low = Number(id.slice(-10)); | |
while (low > 0 || high > 0) { | |
bin = String(low & 1) + bin; | |
low = Math.floor(low / 2); | |
if (high > 0) { | |
low += 5e9 * (high % 2); | |
high = Math.floor(high / 2); | |
} | |
} | |
return bin; | |
} | |
static decode(id: string) { | |
const bin = this.idToBinary(id).toString().padStart(64, "0").split(""); | |
return { | |
timestamp: parseInt(bin.splice(0, Snowflake.BITS.EPOCH).join(""), 2) + this.EPOCH, | |
machineId: parseInt(bin.splice(0, Snowflake.BITS.MACHINE_ID).join(""), 2), | |
sequence: parseInt(bin.splice(0, Snowflake.BITS.SEQUENCE).join(""), 2), | |
unused: parseInt(bin.splice(0, Snowflake.BITS.UNUSED).join(""), 2) | |
}; | |
} | |
static generate(timestamp = Date.now()): string { | |
const bin = `${(timestamp - this.EPOCH).toString(2).padStart(Snowflake.BITS.EPOCH, "0")}${this.MACHINE_ID.toString(2).padStart(Snowflake.BITS.MACHINE_ID, "0")}${(this.SEQUENCE++).toString(2).padStart(Snowflake.BITS.SEQUENCE, "0")}${"0".repeat(Snowflake.BITS.UNUSED)}`; | |
if (this.SEQUENCE >= (this.MAX_SEQUENCE - 1)) this.SEQUENCE = 0; | |
return this.binaryToId(bin); | |
} | |
static getSequence() { return Number(this.SEQUENCE); /* make uneditable */ } | |
} | |
export default Snowflake; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment