-
-
Notifications
You must be signed in to change notification settings - Fork 641
/
cmp.ts
91 lines (84 loc) · 2.34 KB
/
cmp.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Implementation of https://www.w3.org/TR/IndexedDB-3/#compare-two-keys
import { toStringTag } from './utils';
// ... with the adjustment to return NaN instead of throwing.
export function cmp(a: any, b: any): number {
try {
const ta = type(a);
const tb = type(b);
if (ta !== tb) {
if (ta === 'Array') return 1;
if (tb === 'Array') return -1;
if (ta === 'binary') return 1;
if (tb === 'binary') return -1;
if (ta === 'string') return 1;
if (tb === 'string') return -1;
if (ta === 'Date') return 1;
if (tb !== 'Date') return NaN;
return -1;
}
switch (ta) {
case 'number':
case 'Date':
case 'string':
return a > b ? 1 : a < b ? -1 : 0;
case 'binary': {
return compareUint8Arrays(getUint8Array(a), getUint8Array(b));
}
case 'Array':
return compareArrays(a, b);
}
} catch {}
return NaN; // Return value if any given args are valid keys.
}
export function compareArrays(a: any[], b: any[]): number {
const al = a.length;
const bl = b.length;
const l = al < bl ? al : bl;
for (let i = 0; i < l; ++i) {
const res = cmp(a[i], b[i]);
if (res !== 0) return res;
}
return al === bl ? 0 : al < bl ? -1 : 1;
}
export function compareUint8Arrays(
a: Uint8Array,
b: Uint8Array
) {
const al = a.length;
const bl = b.length;
const l = al < bl ? al : bl;
for (let i = 0; i < l; ++i) {
if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;
}
return al === bl ? 0 : al < bl ? -1 : 1;
}
// Implementation of https://www.w3.org/TR/IndexedDB-3/#key-type
function type(x: any) {
const t = typeof x;
if (t !== 'object') return t;
if (ArrayBuffer.isView(x)) return 'binary';
const tsTag = toStringTag(x); // Cannot use instanceof in Safari
return tsTag === 'ArrayBuffer' ? 'binary' : (tsTag as 'Array' | 'Date');
}
type BinaryType =
| ArrayBuffer
| DataView
| Uint8ClampedArray
| ArrayBufferView
| Uint8Array
| Int8Array
| Uint16Array
| Int16Array
| Uint32Array
| Int32Array
| Float32Array
| Float64Array
| BigInt64Array
| BigUint64Array;
function getUint8Array(a: BinaryType): Uint8Array {
if (a instanceof Uint8Array) return a;
if (ArrayBuffer.isView(a))
// TypedArray or DataView
return new Uint8Array(a.buffer, a.byteOffset, a.byteLength);
return new Uint8Array(a); // ArrayBuffer
}