Adjust sorting (#3819)

* Adjust sorting

* typo
This commit is contained in:
Jaco
2021-07-28 07:40:46 +02:00
committed by GitHub
parent 9a4893130d
commit a281e0dc2d
+30 -21
View File
@@ -1,12 +1,13 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '@polkadot/util';
import type { Codec } from '../../types';
import type { Enum } from '../Enum';
import { isBn, isFunction, isNumber, stringify } from '@polkadot/util';
import { bnToBn, isBigInt, isBn, isFunction, isNumber, stringify } from '@polkadot/util';
type SortArg = Codec | Codec[] | number[] | number | Uint8Array
type SortArg = Codec | Codec[] | number[] | BN | bigint | number | Uint8Array;
/** @internal **/
function isArrayLike (arg: SortArg): arg is Uint8Array | Codec[] | number[] {
@@ -23,40 +24,48 @@ function isEnum (arg: SortArg): arg is Enum {
return isCodec(arg) && isNumber((arg as Enum).index) && isCodec((arg as Enum).value);
}
/** @internal */
function isNumberLike (arg: SortArg): arg is BN | bigint | number {
return isNumber(arg) || isBn(arg) || isBigInt(arg);
}
/** @internal */
function sortArray (a: Uint8Array | Codec[] | number[], b: Uint8Array | Codec[] | number[]): number {
// Vec, Tuple, Bytes etc.
let sortRes = 0;
const minLen = Math.min(a.length, b.length);
for (let i = 0; i < minLen; ++i) {
sortRes = sortAsc(a[i], b[i]);
if (sortRes !== 0) {
return sortRes;
}
}
return a.length - b.length;
}
/**
* Sort keys/values of BTreeSet/BTreeMap in acending order for encoding compatibility with Rust's BTreeSet/BTreeMap
* Sort keys/values of BTreeSet/BTreeMap in ascending order for encoding compatibility with Rust's BTreeSet/BTreeMap
* (https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html)
* (https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html)
*/
export function sortAsc<V extends SortArg = Codec> (a: V, b: V): number {
if (isNumber(a) && isNumber(b)) {
return a - b;
if (isNumberLike(a) && isNumberLike(b)) {
return bnToBn(a).cmp(bnToBn(b));
} else if (a instanceof Map && b instanceof Map) {
return sortAsc(Array.from(a.values()), Array.from(b.values()));
} else if (isEnum(a) && isEnum(b)) {
return sortAsc(a.index, b.index) || sortAsc(a.value, b.value);
} else if (isArrayLike(a) && isArrayLike(b)) {
// Vec, Tuple, Bytes etc.
let sortRes = 0;
const minLen = Math.min(a.length, b.length);
for (let i = 0; i < minLen; ++i) {
sortRes = sortAsc(a[i], b[i]);
if (sortRes !== 0) {
return sortRes;
}
}
return a.length - b.length;
} else if (isBn(a) && isBn(b)) {
return a.cmp(b);
return sortArray(a, b);
} else if (isCodec(a) && isCodec(b)) {
// Text, Bool etc.
return sortAsc(a.toU8a(true), b.toU8a(true));
}
throw new Error(`Attempting to sort unrecognized value: ${stringify(a)}`);
throw new Error(`Attempting to sort unrecognized values: ${stringify(a)} (typeof ${typeof a}) <-> ${stringify(b)} (typeof ${typeof b})`);
}
export function sortSet<V extends Codec = Codec> (set: Set<V>): Set<V> {