refactor(ulid): remove len argument from encodeTime() and encodeRandom() (#5054)

This commit is contained in:
Asher Gomez 2024-06-17 15:11:11 +12:00 committed by GitHub
parent 635e062330
commit f86c10ad8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 36 deletions

View File

@ -16,26 +16,26 @@ function replaceCharAt(str: string, index: number, char: string) {
return str.substring(0, index) + char + str.substring(index + 1);
}
export function encodeTime(now: number, len: number = TIME_LEN): string {
if (!Number.isInteger(now) || now < 0 || now > TIME_MAX) {
export function encodeTime(timestamp: number): string {
if (!Number.isInteger(timestamp) || timestamp < 0 || timestamp > TIME_MAX) {
throw new RangeError(
"Time must be a positive integer less than " + TIME_MAX,
`Time must be a positive integer less than ${TIME_MAX}`,
);
}
let str = "";
for (; len > 0; len--) {
const mod = now % ENCODING_LEN;
for (let len = TIME_LEN; len > 0; len--) {
const mod = timestamp % ENCODING_LEN;
str = ENCODING[mod] + str;
now = (now - mod) / ENCODING_LEN;
timestamp = Math.floor(timestamp / ENCODING_LEN);
}
return str;
}
export function encodeRandom(len: number): string {
export function encodeRandom(): string {
let str = "";
const randomBytes = crypto.getRandomValues(new Uint8Array(len));
for (const randomByte of randomBytes) {
str += ENCODING[randomByte % ENCODING_LEN];
const bytes = crypto.getRandomValues(new Uint8Array(RANDOM_LEN));
for (const byte of bytes) {
str += ENCODING[byte % ENCODING_LEN];
}
return str;
}
@ -67,10 +67,10 @@ export function monotonicFactory(encodeRand = encodeRandom): ULID {
return function ulid(seedTime: number = Date.now()): string {
if (seedTime <= lastTime) {
const incrementedRandom = (lastRandom = incrementBase32(lastRandom));
return encodeTime(lastTime, TIME_LEN) + incrementedRandom;
return encodeTime(lastTime) + incrementedRandom;
}
lastTime = seedTime;
const newRandom = (lastRandom = encodeRand(RANDOM_LEN));
return encodeTime(seedTime, TIME_LEN) + newRandom;
const newRandom = (lastRandom = encodeRand());
return encodeTime(seedTime) + newRandom;
};
}

View File

@ -50,7 +50,6 @@ import {
ENCODING,
ENCODING_LEN,
monotonicFactory,
RANDOM_LEN,
TIME_LEN,
TIME_MAX,
ULID_LEN,
@ -175,5 +174,5 @@ export function monotonicUlid(seedTime: number = Date.now()): string {
* @returns A ULID.
*/
export function ulid(seedTime: number = Date.now()): string {
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
return encodeTime(seedTime) + encodeRandom();
}

View File

@ -9,10 +9,9 @@ import { decodeTime, monotonicUlid, ulid } from "./mod.ts";
import {
encodeRandom,
encodeTime,
ENCODING,
ENCODING_LEN,
incrementBase32,
monotonicFactory,
RANDOM_LEN,
} from "./_util.ts";
Deno.test("incrementBase32()", async (t) => {
@ -46,28 +45,20 @@ Deno.test("incrementBase32()", async (t) => {
Deno.test("encodeTime()", async (t) => {
await t.step("should return expected encoded result", () => {
assertEquals("01ARYZ6S41", encodeTime(1469918176385, 10));
});
await t.step("should change length properly", () => {
assertEquals("0001AS99AA60", encodeTime(1470264322240, 12));
});
await t.step("should truncate time if not enough length", () => {
assertEquals("AS4Y1E11", encodeTime(1470118279201, 8));
assertEquals("01ARYZ6S41", encodeTime(1469918176385));
});
await t.step("should throw an error", async (t) => {
await t.step("if time greater than (2 ^ 48) - 1", () => {
assertThrows(() => {
encodeTime(Math.pow(2, 48), 8);
encodeTime(Math.pow(2, 48));
}, Error);
});
await t.step("if time is not a number", () => {
assertThrows(() => {
// deno-lint-ignore no-explicit-any
encodeTime("test" as any, 3);
encodeTime("test" as any);
}, Error);
});
@ -93,7 +84,7 @@ Deno.test("encodeTime()", async (t) => {
Deno.test("encodeRandom()", async (t) => {
await t.step("should return correct length", () => {
assertEquals(12, encodeRandom(12).length);
assertEquals(RANDOM_LEN, encodeRandom().length);
});
});
@ -146,13 +137,8 @@ Deno.test("ulid()", async (t) => {
});
Deno.test("monotonicUlid() handles monotonicity", async (t) => {
function encodeRandom(len: number): string {
let str = "";
const randomBytes = new Array(len).fill(30);
for (let i = 0; i < len; i++) {
str += ENCODING[randomBytes[i] % ENCODING_LEN];
}
return str;
function encodeRandom(): string {
return "YYYYYYYYYYYYYYYY";
}
await t.step("without seedTime", async (t) => {