From 2912296d96a4f1462f205d354331e3678c0225be Mon Sep 17 00:00:00 2001 From: Mohtasim Alam Sohom <94981761+devaoto@users.noreply.github.com> Date: Mon, 7 Oct 2024 03:23:53 +0600 Subject: [PATCH] refactor: optimize the resolveColor function for better perfomance (#273) * refactor: optimize the resolveColor function for better perfomance * refactor: optimize the resolveColor function even further for higher number of iterations * format: fix code formatting * just use if(lookupColor) --- src/common/it/utils.ts | 60 +++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/common/it/utils.ts b/src/common/it/utils.ts index 6ed9a8d..43a9f2b 100644 --- a/src/common/it/utils.ts +++ b/src/common/it/utils.ts @@ -22,28 +22,37 @@ import { type APIPartialEmoji, FormattingPatterns, GatewayIntentBits } from '../ export function calculateShardId(guildId: string, shards?: number) { return Number((BigInt(guildId) >> 22n) % BigInt(shards ?? 1)); } + +// It is used for resolve color for better performance +const ColorLookup: { [key: string]: number } = { + Random: -1, // Special value for random color + ...EmbedColors, +}; + /** * Resolves the color to a numeric representation. * @param color The color to resolve. * @returns The numeric representation of the color. */ export function resolveColor(color: ColorResolvable): number { - switch (typeof color) { - case 'string': { - if (color === 'Random') return Math.floor(Math.random() * (0xffffff + 1)); - if (color.startsWith('#')) return Number.parseInt(color.slice(1), 16); - if (color in EmbedColors) return EmbedColors[color as keyof typeof EmbedColors]; - return EmbedColors.Default; - } - case 'number': - return color; - case 'object': - if (Array.isArray(color)) return (color[0] << 16) + (color[1] << 8) + color[2]; - break; - default: - return color; + const type = typeof color; + + if (type === 'number') { + if (!Number.isInteger(color) || (color as number) < 0) throw new Error(`Invalid color: ${color}`); + return color as number; } - return color; + + if (type === 'string') { + const lookupColor = ColorLookup[color as keyof typeof EmbedColors]; + if (lookupColor) { + return lookupColor === -1 ? Math.floor(Math.random() * 0xffffff) : lookupColor; + } + return (color as string).startsWith('#') ? Number.parseInt((color as string).slice(1), 16) : EmbedColors.Default; + } + + return Array.isArray(color) && color.length >= 3 + ? (color[0] << 16) | (color[1] << 8) | color[2] + : EmbedColors.Default; } /** @@ -320,7 +329,11 @@ export function resolvePartialEmoji(emoji: EmojiResolvable): APIPartialEmoji | u if (typeof emoji === 'string') { const groups: Partial | undefined = emoji.match(FormattingPatterns.Emoji)?.groups; if (groups) { - return { animated: !!groups.animated, name: groups.name!, id: groups.id! }; + return { + animated: !!groups.animated, + name: groups.name!, + id: groups.id!, + }; } if (emoji.includes('%')) { emoji = encodeURIComponent(emoji); @@ -342,12 +355,23 @@ export async function resolveEmoji(emoji: EmojiResolvable, cache: Cache): Promis if (typeof emoji === 'string') { if (!emoji.match(/\d{17,20}/g)) return; const fromCache = await cache.emojis?.get(emoji); - return fromCache && { animated: fromCache.animated, id: fromCache.id, name: fromCache.name }; + return ( + fromCache && { + animated: fromCache.animated, + id: fromCache.id, + name: fromCache.name, + } + ); } if (emoji.id) { const fromCache = await cache.emojis?.get(emoji.id); - if (fromCache) return { animated: fromCache.animated, id: fromCache.id, name: fromCache.name }; + if (fromCache) + return { + animated: fromCache.animated, + id: fromCache.id, + name: fromCache.name, + }; } return; }