1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport {isString} from './object_utils'; 16*6dbdd20aSAndroid Build Coastguard Worker 17*6dbdd20aSAndroid Build Coastguard Workerexport type ComparisonFn<X> = (a: X, b: X) => number; 18*6dbdd20aSAndroid Build Coastguard Worker 19*6dbdd20aSAndroid Build Coastguard Workerexport type SortDirection = 'DESC' | 'ASC'; 20*6dbdd20aSAndroid Build Coastguard Worker 21*6dbdd20aSAndroid Build Coastguard Worker// Having a comparison function of type S and a getter that returns value of 22*6dbdd20aSAndroid Build Coastguard Worker// type S from value of type T, values of type T can be compared. 23*6dbdd20aSAndroid Build Coastguard Workerexport function comparingBy<T, S>( 24*6dbdd20aSAndroid Build Coastguard Worker getter: (t: T) => S, 25*6dbdd20aSAndroid Build Coastguard Worker comparison: ComparisonFn<S>, 26*6dbdd20aSAndroid Build Coastguard Worker): ComparisonFn<T> { 27*6dbdd20aSAndroid Build Coastguard Worker return (x, y) => { 28*6dbdd20aSAndroid Build Coastguard Worker return comparison(getter(x), getter(y)); 29*6dbdd20aSAndroid Build Coastguard Worker }; 30*6dbdd20aSAndroid Build Coastguard Worker} 31*6dbdd20aSAndroid Build Coastguard Worker 32*6dbdd20aSAndroid Build Coastguard Workerexport function withDirection<T>( 33*6dbdd20aSAndroid Build Coastguard Worker comparison: ComparisonFn<T>, 34*6dbdd20aSAndroid Build Coastguard Worker sortDirection?: SortDirection, 35*6dbdd20aSAndroid Build Coastguard Worker): ComparisonFn<T> { 36*6dbdd20aSAndroid Build Coastguard Worker if (sortDirection !== 'DESC') { 37*6dbdd20aSAndroid Build Coastguard Worker return comparison; 38*6dbdd20aSAndroid Build Coastguard Worker } 39*6dbdd20aSAndroid Build Coastguard Worker 40*6dbdd20aSAndroid Build Coastguard Worker return (x, y) => { 41*6dbdd20aSAndroid Build Coastguard Worker return comparison(y, x); 42*6dbdd20aSAndroid Build Coastguard Worker }; 43*6dbdd20aSAndroid Build Coastguard Worker} 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Workerexport type SortableValue = 46*6dbdd20aSAndroid Build Coastguard Worker | string 47*6dbdd20aSAndroid Build Coastguard Worker | number 48*6dbdd20aSAndroid Build Coastguard Worker | bigint 49*6dbdd20aSAndroid Build Coastguard Worker | null 50*6dbdd20aSAndroid Build Coastguard Worker | Uint8Array 51*6dbdd20aSAndroid Build Coastguard Worker | undefined; 52*6dbdd20aSAndroid Build Coastguard Worker 53*6dbdd20aSAndroid Build Coastguard Workerfunction columnTypeKind(a: SortableValue): number { 54*6dbdd20aSAndroid Build Coastguard Worker if (a === undefined) { 55*6dbdd20aSAndroid Build Coastguard Worker return 0; 56*6dbdd20aSAndroid Build Coastguard Worker } 57*6dbdd20aSAndroid Build Coastguard Worker if (a === null) { 58*6dbdd20aSAndroid Build Coastguard Worker return 1; 59*6dbdd20aSAndroid Build Coastguard Worker } 60*6dbdd20aSAndroid Build Coastguard Worker if (typeof a === 'number') { 61*6dbdd20aSAndroid Build Coastguard Worker return 2; 62*6dbdd20aSAndroid Build Coastguard Worker } 63*6dbdd20aSAndroid Build Coastguard Worker if (isString(a)) { 64*6dbdd20aSAndroid Build Coastguard Worker return 3; 65*6dbdd20aSAndroid Build Coastguard Worker } 66*6dbdd20aSAndroid Build Coastguard Worker // a instanceof Uint8Array 67*6dbdd20aSAndroid Build Coastguard Worker return 4; 68*6dbdd20aSAndroid Build Coastguard Worker} 69*6dbdd20aSAndroid Build Coastguard Worker 70*6dbdd20aSAndroid Build Coastguard Workerexport function compareUniversal(a: SortableValue, b: SortableValue): number { 71*6dbdd20aSAndroid Build Coastguard Worker if (a === undefined && b === undefined) { 72*6dbdd20aSAndroid Build Coastguard Worker return 0; 73*6dbdd20aSAndroid Build Coastguard Worker } 74*6dbdd20aSAndroid Build Coastguard Worker if (a === null && b === null) { 75*6dbdd20aSAndroid Build Coastguard Worker return 0; 76*6dbdd20aSAndroid Build Coastguard Worker } 77*6dbdd20aSAndroid Build Coastguard Worker if (typeof a === 'number' && typeof b === 'number') { 78*6dbdd20aSAndroid Build Coastguard Worker return a - b; 79*6dbdd20aSAndroid Build Coastguard Worker } 80*6dbdd20aSAndroid Build Coastguard Worker if (isString(a) && isString(b)) { 81*6dbdd20aSAndroid Build Coastguard Worker return a.localeCompare(b); 82*6dbdd20aSAndroid Build Coastguard Worker } 83*6dbdd20aSAndroid Build Coastguard Worker if (a instanceof Uint8Array && b instanceof Uint8Array) { 84*6dbdd20aSAndroid Build Coastguard Worker // Do the lexicographical comparison 85*6dbdd20aSAndroid Build Coastguard Worker for (let i = 0; i < a.length && i < b.length; i++) { 86*6dbdd20aSAndroid Build Coastguard Worker if (a[i] < b[i]) { 87*6dbdd20aSAndroid Build Coastguard Worker return -1; 88*6dbdd20aSAndroid Build Coastguard Worker } 89*6dbdd20aSAndroid Build Coastguard Worker if (a[i] > b[i]) { 90*6dbdd20aSAndroid Build Coastguard Worker return 1; 91*6dbdd20aSAndroid Build Coastguard Worker } 92*6dbdd20aSAndroid Build Coastguard Worker } 93*6dbdd20aSAndroid Build Coastguard Worker // No discrepancies found in the common prefix, compare lengths of arrays. 94*6dbdd20aSAndroid Build Coastguard Worker return a.length - b.length; 95*6dbdd20aSAndroid Build Coastguard Worker } 96*6dbdd20aSAndroid Build Coastguard Worker 97*6dbdd20aSAndroid Build Coastguard Worker // Values are of different kinds, compare the kinds 98*6dbdd20aSAndroid Build Coastguard Worker return columnTypeKind(a) - columnTypeKind(b); 99*6dbdd20aSAndroid Build Coastguard Worker} 100