import { has } from '../../../../core/object'; 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, primitiveSerialize } from '../../operations/base/$serialize'; import { $STRINGIFY, Stringify, deepStringify, stringifyObjectWrapper, quoteKey } from '../../operations/base/$stringify'; export function assign(lhs: any, rhs: any, assignfn: Assign, clonefn: Clone, context?: any) { const lhsKeys = Object.keys(lhs); for (let i = 0; i < lhsKeys.length; i++) { const key = lhsKeys[i]; if (!rhs.hasOwnProperty(key)) { delete lhs[key]; continue; } lhs[key] = assignfn.call(context, lhs[key], rhs[key]) as any; } const rhsKeys = Object.keys(rhs); for (let i = 0; i < rhsKeys.length; i++) { const key = rhsKeys[i]; if (!lhs.hasOwnProperty(key)) lhs[key] = clonefn.call(context, rhs[key]) as any; } return lhs; } export function clone(obj: any, clonefn: Clone, constructfn: Construct, context?: any) { const ret = constructfn(); const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; ret[key] = clonefn.call(context, obj[key]); } return ret; } export function compare(lhs: any, rhs: any, comparefn: Compare<[any, any]>, context?: any) { const lhsKeys = Object.keys(lhs); const rhsKeys = Object.keys(rhs); const lhsLength = lhsKeys.length; const rhsLength = rhsKeys.length; const minLength = Math.min(lhsLength, rhsLength); for (let i = 0; i < minLength; i++) { const lhsKey = lhsKeys[i]; const rhsKey = rhsKeys[i]; const result = comparefn.call(context, [lhsKey, lhs[lhsKey]], [rhsKey, rhs[rhsKey]]); if (result !== 0) return result; } return lhsLength - rhsLength; } export function dump(obj: any, dumpfn: Dump, context?: any) { const ret: any = {}; const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; ret[key] = dumpfn.call(context, obj[key]); } return ret; } export function equal(lhs: any, rhs: any, equalfn: Equal, context?: any) { const lhsKeys = Object.keys(lhs); const rhsKeys = Object.keys(rhs); if (lhsKeys.length !== rhsKeys.length) return false; for (let i = 0; i < lhsKeys.length; i++) { const key = lhsKeys[i]; if (!rhs.hasOwnProperty(key)) return false; if (!equalfn.call(context, lhs[key], rhs[key])) return false; } for (let i = 0; i < rhsKeys.length; i++) if (!lhs.hasOwnProperty(rhsKeys[i])) return false; return true; } export function hash(obj: any, hashfn: Hash<[any, any]>, seed = 0, context?: any) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; seed = (seed + hashfn.call(context, [key, obj[key]])) >>> 0; } return seed; } export function restore(obj: any, state: any, restorefn: Restore, createfn: Create, context?: any) { const objKeys = Object.keys(obj); const stateKeys = Object.keys(state); for (let i = 0; i < objKeys.length; i++) { const key = objKeys[i]; if (!has(state, key)) { delete obj[key]; continue; } obj[key] = restorefn.call(context, obj[key], state[key]); } for (let i = 0; i < stateKeys.length; i++) { const key = stateKeys[i]; if (!obj.hasOwnProperty(key)) obj[key] = createfn.call(context, state[key]); } return obj; } export function stringify(obj: any, stringifyfn: Stringify, context?: any) { return Object.keys(obj).map(key => `${quoteKey(key)}: ${stringifyfn.call(context, obj[key])}`).join(', '); } export const $assign = deepAssign(assign); export const $clone = deepClone(clone); export const $compare = deepCompare(compare); export const $construct = genericConstruct; export const $create = genericCreate; export const $dump = deepDump(dump); export const $equal = deepEqual(equal); export const $hash = deepHash(hash); export const $restore = deepRestore(restore); export const $serialize = primitiveSerialize; export const $stringify = deepStringify(stringify, stringifyObjectWrapper); export const $constructor = Object; export const $name = 'Object'; 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 };