import { $NAME, MetaContext, MetaObject } from '../../MetaContext'; export const $COMPARE = '$compare'; export type Compare = (lhs: T, rhs: T) => number; export type $Compare = { [$COMPARE]: Compare }; export const withCompare = MetaContext>(MetaContextBase: TMetaContextBase) => class extends MetaContextBase { [$COMPARE](lhs: T, rhs: T) { const $lhs = this.resolveValue(lhs); const $rhs = this.resolveValue(rhs); if ($lhs !== $rhs) throw new TypeError(`MetaContext.${$COMPARE}(): type missmatch '${$lhs[$NAME]}' !== '${$rhs[$NAME]}'`); return $lhs[$COMPARE](lhs, rhs, this) as number; } }; export type GenericCompare = (lhs: T, rhs: T, comparefn: Compare, context: any) => number; export function deepCompare(genericCompare: GenericCompare) { return function $compare(this: MetaObject, lhs: T, rhs: T, context: MetaContext & $Compare) { const comparefn = context[$COMPARE]; return (this[$COMPARE] = function $compare(lhs: T, rhs: T, context: MetaContext) { return genericCompare(lhs, rhs, comparefn, context); })(lhs, rhs, context); }; } export function primitiveWrapperCompare(lhs: T, rhs: T, context: MetaContext & $Compare) { return context[$COMPARE](lhs.valueOf(), rhs.valueOf()); }