atomic-fns 1.2.0 → 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 +397 -91
- 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 -256
- 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 -623
- package/dist/collections/index.js +14 -844
- 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 -148
- package/dist/decimal/index.js +10 -410
- 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 -53
- 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 -224
- 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 +99 -51
- package/dist/collections/BTree.d.ts +0 -230
- package/dist/collections/BTree.js +0 -1143
- package/dist/collections/Heap.d.ts +0 -69
- package/dist/collections/Heap.js +0 -181
- package/dist/collections/LRUCache.d.ts +0 -83
- package/dist/collections/LRUCache.js +0 -139
- 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 -142
- package/dist/collections/SplayTree.d.ts +0 -107
- package/dist/collections/SplayTree.js +0 -351
- 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 -33
- package/dist/functools/index.d.ts +0 -106
- package/dist/functools/index.js +0 -203
- package/dist/globals/index.d.ts +0 -268
- package/dist/globals/index.js +0 -447
- package/dist/i18n/currency.d.ts +0 -27
- package/dist/i18n/currency.js +0 -100
- package/dist/i18n/date/index.d.ts +0 -210
- package/dist/i18n/date/index.js +0 -552
- package/dist/i18n/date/utils.d.ts +0 -64
- package/dist/i18n/date/utils.js +0 -192
- package/dist/i18n/duration.d.ts +0 -113
- package/dist/i18n/duration.js +0 -398
- package/dist/i18n/format.d.ts +0 -34
- package/dist/i18n/format.js +0 -378
- package/dist/i18n/index.d.ts +0 -9
- package/dist/i18n/index.js +0 -8
- package/dist/itertools/index.d.ts +0 -251
- package/dist/itertools/index.js +0 -434
- package/dist/math/index.d.ts +0 -79
- package/dist/math/index.js +0 -81
- package/dist/mod.d.ts +0 -1
- package/dist/mod.js +0 -1
- package/dist/operators/index.d.ts +0 -148
- package/dist/operators/index.js +0 -325
- package/dist/types.d.ts +0 -19
- package/dist/types.js +0 -1
|
@@ -1,298 +1,239 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
return {
|
|
6
|
-
next,
|
|
7
|
-
[Symbol.iterator]() {
|
|
8
|
-
return this;
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
}
|
|
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;
|
|
12
5
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
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
|
+
* ```
|
|
15
18
|
*/
|
|
16
|
-
export class Deque
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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);
|
|
41
59
|
}
|
|
42
60
|
}
|
|
43
|
-
/**
|
|
61
|
+
/** The number of elements. */
|
|
44
62
|
get size() {
|
|
45
|
-
return this
|
|
63
|
+
return this.#size;
|
|
46
64
|
}
|
|
47
65
|
/**
|
|
48
|
-
*
|
|
66
|
+
* Maximum size when constructed with a finite `maxlen`, otherwise `undefined`.
|
|
49
67
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.start = 0;
|
|
53
|
-
this.count = 0;
|
|
68
|
+
get maxlen() {
|
|
69
|
+
return this.#maxlen;
|
|
54
70
|
}
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
* @returns {number} Returns the new size of the deque.
|
|
59
|
-
*/
|
|
60
|
-
add(item) {
|
|
61
|
-
return this.append(item);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Appends a new element to the end of the deque.
|
|
65
|
-
* @param {T} item Item to append.
|
|
66
|
-
* @returns {number} Returns the new size of the deque.
|
|
67
|
-
*/
|
|
68
|
-
append(item) {
|
|
69
|
-
if (this.count === this.capacity)
|
|
70
|
-
this.popleft();
|
|
71
|
-
const index = (this.start + this.count) % this.capacity;
|
|
72
|
-
this.items[index] = item;
|
|
73
|
-
return ++this.count;
|
|
71
|
+
/** `'Deque'`, for `Object.prototype.toString`. */
|
|
72
|
+
get [Symbol.toStringTag]() {
|
|
73
|
+
return 'Deque';
|
|
74
74
|
}
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (this.count === this.capacity)
|
|
82
|
-
this.pop();
|
|
83
|
-
let index = this.start - 1;
|
|
84
|
-
if (this.start === 0)
|
|
85
|
-
index = this.capacity - 1;
|
|
86
|
-
this.items[index] = item;
|
|
87
|
-
this.start = index;
|
|
88
|
-
return ++this.count;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Removes and returns the element at the end of the deque.
|
|
92
|
-
* @returns {?T} Returns the popped item.
|
|
93
|
-
*/
|
|
94
|
-
pop() {
|
|
95
|
-
if (this.count === 0)
|
|
96
|
-
return;
|
|
97
|
-
const index = (this.start + this.count - 1) % this.capacity;
|
|
98
|
-
this.count--;
|
|
99
|
-
return this.items[index];
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Alias of {@link Deque.pop}
|
|
103
|
-
* @returns {?T} Returns the popped item.
|
|
104
|
-
*/
|
|
105
|
-
remove() {
|
|
106
|
-
return this.pop();
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Removes and returns the element at the beginning of the deque.
|
|
110
|
-
* @returns {?T} Returns the removed deque element.
|
|
111
|
-
*/
|
|
112
|
-
popleft() {
|
|
113
|
-
if (this.count === 0)
|
|
114
|
-
return;
|
|
115
|
-
const index = this.start;
|
|
116
|
-
this.count--;
|
|
117
|
-
this.start++;
|
|
118
|
-
if (this.start === this.capacity)
|
|
119
|
-
this.start = 0;
|
|
120
|
-
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;
|
|
121
81
|
}
|
|
122
82
|
/**
|
|
123
|
-
*
|
|
124
|
-
* @returns
|
|
83
|
+
* Append one or more elements at the end.
|
|
84
|
+
* @returns The new size.
|
|
125
85
|
*/
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return this
|
|
86
|
+
push(...xs) {
|
|
87
|
+
for (const x of xs)
|
|
88
|
+
this.#pushOne(x);
|
|
89
|
+
return this.#size;
|
|
130
90
|
}
|
|
131
91
|
/**
|
|
132
|
-
*
|
|
133
|
-
* @
|
|
134
|
-
* @returns {?T} The element if exists
|
|
92
|
+
* Insert one or more elements at the front, preserving argument order.
|
|
93
|
+
* @returns The new size.
|
|
135
94
|
*/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return;
|
|
141
|
-
return this.items[(this.start + index) % this.capacity];
|
|
95
|
+
unshift(...xs) {
|
|
96
|
+
for (let i = xs.length - 1; i >= 0; i--)
|
|
97
|
+
this.#unshiftOne(xs[i]);
|
|
98
|
+
return this.#size;
|
|
142
99
|
}
|
|
143
100
|
/**
|
|
144
|
-
*
|
|
145
|
-
* @param {number} index The given index
|
|
101
|
+
* Remove and return the last element, or `undefined` when empty.
|
|
146
102
|
*/
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
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;
|
|
154
111
|
}
|
|
155
112
|
/**
|
|
156
|
-
*
|
|
157
|
-
* @param {T} x The value to find
|
|
158
|
-
* @returns {boolean} `true` if the value is found
|
|
113
|
+
* Remove and return the first element, or `undefined` when empty.
|
|
159
114
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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;
|
|
166
123
|
}
|
|
167
124
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* @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`.
|
|
171
127
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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)];
|
|
177
133
|
}
|
|
178
134
|
/**
|
|
179
|
-
*
|
|
180
|
-
* @
|
|
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.
|
|
181
138
|
*/
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
let j = 0;
|
|
187
|
-
while (j < l) {
|
|
188
|
-
iteratee(this.items[i], j, this);
|
|
189
|
-
i++;
|
|
190
|
-
j++;
|
|
191
|
-
if (i === c)
|
|
192
|
-
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`);
|
|
193
143
|
}
|
|
144
|
+
this.#buf[this.#phys(idx)] = v;
|
|
145
|
+
return this;
|
|
194
146
|
}
|
|
195
|
-
/**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
*/
|
|
199
|
-
reversed() {
|
|
200
|
-
return this.toArray().reverse();
|
|
147
|
+
/** Whether `value` is present (SameValueZero). */
|
|
148
|
+
includes(value) {
|
|
149
|
+
return this.values().some((v) => sameValueZero(v, value));
|
|
201
150
|
}
|
|
202
|
-
/**
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
toArray() {
|
|
207
|
-
// Optimization
|
|
208
|
-
const offset = this.start + this.count;
|
|
209
|
-
if (offset < this.capacity)
|
|
210
|
-
return this.items.slice(this.start, offset);
|
|
211
|
-
const array = new this.ArrayConstructor(this.count);
|
|
212
|
-
const c = this.capacity;
|
|
213
|
-
const l = this.count;
|
|
214
|
-
let i = this.start;
|
|
215
|
-
let j = 0;
|
|
216
|
-
while (j < l) {
|
|
217
|
-
array[j] = this.items[i];
|
|
218
|
-
i++;
|
|
219
|
-
j++;
|
|
220
|
-
if (i === c)
|
|
221
|
-
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]);
|
|
222
155
|
}
|
|
223
|
-
return array;
|
|
224
156
|
}
|
|
225
|
-
/**
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
values() {
|
|
230
|
-
const items = this.items;
|
|
231
|
-
const c = this.capacity;
|
|
232
|
-
const l = this.count;
|
|
233
|
-
let i = this.start;
|
|
234
|
-
let j = 0;
|
|
235
|
-
return IterableIterator(() => {
|
|
236
|
-
if (j >= l)
|
|
237
|
-
return {
|
|
238
|
-
done: true,
|
|
239
|
-
value: undefined
|
|
240
|
-
};
|
|
241
|
-
const value = items[i];
|
|
242
|
-
i++;
|
|
243
|
-
j++;
|
|
244
|
-
if (i === c)
|
|
245
|
-
i = 0;
|
|
246
|
-
return { value };
|
|
247
|
-
});
|
|
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;
|
|
248
161
|
}
|
|
249
|
-
/**
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
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)];
|
|
254
166
|
}
|
|
255
|
-
/**
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
entries() {
|
|
260
|
-
const items = this.items;
|
|
261
|
-
const c = this.capacity;
|
|
262
|
-
const l = this.count;
|
|
263
|
-
let i = this.start;
|
|
264
|
-
let j = 0;
|
|
265
|
-
return IterableIterator(() => {
|
|
266
|
-
if (j >= l)
|
|
267
|
-
return {
|
|
268
|
-
done: true,
|
|
269
|
-
value: undefined
|
|
270
|
-
};
|
|
271
|
-
const value = items[i];
|
|
272
|
-
i++;
|
|
273
|
-
if (i === c)
|
|
274
|
-
i = 0;
|
|
275
|
-
return {
|
|
276
|
-
value: [j++, value]
|
|
277
|
-
};
|
|
278
|
-
});
|
|
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)]];
|
|
279
171
|
}
|
|
172
|
+
/** The elements, front to back. */
|
|
280
173
|
[Symbol.iterator]() {
|
|
281
174
|
return this.values();
|
|
282
175
|
}
|
|
283
|
-
|
|
284
|
-
|
|
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
|
+
}
|
|
285
220
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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;
|
|
297
238
|
}
|
|
298
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;
|