-
Notifications
You must be signed in to change notification settings - Fork 225
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Move natural-sort functionality into packages/internal (#10320)
Ref endojs/endo#2113 ## Description Removes unnecessary use of `localeCompare` and consolidates natural-order sorting. ### Security Considerations n/a ### Scaling Considerations n/a ### Documentation Considerations n/a ### Testing Considerations None in particular, although I probably should add something to packages/internal/test. ### Upgrade Considerations This code runs outside of all vats (and AFAIK is not exercised on-chain at all) and is safe to include in any release.
- Loading branch information
Showing
3 changed files
with
65 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* @param {string} a | ||
* @param {string} b | ||
* @returns {-1 | 0 | 1} | ||
*/ | ||
const compareNats = (a, b) => { | ||
// Default to IEEE 754 number arithmetic for speed, but fall back on bigint | ||
// arithmetic to resolve ties because big numbers can lose resolution | ||
// (sometimes even becoming infinite) and then ultimately on length to resolve | ||
// ties by ascending count of leading zeros. | ||
const diff = +a - +b; | ||
const finiteDiff = | ||
(Number.isFinite(diff) && diff) || | ||
(a === b ? 0 : Number(BigInt(a) - BigInt(b)) || a.length - b.length); | ||
|
||
// @ts-expect-error this call really does return -1 | 0 | 1 | ||
return Math.sign(finiteDiff); | ||
}; | ||
|
||
// TODO: compareByCodePoints | ||
// https://github.com/endojs/endo/pull/2008 | ||
// eslint-disable-next-line no-nested-ternary | ||
const compareStrings = (a, b) => (a > b ? 1 : a < b ? -1 : 0); | ||
|
||
const rPrefixedDigits = /^(\D*)(\d+)(\D.*|)/s; | ||
|
||
/** | ||
* Perform a single-level natural-sort comparison, finding the first decimal | ||
* digit sequence in each operand and comparing first by the (possibly empty) | ||
* preceding prefix as strings, then by the digits as integers, then by any | ||
* following suffix (e.g., sorting 'ko42' before 'ko100' as ['ko', 42] vs. | ||
* ['ko', 100]). | ||
* | ||
* @param {string} a | ||
* @param {string} b | ||
* @returns {-1 | 0 | 1} | ||
*/ | ||
export const naturalCompare = (a, b) => { | ||
const [_a, aPrefix, aDigits, aSuffix] = rPrefixedDigits.exec(a) || []; | ||
if (aPrefix !== undefined) { | ||
const [_b, bPrefix, bDigits, bSuffix] = rPrefixedDigits.exec(b) || []; | ||
if (bPrefix === aPrefix) { | ||
return compareNats(aDigits, bDigits) || compareStrings(aSuffix, bSuffix); | ||
} | ||
} | ||
return compareStrings(a, b); | ||
}; | ||
harden(naturalCompare); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters