import { $NAME, MetaContext, MetaObject } from '../../MetaContext'; export const $HASH = '$hash'; export type Hash = (obj: T, seed?: number) => number; export type $Hash = { [$HASH]: Hash }; export type HashString = { hashString(str: string, seed?: number): number }; export type HashNumber = { hashNumber(value: number, seed?: number): number }; export const withHash = MetaContext & HashString & HashNumber>(MetaContextBase: TMetaContextBase) => class extends MetaContextBase { [$HASH](value: T, seed?: number) { return this.resolveValue(value)[$HASH](value, seed, this) as number; } }; export type GenericHash = (obj: T, hashfn: Hash, seed: number, context: any) => number; export function deepHash(hash: GenericHash) { return function $hash(this: MetaObject, obj: T, seed: number, context: MetaContext & $Hash) { const hashfn = context[$HASH]; return (this[$HASH] = function $hash(this: MetaObject, obj: T, seed: number, context: MetaContext & $Hash) { return hash(obj, hashfn, seed, context); }).call(this, obj, seed, context) as number; }; } export function hashMetaObjectName(metaObject: MetaObject, seed: number, context: MetaContext & HashString & HashNumber) { return context.hashNumber(context.hashString(metaObject[$NAME]), seed); }