@aeternity/aepp-calldata
Version:
Aeternity data serialization library
170 lines (157 loc) • 4.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _assert = _interopRequireDefault(require("./utils/assert.cjs"));
var _FateList = _interopRequireDefault(require("./types/FateList.cjs"));
var _FateTuple = _interopRequireDefault(require("./types/FateTuple.cjs"));
var _FateTypes = require("./FateTypes.cjs");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/* eslint-disable no-use-before-define */
// TODO types comparator
const listComparator = (a, b) => {
if (a.length === 0) {
return -1;
}
if (b.length === 0) {
return 1;
}
const cmp = FateComparator(a.itemsType);
for (let i = 0; i < a.length; i++) {
// second list is shorter but matches as prefix of the first one
if (typeof b.items[i] === 'undefined') {
return 1;
}
// element difference
const diff = cmp(a.items[i], b.items[i]);
if (diff !== 0) {
return diff;
}
}
// if there is no early return from the loop above
// then the first list match a prefix of the second
// equal lists
if (a.length === b.length) {
return 0;
}
// first list is shorter, thus smaller
return -1;
};
const tupleComparator = (a, b) => {
if (a.size === 0) {
return -1;
}
const sizeDiff = a.size - b.size;
if (sizeDiff !== 0) {
return sizeDiff;
}
// equal size - compare elements
for (let i = 0; i < a.size; i++) {
const valTypeA = a.valueTypes[i];
// TODO support different types ?
const diff = FateComparator(valTypeA)(a.items[i], b.items[i]);
if (diff !== 0) {
return diff;
}
}
// equal tuples
return 0;
};
const variantComparator = (a, b) => {
const aDiff = a.arities.length - b.arities.length;
if (aDiff !== 0) {
return aDiff;
}
const aList = new _FateList.default(a.aritiesType, a.arities);
const bList = new _FateList.default(b.aritiesType, b.arities);
const aComparator = FateComparator(aList);
const lDiff = aComparator(aList, bList);
if (lDiff !== 0) {
return lDiff;
}
const tDiff = a.tag - b.tag;
if (tDiff !== 0) {
return tDiff;
}
// equal arities and tags - compare elements
const elementsComparator = FateComparator((0, _FateTypes.FateTypeTuple)());
return elementsComparator(new _FateTuple.default(a.valueTypes, a.value), new _FateTuple.default(b.valueTypes, b.value));
};
const mapItemComparator = type => {
const keyComparator = FateComparator(type);
return (a, b) => keyComparator(a.key, b.key);
};
const mapComparator = (a, b) => {
const aItems = [...a.items];
const bItems = [...b.items];
aItems.sort(mapItemComparator(a.keyType));
bItems.sort(mapItemComparator(b.keyType));
const keyComparator = FateComparator(a.keyType);
const valueComparator = FateComparator(a.valueType);
for (let i = 0; i < aItems.length; i++) {
// second map is smaller (less items)
if (typeof bItems[i] === 'undefined') {
return 1;
}
const aItem = aItems[i];
const bItem = bItems[i];
const kDiff = keyComparator(aItem.key, bItem.key);
if (kDiff !== 0) {
return kDiff;
}
const vDiff = valueComparator(aItem.value, bItem.value);
if (vDiff !== 0) {
return vDiff;
}
}
// equal number of items
if (aItems.length === bItems.length) {
return 0;
}
// first map item list is shorter, thus smaller
return -1;
};
const bytesComparator = (a, b) => {
const aList = new _FateList.default((0, _FateTypes.FateTypeInt)(), a.valueOf());
const bList = new _FateList.default((0, _FateTypes.FateTypeInt)(), b.valueOf());
return listComparator(aList, bList);
};
const stringComparator = (a, b) => {
const encoder = new TextEncoder();
const as = a.toString();
const bs = b.toString();
if (as.length === bs.length) {
return bytesComparator(encoder.encode(a), encoder.encode(b));
}
return as.length - bs.length;
};
const intComparator = (a, b) => Number(BigInt(a) - BigInt(b));
const boolComparator = (a, b) => a - b;
const bitsComparator = (a, b) => {
return a < 0 || b < 0 ? -intComparator(a, b) : intComparator(a, b);
};
const comparators = {
'int': intComparator,
'bool': boolComparator,
'string': stringComparator,
'bits': bitsComparator,
// composite types
'list': listComparator,
'tuple': tupleComparator,
'variant': variantComparator,
'map': mapComparator,
// objects (bytes)
'bytes': bytesComparator,
'account_pubkey': bytesComparator,
'channel': bytesComparator,
'contract_pubkey': bytesComparator,
'oracle_query_id': bytesComparator,
'oracle_pubkey': bytesComparator
};
const FateComparator = type => {
(0, _assert.default)(type.hasOwnProperty('name'), `Cannot determine type name of ${JSON.stringify(type)}`);
(0, _assert.default)(comparators.hasOwnProperty(type.name), `Unsupported comparator for ${type.name}`);
return comparators[type.name];
};
var _default = exports.default = FateComparator;