import { $NAME, $CONSTRUCTOR } from '../../MetaContext'; import { $ASSIGN, Assign, deepAssign } from '../../operations/base/$assign'; import { $CLONE, Clone, deepClone } from '../../operations/base/$clone'; import { $COMPARE, Compare, deepCompare } from '../../operations/base/$compare'; import { $CONSTRUCT, Construct, genericConstruct } from '../../operations/base/$construct'; import { $DUMP, Dump, deepDump } from '../../operations/base/$dump'; import { $EQUAL, Equal, deepEqual } from '../../operations/base/$equal'; import { $HASH, Hash, deepHash } from '../../operations/base/$hash'; import { $RESTORE, $CREATE, Restore, Create, deepRestore, genericCreate } from '../../operations/base/$restore'; import { $SERIALIZE, genericSerialize } from '../../operations/base/$serialize'; import { $STRINGIFY, Stringify, deepStringify, stringifyObjectLikeWrapper, quoteKey } from '../../operations/base/$stringify'; export function assign(lhs: Map, rhs: Map, assignfn: Assign<[K, V]>, clonefn: Clone<[K, V]>, context?: any) { for (const entry of lhs) { const key = entry[0]; if (!rhs.has(key)) { lhs.delete(key); continue; } lhs.set(key, (assignfn.call(context, [key, lhs.get(key)!], [key, rhs.get(key)!]) as [K, V])[1]); } for (const entry of rhs) if (!lhs.has(entry[0])) { const [key, value] = clonefn.call(context, entry) as [K, V]; lhs.set(key, value); } return lhs; } export function clone(map: Map, clonefn: Clone<[K, V]>, constructfn: Construct>, context?: any) { const entries = new Array(map.size); let i = 0; for (const entry of map) entries[i++] = clonefn.call(context, entry); return constructfn(entries); } export function compare(lhs: Map, rhs: Map, comparefn: Compare<[K, V]>, context?: any) { const lhsSize = lhs.size; const rhsSize = rhs.size; const minSize = Math.min(lhsSize, rhsSize); const lhsEntries = lhs.entries(); const rhsEntries = rhs.entries(); for (let i = 0; i < minSize; i++) { const result = comparefn.call(context, lhsEntries.next().value, rhsEntries.next().value); if (result !== 0) return result; } return lhsSize - rhsSize; } export function dump(map: Map, dumpfn: Dump<[K, V]>, context?: any) { const ret = new Array(map.size); let i = 0; for (const entry of map) ret[i++] = dumpfn.call(context, entry); return ret; } export function equal(lhs: Map, rhs: Map, equalfn: Equal, context?: any) { if (lhs.size !== rhs.size) return false; for (const key of lhs.keys()) { if (!rhs.has(key)) return false; if (!equalfn.call(context, lhs.get(key)!, rhs.get(key)!)) return false; } for (const key of rhs.keys()) if (!lhs.has(key)) return false; return true; } export function hash(map: Map, hashfn: Hash<[K, V]>, seed = 0, context?: any) { for (const entry of map) seed = (seed + hashfn.call(context, entry)) >>> 0; return seed; } export function restore(map: Map, state: any, _: Restore<[K, V]>, createfn: Create<[K, V]>, context?: any) { map.clear(); for (let i = 0; i < state.length; i++) { const [key, value] = createfn.call(context, state[i]); map.set(key, value); } return map; } export function stringify(map: Map, stringifyfn: Stringify , context?: any) { return [...map].map(([key, value]) => `${typeof key === 'string' ? quoteKey(key) : stringifyfn.call(context, key)}: ${stringifyfn.call(context, value)}`).join(', '); } export const $assign = deepAssign, [any, any]>(assign); export const $clone = deepClone, [any, any]>(clone); export const $compare = deepCompare, [any, any]>(compare); export const $construct = genericConstruct; export const $create = genericCreate; export const $dump = deepDump, [any, any]>(dump); export const $equal = deepEqual, any>(equal); export const $hash = deepHash, any>(hash); export const $restore = deepRestore, [any, any]>(restore); export const $serialize = genericSerialize; export const $stringify = deepStringify, any>(stringify, stringifyObjectLikeWrapper); export const $constructor = Map; export const $name = 'Map'; export const $tag = { [$CONSTRUCTOR]: $constructor, [$NAME]: $name }; export default { [$CONSTRUCTOR]: $constructor, [$NAME]: $name, [$ASSIGN]: $assign, [$CLONE]: $clone, [$COMPARE]: $compare, [$CONSTRUCT]: $construct, [$CREATE]: $create, [$DUMP]: $dump, [$EQUAL]: $equal, [$HASH]: $hash, [$RESTORE]: $restore, [$SERIALIZE]: $serialize, [$STRINGIFY]: $stringify };