export type Dictionary = { entries: Array<[K, V]>; indices: Map; isIterating: boolean; deleteQueue: Array; setQueue: Array<[K, V]>; }; export function createDictionary(): Dictionary { return { entries: [], indices: new Map(), isIterating: false, deleteQueue: [], setQueue: [], }; } export function deleteEntry(dict: Dictionary, key: K): void { const index = dict.indices.get(key); if (index === undefined) { return; } const last = dict.entries.length - 1; if (index !== last) { dict.entries[index] = dict.entries[last]; dict.indices.set(dict.entries[index][0], index); } dict.entries.pop(); dict.indices.delete(key); } export function deleteEntrySave(dict: Dictionary, key: K): void { if (dict.isIterating) { dict.deleteQueue.push(); } else { deleteEntry(dict, key); } } export function setEntry( dict: Dictionary, [key, value]: [K, V], ): void { const index = dict.indices.get(key); if (index === undefined) { dict.entries.push([key, value]); dict.indices.set(key, dict.entries.length); } else { dict.entries[index][1] = value; } } export function setEntrySave( dict: Dictionary, key: K, value: V, ): void { if (dict.isIterating) { dict.setQueue.push([key, value]); } else { setEntry(dict, [key, value]); } } export function getEntry(dict: Dictionary, key: K): V | undefined { const index = dict.indices.get(key); return index === undefined ? undefined : dict.entries[index][1]; } export function forEntry( dict: Dictionary, callback: (value: V, key: K, index: number) => void, ): void { dict.isIterating = true; for (let i = 0; i < dict.entries.length; i++) { callback(dict.entries[i][1], dict.entries[i][0], i); } dict.isIterating = false; while (dict.deleteQueue.length > 0) { deleteEntry(dict, dict.deleteQueue.pop()!); } while (dict.setQueue.length > 0) { setEntry(dict, dict.setQueue.pop()!); } }