atomic-fns 1.1.7 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +405 -60
- package/dist/array/index.d.ts +9 -0
- package/dist/array/index.js +9 -0
- package/dist/array/list.d.ts +99 -0
- package/dist/array/list.js +133 -0
- package/dist/array/sets.d.ts +130 -0
- package/dist/array/sets.js +213 -0
- package/dist/async/index.d.ts +6 -0
- package/dist/async/index.js +6 -0
- package/dist/async/retry.d.ts +38 -0
- package/dist/async/retry.js +56 -0
- package/dist/async/sleep.d.ts +42 -0
- package/dist/async/sleep.js +76 -0
- package/dist/collections/bisect.d.ts +103 -0
- package/dist/collections/bisect.js +157 -0
- package/dist/collections/deque.d.ts +67 -97
- package/dist/collections/deque.js +197 -249
- package/dist/collections/entries.d.ts +89 -0
- package/dist/collections/entries.js +131 -0
- package/dist/collections/frozen-set.d.ts +42 -0
- package/dist/collections/frozen-set.js +64 -0
- package/dist/collections/group.d.ts +141 -0
- package/dist/collections/group.js +241 -0
- package/dist/collections/heap.d.ts +64 -0
- package/dist/collections/heap.js +205 -0
- package/dist/collections/index.d.ts +15 -642
- package/dist/collections/index.js +14 -716
- package/dist/collections/internal/arrayKeys.d.ts +19 -0
- package/dist/collections/internal/arrayKeys.js +83 -0
- package/dist/collections/internal/invariants.d.ts +4 -0
- package/dist/collections/internal/invariants.js +12 -0
- package/dist/collections/internal/iterable.d.ts +25 -0
- package/dist/collections/internal/iterable.js +62 -0
- package/dist/collections/iterate.d.ts +162 -0
- package/dist/collections/iterate.js +188 -0
- package/dist/collections/lru-cache.d.ts +58 -0
- package/dist/collections/lru-cache.js +164 -0
- package/dist/collections/order.d.ts +19 -0
- package/dist/collections/order.js +38 -0
- package/dist/collections/shape.d.ts +32 -0
- package/dist/collections/shape.js +86 -0
- package/dist/collections/sorted-map.d.ts +171 -0
- package/dist/collections/sorted-map.js +845 -0
- package/dist/collections/sorted-set.d.ts +103 -0
- package/dist/collections/sorted-set.js +147 -0
- package/dist/collections/splay-tree.d.ts +82 -0
- package/dist/collections/splay-tree.js +354 -0
- package/dist/collections/trie.d.ts +58 -0
- package/dist/collections/trie.js +196 -0
- package/dist/decimal/currency.d.ts +211 -0
- package/dist/decimal/currency.js +321 -0
- package/dist/decimal/decimal.d.ts +299 -0
- package/dist/decimal/decimal.js +660 -0
- package/dist/decimal/index.d.ts +11 -145
- package/dist/decimal/index.js +10 -374
- package/dist/decimal/internal/bits.d.ts +2 -0
- package/dist/decimal/internal/bits.js +7 -0
- package/dist/decimal/internal/echo.d.ts +4 -0
- package/dist/decimal/internal/echo.js +6 -0
- package/dist/decimal/internal/isqrt.d.ts +9 -0
- package/dist/decimal/internal/isqrt.js +34 -0
- package/dist/decimal/internal/locale.d.ts +7 -0
- package/dist/decimal/internal/locale.js +24 -0
- package/dist/decimal/internal/minor-units.d.ts +2 -0
- package/dist/decimal/internal/minor-units.js +33 -0
- package/dist/decimal/internal/pow10.d.ts +24 -0
- package/dist/decimal/internal/pow10.js +96 -0
- package/dist/encoding/base64.d.ts +39 -0
- package/dist/encoding/base64.js +53 -0
- package/dist/encoding/hex.d.ts +23 -0
- package/dist/encoding/hex.js +34 -0
- package/dist/encoding/index.d.ts +6 -0
- package/dist/encoding/index.js +6 -0
- package/dist/function/debounce.d.ts +68 -0
- package/dist/function/debounce.js +203 -0
- package/dist/function/index.d.ts +6 -0
- package/dist/function/index.js +6 -0
- package/dist/function/shared.d.ts +2 -0
- package/dist/function/shared.js +5 -0
- package/dist/function/wrap.d.ts +130 -0
- package/dist/function/wrap.js +113 -0
- package/dist/hash/digest.d.ts +18 -0
- package/dist/hash/digest.js +26 -0
- package/dist/hash/hash.d.ts +22 -0
- package/dist/hash/hash.js +252 -0
- package/dist/hash/hashString.d.ts +13 -0
- package/dist/hash/hashString.js +53 -0
- package/dist/hash/index.d.ts +8 -0
- package/dist/hash/index.js +8 -0
- package/dist/hash/stableStringify.d.ts +19 -0
- package/dist/hash/stableStringify.js +102 -0
- package/dist/id/index.d.ts +7 -0
- package/dist/id/index.js +7 -0
- package/dist/id/nanoid.d.ts +16 -0
- package/dist/id/nanoid.js +65 -0
- package/dist/id/uniqueId.d.ts +14 -0
- package/dist/id/uniqueId.js +20 -0
- package/dist/id/uuid.d.ts +25 -0
- package/dist/id/uuid.js +64 -0
- package/dist/index.d.ts +15 -8
- package/dist/index.js +15 -8
- package/dist/internal/bytes.d.ts +11 -0
- package/dist/internal/bytes.js +33 -0
- package/dist/internal/codec.d.ts +11 -0
- package/dist/internal/codec.js +84 -0
- package/dist/internal/compare.d.ts +10 -0
- package/dist/internal/compare.js +26 -0
- package/dist/internal/crypto.d.ts +5 -0
- package/dist/internal/crypto.js +11 -0
- package/dist/internal/keys.d.ts +12 -0
- package/dist/internal/keys.js +23 -0
- package/dist/internal/kind.d.ts +44 -0
- package/dist/internal/kind.js +139 -0
- package/dist/internal/sparse.d.ts +51 -0
- package/dist/internal/sparse.js +104 -0
- package/dist/internal/text.d.ts +7 -0
- package/dist/internal/text.js +15 -0
- package/dist/internal/timer.d.ts +10 -0
- package/dist/internal/timer.js +17 -0
- package/dist/internal/truncate.d.ts +10 -0
- package/dist/internal/truncate.js +22 -0
- package/dist/internal/walk.d.ts +47 -0
- package/dist/internal/walk.js +100 -0
- package/dist/is/index.d.ts +8 -0
- package/dist/is/index.js +8 -0
- package/dist/is/isArrayLike.d.ts +18 -0
- package/dist/is/isArrayLike.js +25 -0
- package/dist/is/isError.d.ts +13 -0
- package/dist/is/isError.js +18 -0
- package/dist/is/isNil.d.ts +12 -0
- package/dist/is/isNil.js +14 -0
- package/dist/is/isPlainObject.d.ts +15 -0
- package/dist/is/isPlainObject.js +34 -0
- package/dist/number/index.d.ts +7 -0
- package/dist/number/index.js +7 -0
- package/dist/number/round.d.ts +86 -0
- package/dist/number/round.js +130 -0
- package/dist/number/stats.d.ts +52 -0
- package/dist/number/stats.js +115 -0
- package/dist/object/cloneDeep.d.ts +28 -0
- package/dist/object/cloneDeep.js +200 -0
- package/dist/object/index.d.ts +14 -0
- package/dist/object/index.js +13 -0
- package/dist/object/isEqual.d.ts +64 -0
- package/dist/object/isEqual.js +289 -0
- package/dist/object/matches.d.ts +40 -0
- package/dist/object/matches.js +284 -0
- package/dist/object/merge.d.ts +66 -0
- package/dist/object/merge.js +272 -0
- package/dist/object/parsePath.d.ts +22 -0
- package/dist/object/parsePath.js +111 -0
- package/dist/object/path.d.ts +85 -0
- package/dist/object/path.js +208 -0
- package/dist/object/pick.d.ts +91 -0
- package/dist/object/pick.js +180 -0
- package/dist/object/reshape.d.ts +73 -0
- package/dist/object/reshape.js +144 -0
- package/dist/random/index.d.ts +96 -32
- package/dist/random/index.js +215 -50
- package/dist/string/case.d.ts +71 -0
- package/dist/string/case.js +152 -0
- package/dist/string/fold.d.ts +35 -0
- package/dist/string/fold.js +100 -0
- package/dist/string/index.d.ts +6 -187
- package/dist/string/index.js +6 -226
- package/dist/string/truncate.d.ts +25 -0
- package/dist/string/truncate.js +44 -0
- package/dist/string/words.d.ts +27 -0
- package/dist/string/words.js +241 -0
- package/package.json +101 -58
- package/dist/collections/BTree.d.ts +0 -229
- package/dist/collections/BTree.js +0 -1165
- package/dist/collections/Heap.d.ts +0 -69
- package/dist/collections/Heap.js +0 -181
- package/dist/collections/LRUCache.d.ts +0 -80
- package/dist/collections/LRUCache.js +0 -126
- package/dist/collections/SortedMap.d.ts +0 -92
- package/dist/collections/SortedMap.js +0 -131
- package/dist/collections/SortedSet.d.ts +0 -69
- package/dist/collections/SortedSet.js +0 -99
- package/dist/collections/SortedTree.d.ts +0 -103
- package/dist/collections/SortedTree.js +0 -141
- package/dist/collections/SplayTree.d.ts +0 -105
- package/dist/collections/SplayTree.js +0 -338
- package/dist/collections/Trie.d.ts +0 -42
- package/dist/collections/Trie.js +0 -104
- package/dist/collections/abc.d.ts +0 -152
- package/dist/collections/abc.js +0 -39
- package/dist/collections/frozenset.d.ts +0 -19
- package/dist/collections/frozenset.js +0 -30
- package/dist/functools/index.d.ts +0 -130
- package/dist/functools/index.js +0 -235
- package/dist/globals/index.d.ts +0 -285
- package/dist/globals/index.js +0 -463
- package/dist/i18n/currency.d.ts +0 -24
- package/dist/i18n/currency.js +0 -85
- package/dist/i18n/date/index.d.ts +0 -203
- package/dist/i18n/date/index.js +0 -531
- package/dist/i18n/date/utils.d.ts +0 -65
- package/dist/i18n/date/utils.js +0 -290
- package/dist/i18n/duration.d.ts +0 -112
- package/dist/i18n/duration.js +0 -392
- package/dist/i18n/format.d.ts +0 -31
- package/dist/i18n/format.js +0 -506
- package/dist/i18n/index.d.ts +0 -8
- package/dist/i18n/index.js +0 -8
- package/dist/itertools/index.d.ts +0 -255
- package/dist/itertools/index.js +0 -437
- package/dist/math/index.d.ts +0 -96
- package/dist/math/index.js +0 -98
- package/dist/mod.d.ts +0 -1
- package/dist/mod.js +0 -1
- package/dist/operators/index.d.ts +0 -152
- package/dist/operators/index.js +0 -305
- package/dist/types.d.ts +0 -19
- package/dist/types.js +0 -1
|
@@ -1,291 +1,239 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { assertNotHugeSparse } from './internal/arrayKeys.js';
|
|
2
|
+
import { sameValueZero } from '../internal/compare.js';
|
|
3
|
+
import { iteratesAsArray, requireIterable } from './internal/iterable.js';
|
|
4
|
+
const MIN_CAPACITY = 8;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* A double-ended queue on a ring buffer, with Array's method names: `push` and `pop` at the end,
|
|
7
|
+
* `unshift` and `shift` at the front, `at` and `set` by index, all O(1) amortized. It grows by
|
|
8
|
+
* doubling when unbounded; with `maxlen` it evicts from the opposite end, as Python's `deque` does.
|
|
9
|
+
* `includes` uses SameValueZero.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const recent = new Deque<number>([], { maxlen: 3 })
|
|
14
|
+
* recent.push(1, 2, 3, 4)
|
|
15
|
+
* ;[...recent] // [2, 3, 4]
|
|
16
|
+
* recent.shift() // 2
|
|
17
|
+
* ```
|
|
8
18
|
*/
|
|
9
|
-
export class Deque
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
export class Deque {
|
|
20
|
+
#buf;
|
|
21
|
+
#cap;
|
|
22
|
+
#head = 0;
|
|
23
|
+
#size = 0;
|
|
24
|
+
#maxlen;
|
|
25
|
+
#arrType;
|
|
26
|
+
#empty;
|
|
27
|
+
/**
|
|
28
|
+
* Create a deque holding `items`, in order.
|
|
29
|
+
* @param items Initial elements, read one at a time. When longer than `maxlen`, only the last
|
|
30
|
+
* `maxlen` remain.
|
|
31
|
+
* @param options.maxlen Maximum size; overflow evicts from the opposite end. `0` makes push/unshift
|
|
32
|
+
* no-ops. `null`, `undefined` and `Infinity` mean unbounded.
|
|
33
|
+
* @param options.arrType Typed-array (or similar) constructor used for storage.
|
|
34
|
+
* @throws {TypeError} when `items` is not iterable, or `maxlen` is not a number, `null` or
|
|
35
|
+
* `undefined`.
|
|
36
|
+
* @throws {RangeError} when `maxlen` is negative, not an integer, or above
|
|
37
|
+
* `Number.MAX_SAFE_INTEGER`, or when `items` is a huge sparse array.
|
|
38
|
+
*/
|
|
39
|
+
constructor(items, options) {
|
|
40
|
+
const maxlen = options?.maxlen ?? undefined;
|
|
41
|
+
if (maxlen !== undefined && typeof maxlen !== 'number') {
|
|
42
|
+
throw new TypeError('maxlen must be a number');
|
|
43
|
+
}
|
|
44
|
+
if (maxlen !== undefined &&
|
|
45
|
+
maxlen !== Infinity &&
|
|
46
|
+
(!Number.isInteger(maxlen) || maxlen < 0 || maxlen > Number.MAX_SAFE_INTEGER)) {
|
|
47
|
+
throw new RangeError('maxlen must be a non-negative integer <= Number.MAX_SAFE_INTEGER or Infinity');
|
|
48
|
+
}
|
|
49
|
+
this.#maxlen = maxlen === Infinity ? undefined : maxlen;
|
|
50
|
+
this.#arrType = options?.arrType;
|
|
51
|
+
this.#empty = this.#alloc(1)[0];
|
|
52
|
+
const source = requireIterable(items ?? []);
|
|
53
|
+
if (iteratesAsArray(source))
|
|
54
|
+
assertNotHugeSparse(source);
|
|
55
|
+
this.#cap = MIN_CAPACITY;
|
|
56
|
+
this.#buf = this.#alloc(this.#cap);
|
|
57
|
+
for (const x of source) {
|
|
58
|
+
this.#pushOne(x);
|
|
32
59
|
}
|
|
33
60
|
}
|
|
34
|
-
/**
|
|
61
|
+
/** The number of elements. */
|
|
35
62
|
get size() {
|
|
36
|
-
return this
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Method used to clear the structure.
|
|
40
|
-
*/
|
|
41
|
-
clear() {
|
|
42
|
-
// Properties
|
|
43
|
-
this.start = 0;
|
|
44
|
-
this.count = 0;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Alias of {@link Deque.append}
|
|
48
|
-
* @param {T} item Item to append.
|
|
49
|
-
* @returns {number} Returns the new size of the deque.
|
|
50
|
-
*/
|
|
51
|
-
add(item) {
|
|
52
|
-
return this.append(item);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Appends a new element to the end of the deque.
|
|
56
|
-
* @param {T} item Item to append.
|
|
57
|
-
* @returns {number} Returns the new size of the deque.
|
|
58
|
-
*/
|
|
59
|
-
append(item) {
|
|
60
|
-
if (this.count === this.capacity)
|
|
61
|
-
this.popleft();
|
|
62
|
-
const index = (this.start + this.count) % this.capacity;
|
|
63
|
-
this.items[index] = item;
|
|
64
|
-
return ++this.count;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Appends a new element to the beginning of the deque.
|
|
68
|
-
* @param {T} item Item to prepend.
|
|
69
|
-
* @returns {number} Returns the new size of the deque.
|
|
70
|
-
*/
|
|
71
|
-
appendleft(item) {
|
|
72
|
-
if (this.count === this.capacity)
|
|
73
|
-
this.pop();
|
|
74
|
-
let index = this.start - 1;
|
|
75
|
-
if (this.start === 0)
|
|
76
|
-
index = this.capacity - 1;
|
|
77
|
-
this.items[index] = item;
|
|
78
|
-
this.start = index;
|
|
79
|
-
return ++this.count;
|
|
63
|
+
return this.#size;
|
|
80
64
|
}
|
|
81
65
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @returns {?T} Returns the popped item.
|
|
66
|
+
* Maximum size when constructed with a finite `maxlen`, otherwise `undefined`.
|
|
84
67
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return;
|
|
88
|
-
const index = (this.start + this.count - 1) % this.capacity;
|
|
89
|
-
this.count--;
|
|
90
|
-
return this.items[index];
|
|
68
|
+
get maxlen() {
|
|
69
|
+
return this.#maxlen;
|
|
91
70
|
}
|
|
92
|
-
/**
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
*/
|
|
96
|
-
remove() {
|
|
97
|
-
return this.pop();
|
|
71
|
+
/** `'Deque'`, for `Object.prototype.toString`. */
|
|
72
|
+
get [Symbol.toStringTag]() {
|
|
73
|
+
return 'Deque';
|
|
98
74
|
}
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return;
|
|
106
|
-
const index = this.start;
|
|
107
|
-
this.count--;
|
|
108
|
-
this.start++;
|
|
109
|
-
if (this.start === this.capacity)
|
|
110
|
-
this.start = 0;
|
|
111
|
-
return this.items[index];
|
|
75
|
+
/** Remove every element and give back the buffer a burst grew. */
|
|
76
|
+
clear() {
|
|
77
|
+
this.#cap = MIN_CAPACITY;
|
|
78
|
+
this.#buf = this.#alloc(this.#cap);
|
|
79
|
+
this.#head = 0;
|
|
80
|
+
this.#size = 0;
|
|
112
81
|
}
|
|
113
82
|
/**
|
|
114
|
-
*
|
|
115
|
-
* @returns
|
|
83
|
+
* Append one or more elements at the end.
|
|
84
|
+
* @returns The new size.
|
|
116
85
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return this
|
|
86
|
+
push(...xs) {
|
|
87
|
+
for (const x of xs)
|
|
88
|
+
this.#pushOne(x);
|
|
89
|
+
return this.#size;
|
|
121
90
|
}
|
|
122
91
|
/**
|
|
123
|
-
*
|
|
124
|
-
* @
|
|
125
|
-
* @returns {?T} The element if exists
|
|
92
|
+
* Insert one or more elements at the front, preserving argument order.
|
|
93
|
+
* @returns The new size.
|
|
126
94
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (index < 0)
|
|
132
|
-
index += this.count;
|
|
133
|
-
if (index > this.capacity)
|
|
134
|
-
index -= this.capacity;
|
|
135
|
-
return this.items[index];
|
|
95
|
+
unshift(...xs) {
|
|
96
|
+
for (let i = xs.length - 1; i >= 0; i--)
|
|
97
|
+
this.#unshiftOne(xs[i]);
|
|
98
|
+
return this.#size;
|
|
136
99
|
}
|
|
137
100
|
/**
|
|
138
|
-
*
|
|
139
|
-
* @param {number} index The given index
|
|
101
|
+
* Remove and return the last element, or `undefined` when empty.
|
|
140
102
|
*/
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this
|
|
103
|
+
pop() {
|
|
104
|
+
if (this.#size === 0)
|
|
105
|
+
return undefined;
|
|
106
|
+
const j = this.#phys(this.#size - 1);
|
|
107
|
+
const x = this.#buf[j];
|
|
108
|
+
this.#buf[j] = this.#empty;
|
|
109
|
+
this.#size--;
|
|
110
|
+
return x;
|
|
147
111
|
}
|
|
148
112
|
/**
|
|
149
|
-
*
|
|
150
|
-
* @param {T} x The value to find
|
|
151
|
-
* @returns {boolean} `true` if the value is found
|
|
113
|
+
* Remove and return the first element, or `undefined` when empty.
|
|
152
114
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
115
|
+
shift() {
|
|
116
|
+
if (this.#size === 0)
|
|
117
|
+
return undefined;
|
|
118
|
+
const x = this.#buf[this.#head];
|
|
119
|
+
this.#buf[this.#head] = this.#empty;
|
|
120
|
+
this.#head = (this.#head + 1) % this.#cap;
|
|
121
|
+
this.#size--;
|
|
122
|
+
return x;
|
|
159
123
|
}
|
|
160
124
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* @returns {?T} The element if exists
|
|
125
|
+
* Element at index `i` (negative from the end). Out of range or empty -> `undefined`.
|
|
126
|
+
* The index coerces as in `Array.prototype.at`; values that coerce to `NaN` mean `0`.
|
|
164
127
|
*/
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
128
|
+
at(i) {
|
|
129
|
+
const idx = this.#fromEnd(i);
|
|
130
|
+
if (idx < 0 || idx >= this.#size)
|
|
131
|
+
return undefined;
|
|
132
|
+
return this.#buf[this.#phys(idx)];
|
|
170
133
|
}
|
|
171
134
|
/**
|
|
172
|
-
*
|
|
173
|
-
* @
|
|
135
|
+
* Replace the element at index `i` (negative from the end). The index coerces as in {@link at}.
|
|
136
|
+
* @returns `this`
|
|
137
|
+
* @throws {RangeError} when the index is out of range.
|
|
174
138
|
*/
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
let j = 0;
|
|
180
|
-
while (j < l) {
|
|
181
|
-
iteratee(this.items[i], j, this);
|
|
182
|
-
i++;
|
|
183
|
-
j++;
|
|
184
|
-
if (i === c)
|
|
185
|
-
i = 0;
|
|
139
|
+
set(i, v) {
|
|
140
|
+
const idx = this.#fromEnd(i);
|
|
141
|
+
if (idx < 0 || idx >= this.#size) {
|
|
142
|
+
throw new RangeError(`index ${String(i).slice(0, 40)} out of range`);
|
|
186
143
|
}
|
|
144
|
+
this.#buf[this.#phys(idx)] = v;
|
|
145
|
+
return this;
|
|
187
146
|
}
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*/
|
|
192
|
-
reversed() {
|
|
193
|
-
return this.toArray().reverse();
|
|
147
|
+
/** Whether `value` is present (SameValueZero). */
|
|
148
|
+
includes(value) {
|
|
149
|
+
return this.values().some((v) => sameValueZero(v, value));
|
|
194
150
|
}
|
|
195
|
-
/**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
toArray() {
|
|
200
|
-
// Optimization
|
|
201
|
-
const offset = this.start + this.count;
|
|
202
|
-
if (offset < this.capacity)
|
|
203
|
-
return this.items.slice(this.start, offset);
|
|
204
|
-
const array = new this.ArrayConstructor(this.count);
|
|
205
|
-
const c = this.capacity;
|
|
206
|
-
const l = this.count;
|
|
207
|
-
let i = this.start;
|
|
208
|
-
let j = 0;
|
|
209
|
-
while (j < l) {
|
|
210
|
-
array[j] = this.items[i];
|
|
211
|
-
i++;
|
|
212
|
-
j++;
|
|
213
|
-
if (i === c)
|
|
214
|
-
i = 0;
|
|
151
|
+
/** Call `callback(element, index, deque)` for each element, front to back. */
|
|
152
|
+
forEach(callback, thisArg) {
|
|
153
|
+
for (let i = 0; i < this.#size; i++) {
|
|
154
|
+
Reflect.apply(callback, thisArg, [this.#buf[this.#phys(i)], i, this]);
|
|
215
155
|
}
|
|
216
|
-
return array;
|
|
217
156
|
}
|
|
218
|
-
/**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
values() {
|
|
223
|
-
const items = this.items;
|
|
224
|
-
const c = this.capacity;
|
|
225
|
-
const l = this.count;
|
|
226
|
-
let i = this.start;
|
|
227
|
-
let j = 0;
|
|
228
|
-
return IterableIterator(() => {
|
|
229
|
-
if (j >= l)
|
|
230
|
-
return {
|
|
231
|
-
done: true,
|
|
232
|
-
value: undefined
|
|
233
|
-
};
|
|
234
|
-
const value = items[i];
|
|
235
|
-
i++;
|
|
236
|
-
j++;
|
|
237
|
-
if (i === c)
|
|
238
|
-
i = 0;
|
|
239
|
-
return { value };
|
|
240
|
-
});
|
|
157
|
+
/** The indices, front to back, as `Array.prototype.keys` gives them. */
|
|
158
|
+
*keys() {
|
|
159
|
+
for (let i = 0; i < this.#size; i++)
|
|
160
|
+
yield i;
|
|
241
161
|
}
|
|
242
|
-
/**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return this.values();
|
|
162
|
+
/** The elements, front to back. */
|
|
163
|
+
*values() {
|
|
164
|
+
for (let i = 0; i < this.#size; i++)
|
|
165
|
+
yield this.#buf[this.#phys(i)];
|
|
247
166
|
}
|
|
248
|
-
/**
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
entries() {
|
|
253
|
-
const items = this.items;
|
|
254
|
-
const c = this.capacity;
|
|
255
|
-
const l = this.count;
|
|
256
|
-
let i = this.start;
|
|
257
|
-
let j = 0;
|
|
258
|
-
return IterableIterator(() => {
|
|
259
|
-
if (j >= l)
|
|
260
|
-
return {
|
|
261
|
-
done: true,
|
|
262
|
-
value: undefined
|
|
263
|
-
};
|
|
264
|
-
const value = items[i];
|
|
265
|
-
i++;
|
|
266
|
-
if (i === c)
|
|
267
|
-
i = 0;
|
|
268
|
-
return {
|
|
269
|
-
value: [j++, value]
|
|
270
|
-
};
|
|
271
|
-
});
|
|
167
|
+
/** `[index, element]` pairs, front to back. */
|
|
168
|
+
*entries() {
|
|
169
|
+
for (let i = 0; i < this.#size; i++)
|
|
170
|
+
yield [i, this.#buf[this.#phys(i)]];
|
|
272
171
|
}
|
|
172
|
+
/** The elements, front to back. */
|
|
273
173
|
[Symbol.iterator]() {
|
|
274
174
|
return this.values();
|
|
275
175
|
}
|
|
276
|
-
|
|
277
|
-
|
|
176
|
+
/** Index `i` as `Array.prototype.at` reads it: truncated, `NaN` as `0`, negative from the end. */
|
|
177
|
+
#fromEnd(i) {
|
|
178
|
+
const idx = Math.trunc(i) || 0;
|
|
179
|
+
return idx < 0 ? idx + this.#size : idx;
|
|
180
|
+
}
|
|
181
|
+
#phys(i) {
|
|
182
|
+
return (this.#head + i) % this.#cap;
|
|
183
|
+
}
|
|
184
|
+
#alloc(n) {
|
|
185
|
+
if (this.#arrType)
|
|
186
|
+
return new this.#arrType(n);
|
|
187
|
+
return new Array(n);
|
|
188
|
+
}
|
|
189
|
+
/** Double the buffer, clamped to `maxlen`. Called only when full and below `maxlen`. */
|
|
190
|
+
#grow() {
|
|
191
|
+
let newCap = this.#cap * 2;
|
|
192
|
+
if (this.#maxlen !== undefined)
|
|
193
|
+
newCap = Math.min(newCap, this.#maxlen);
|
|
194
|
+
const nb = this.#alloc(newCap);
|
|
195
|
+
for (let i = 0; i < this.#size; i++)
|
|
196
|
+
nb[i] = this.#buf[this.#phys(i)];
|
|
197
|
+
this.#buf = nb;
|
|
198
|
+
this.#cap = newCap;
|
|
199
|
+
this.#head = 0;
|
|
200
|
+
}
|
|
201
|
+
// Both inserts write the new slot before they move `#head` or `#size`, so a value that typed
|
|
202
|
+
// storage rejects leaves the deque as it was, the element it would evict included. At `maxlen`
|
|
203
|
+
// with a full buffer the new slot is the one being evicted, so the write itself evicts it.
|
|
204
|
+
#pushOne(x) {
|
|
205
|
+
if (this.#maxlen === 0)
|
|
206
|
+
return;
|
|
207
|
+
const atMaxlen = this.#size === this.#maxlen;
|
|
208
|
+
if (!atMaxlen && this.#size === this.#cap)
|
|
209
|
+
this.#grow();
|
|
210
|
+
const j = this.#phys(this.#size);
|
|
211
|
+
this.#buf[j] = x;
|
|
212
|
+
if (atMaxlen) {
|
|
213
|
+
if (j !== this.#head)
|
|
214
|
+
this.#buf[this.#head] = this.#empty;
|
|
215
|
+
this.#head = (this.#head + 1) % this.#cap;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
this.#size++;
|
|
219
|
+
}
|
|
278
220
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
221
|
+
#unshiftOne(x) {
|
|
222
|
+
if (this.#maxlen === 0)
|
|
223
|
+
return;
|
|
224
|
+
const atMaxlen = this.#size === this.#maxlen;
|
|
225
|
+
if (!atMaxlen && this.#size === this.#cap)
|
|
226
|
+
this.#grow();
|
|
227
|
+
const j = (this.#head - 1 + this.#cap) % this.#cap;
|
|
228
|
+
this.#buf[j] = x;
|
|
229
|
+
if (atMaxlen) {
|
|
230
|
+
const back = this.#phys(this.#size - 1);
|
|
231
|
+
if (j !== back)
|
|
232
|
+
this.#buf[back] = this.#empty;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this.#size++;
|
|
236
|
+
}
|
|
237
|
+
this.#head = j;
|
|
290
238
|
}
|
|
291
239
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a collection holds: `keys`, `values`, `entries`, `size`, `isEmpty`, `includes`.
|
|
3
|
+
*/
|
|
4
|
+
import { type Collection, type CollectionKey, type CollectionValue } from './shape.js';
|
|
5
|
+
/**
|
|
6
|
+
* The keys of `collection`: indices of an array (holes skipped), typed array, string (one per code
|
|
7
|
+
* point) or other iterable, the keys of a `Map`, the members of a `Set`, and the own enumerable
|
|
8
|
+
* string keys of any other object. `null`, `undefined`, numbers, booleans, bigints and symbols
|
|
9
|
+
* have none. Other iterables are consumed to obtain positions.
|
|
10
|
+
* @param collection The collection to read.
|
|
11
|
+
* @returns A new array of keys, in iteration order.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* keys({ a: 1, b: 2 }) // ['a', 'b']
|
|
15
|
+
* keys(new Map([['x', 1]])) // ['x']
|
|
16
|
+
* keys('héllo') // [0, 1, 2, 3, 4]
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function keys<C extends Collection>(collection: C): CollectionKey<C>[];
|
|
20
|
+
/**
|
|
21
|
+
* The values of `collection`, in the order {@link keys} gives their keys.
|
|
22
|
+
* @param collection The collection to read.
|
|
23
|
+
* @returns A new array of values.
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* values({ a: 1, b: 2 }) // [1, 2]
|
|
27
|
+
* values(new Map([['x', 1]])) // [1]
|
|
28
|
+
* values('👍🏽!') // ['👍', '🏽', '!']
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function values<C extends Collection>(collection: C): CollectionValue<C>[];
|
|
32
|
+
/**
|
|
33
|
+
* The `[key, value]` pairs of `collection`, as `Map.prototype.entries` gives them.
|
|
34
|
+
* @param collection The collection to read.
|
|
35
|
+
* @returns A new array of pairs.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* entries({ a: 1 }) // [['a', 1]]
|
|
39
|
+
* entries(['x', 'y']) // [[0, 'x'], [1, 'y']]
|
|
40
|
+
* entries(new Set(['s'])) // [['s', 's']]
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function entries<C extends Collection>(collection: C): [CollectionKey<C>, CollectionValue<C>][];
|
|
44
|
+
/**
|
|
45
|
+
* How many entries `collection` has: the `size` of a `Map` or `Set`, the present elements of an
|
|
46
|
+
* array (holes do not count), the length of a typed array, the code points of a string, the own
|
|
47
|
+
* enumerable string keys of an object. An iterable that is none of these is read to its end to
|
|
48
|
+
* count it, so a one-shot iterator such as a generator is exhausted.
|
|
49
|
+
* @param collection The collection to measure.
|
|
50
|
+
* @returns The number of entries.
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* size({ a: 1, b: 2 }) // 2
|
|
54
|
+
* size([1, , 3]) // 2
|
|
55
|
+
* size('👍🏽') // 2
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function size(collection: Collection): number;
|
|
59
|
+
/**
|
|
60
|
+
* True when `collection` has no entries, by the rules of {@link size}. An iterable is read only
|
|
61
|
+
* until its first element, and is then closed, so a one-shot iterator such as a generator has
|
|
62
|
+
* nothing left to give.
|
|
63
|
+
* @param collection The collection to test.
|
|
64
|
+
* @returns Whether it has no entries.
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* isEmpty({}) // true
|
|
68
|
+
* isEmpty([, ,]) // true
|
|
69
|
+
* isEmpty(new Map([[1, 2]])) // false
|
|
70
|
+
* isEmpty(null) // true
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function isEmpty(collection: Collection): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* True when `collection` holds `value`, compared with SameValueZero against its values (`NaN`
|
|
76
|
+
* finds `NaN`, `0` finds `-0`). For a string, `value` is a substring, as
|
|
77
|
+
* `String.prototype.includes` reads it. An iterable is read until the first match, where it is
|
|
78
|
+
* closed, or to its end, so a one-shot iterator such as a generator is used up either way.
|
|
79
|
+
* @param collection The collection to search.
|
|
80
|
+
* @param value The value to look for.
|
|
81
|
+
* @returns Whether it is there.
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* includes({ a: 1 }, 1) // true
|
|
85
|
+
* includes(new Map([['k', NaN]]), NaN) // true
|
|
86
|
+
* includes('hello', 'ell') // true
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function includes<C extends Collection>(collection: C, value: C extends string ? string : CollectionValue<C>): boolean;
|