//#region src/memo.ts
const DEFAULT_MAX = 256;
function isPlainObject(value) {
	if (value === null || typeof value !== "object") return false;
	const prototype = Object.getPrototypeOf(value);
	return prototype === Object.prototype || prototype === null;
}
function stableSerialize(value) {
	if (value === null) return "null";
	const valueType = typeof value;
	if (valueType === "string") return JSON.stringify(value);
	if (valueType === "number") {
		if (Number.isNaN(value)) return "number:NaN";
		if (Object.is(value, -0)) return "number:-0";
		if (value === Infinity) return "number:Infinity";
		if (value === -Infinity) return "number:-Infinity";
		return `number:${value}`;
	}
	if (valueType === "boolean") return value ? "true" : "false";
	if (valueType === "undefined") return "undefined";
	if (valueType === "bigint") return `bigint:${value}n`;
	if (valueType === "symbol" || valueType === "function") throw new TypeError("memoize: default key supports only JSON-like arguments; pass options.key for this value");
	if (Array.isArray(value)) return `[${value.map((item) => stableSerialize(item)).join(",")}]`;
	if (!isPlainObject(value)) return `${Object.prototype.toString.call(value)}:${String(value)}`;
	return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableSerialize(value[key])}`).join(",")}}`;
}
function defaultKey(...args) {
	return stableSerialize(args);
}
function memoize(fn, options) {
	const max = options?.max ?? DEFAULT_MAX;
	if (!Number.isInteger(max) || max < 1) throw new TypeError("memoize: options.max must be an integer >= 1");
	const cache = /* @__PURE__ */ new Map();
	const getKey = options?.key ?? defaultKey;
	return (...args) => {
		const key = getKey(...args);
		if (cache.has(key)) {
			const cached = cache.get(key);
			cache.delete(key);
			cache.set(key, cached);
			return cached;
		}
		const result = fn(...args);
		cache.set(key, result);
		while (cache.size > max) {
			const oldestKey = cache.keys().next().value;
			cache.delete(oldestKey);
		}
		return result;
	};
}
//#endregion
export { memoize };
