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 } 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 } from '../../operations/base/$stringify'; export function assign(lhs: Set, rhs: Set, _: Assign, clonefn: Clone, context?: any) { for (const value of lhs.values()) if (!rhs.has(value)) lhs.delete(value); for (const value of rhs.values()) if (!lhs.has(value)) lhs.add(clonefn.call(context, value) as T); return lhs; } export function clone(set: Set, clonefn: Clone, constructfn: Construct>, context?: any) { const values = new Array(set.size); let i = 0; for (const value of set.values()) values[i++] = clonefn.call(context, value); return constructfn(values); } export function compare(lhs: Set, rhs: Set, comparefn: Compare, context?: any) { const lhsSize = lhs.size; const rhsSize = rhs.size; const minSize = Math.min(lhsSize, rhsSize); const lhsValues = lhs.values(); const rhsValues = rhs.values(); for (let i = 0; i < minSize; i++) { const result = comparefn.call(context, lhsValues.next().value, rhsValues.next().value); if (result !== 0) return result; } return lhsSize - rhsSize; } export function dump(set: Set, dumpfn: Dump, context?: any) { const ret = new Array(set.size); let i = 0; for (const value of set.values()) ret[i++] = dumpfn.call(context, value); return ret; } export function equal(lhs: Set, rhs: Set) { if (lhs.size !== rhs.size) return false; for (const value of lhs.values()) if (!rhs.has(value)) return false; for (const value of rhs.values()) if (!lhs.has(value)) return false; return true; } export function hash(set: Set, hashfn: Hash, seed = 0, context?: any) { for (const value of set.values()) seed = (seed + hashfn.call(context, value)) >>> 0; return seed; } export function restore(set: Set, state: any, _: Restore, createfn: Create, context?: any) { set.clear(); for (let i = 0; i < state.length; i++) set.add(createfn.call(context, state[i])); return set; } export function stringify(set: Set, stringifyfn: Stringify, context?: any) { return [...set.values()].map(value => `${stringifyfn.call(context, value)}`).join(', '); } export const $assign = deepAssign, any>(assign); export const $clone = deepClone, any>(clone); export const $compare = deepCompare, any>(compare); export const $construct = genericConstruct; export const $create = genericCreate; export const $dump = deepDump, any>(dump); export const $equal = equal; export const $hash = deepHash, any>(hash); export const $restore = deepRestore, any>(restore); export const $serialize = genericSerialize; export const $stringify = deepStringify, any>(stringify, stringifyObjectLikeWrapper); export const $constructor = Set; export const $name = 'Set'; 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 };