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.
Files changed (216) hide show
  1. package/README.md +405 -60
  2. package/dist/array/index.d.ts +9 -0
  3. package/dist/array/index.js +9 -0
  4. package/dist/array/list.d.ts +99 -0
  5. package/dist/array/list.js +133 -0
  6. package/dist/array/sets.d.ts +130 -0
  7. package/dist/array/sets.js +213 -0
  8. package/dist/async/index.d.ts +6 -0
  9. package/dist/async/index.js +6 -0
  10. package/dist/async/retry.d.ts +38 -0
  11. package/dist/async/retry.js +56 -0
  12. package/dist/async/sleep.d.ts +42 -0
  13. package/dist/async/sleep.js +76 -0
  14. package/dist/collections/bisect.d.ts +103 -0
  15. package/dist/collections/bisect.js +157 -0
  16. package/dist/collections/deque.d.ts +67 -97
  17. package/dist/collections/deque.js +197 -249
  18. package/dist/collections/entries.d.ts +89 -0
  19. package/dist/collections/entries.js +131 -0
  20. package/dist/collections/frozen-set.d.ts +42 -0
  21. package/dist/collections/frozen-set.js +64 -0
  22. package/dist/collections/group.d.ts +141 -0
  23. package/dist/collections/group.js +241 -0
  24. package/dist/collections/heap.d.ts +64 -0
  25. package/dist/collections/heap.js +205 -0
  26. package/dist/collections/index.d.ts +15 -642
  27. package/dist/collections/index.js +14 -716
  28. package/dist/collections/internal/arrayKeys.d.ts +19 -0
  29. package/dist/collections/internal/arrayKeys.js +83 -0
  30. package/dist/collections/internal/invariants.d.ts +4 -0
  31. package/dist/collections/internal/invariants.js +12 -0
  32. package/dist/collections/internal/iterable.d.ts +25 -0
  33. package/dist/collections/internal/iterable.js +62 -0
  34. package/dist/collections/iterate.d.ts +162 -0
  35. package/dist/collections/iterate.js +188 -0
  36. package/dist/collections/lru-cache.d.ts +58 -0
  37. package/dist/collections/lru-cache.js +164 -0
  38. package/dist/collections/order.d.ts +19 -0
  39. package/dist/collections/order.js +38 -0
  40. package/dist/collections/shape.d.ts +32 -0
  41. package/dist/collections/shape.js +86 -0
  42. package/dist/collections/sorted-map.d.ts +171 -0
  43. package/dist/collections/sorted-map.js +845 -0
  44. package/dist/collections/sorted-set.d.ts +103 -0
  45. package/dist/collections/sorted-set.js +147 -0
  46. package/dist/collections/splay-tree.d.ts +82 -0
  47. package/dist/collections/splay-tree.js +354 -0
  48. package/dist/collections/trie.d.ts +58 -0
  49. package/dist/collections/trie.js +196 -0
  50. package/dist/decimal/currency.d.ts +211 -0
  51. package/dist/decimal/currency.js +321 -0
  52. package/dist/decimal/decimal.d.ts +299 -0
  53. package/dist/decimal/decimal.js +660 -0
  54. package/dist/decimal/index.d.ts +11 -145
  55. package/dist/decimal/index.js +10 -374
  56. package/dist/decimal/internal/bits.d.ts +2 -0
  57. package/dist/decimal/internal/bits.js +7 -0
  58. package/dist/decimal/internal/echo.d.ts +4 -0
  59. package/dist/decimal/internal/echo.js +6 -0
  60. package/dist/decimal/internal/isqrt.d.ts +9 -0
  61. package/dist/decimal/internal/isqrt.js +34 -0
  62. package/dist/decimal/internal/locale.d.ts +7 -0
  63. package/dist/decimal/internal/locale.js +24 -0
  64. package/dist/decimal/internal/minor-units.d.ts +2 -0
  65. package/dist/decimal/internal/minor-units.js +33 -0
  66. package/dist/decimal/internal/pow10.d.ts +24 -0
  67. package/dist/decimal/internal/pow10.js +96 -0
  68. package/dist/encoding/base64.d.ts +39 -0
  69. package/dist/encoding/base64.js +53 -0
  70. package/dist/encoding/hex.d.ts +23 -0
  71. package/dist/encoding/hex.js +34 -0
  72. package/dist/encoding/index.d.ts +6 -0
  73. package/dist/encoding/index.js +6 -0
  74. package/dist/function/debounce.d.ts +68 -0
  75. package/dist/function/debounce.js +203 -0
  76. package/dist/function/index.d.ts +6 -0
  77. package/dist/function/index.js +6 -0
  78. package/dist/function/shared.d.ts +2 -0
  79. package/dist/function/shared.js +5 -0
  80. package/dist/function/wrap.d.ts +130 -0
  81. package/dist/function/wrap.js +113 -0
  82. package/dist/hash/digest.d.ts +18 -0
  83. package/dist/hash/digest.js +26 -0
  84. package/dist/hash/hash.d.ts +22 -0
  85. package/dist/hash/hash.js +252 -0
  86. package/dist/hash/hashString.d.ts +13 -0
  87. package/dist/hash/hashString.js +53 -0
  88. package/dist/hash/index.d.ts +8 -0
  89. package/dist/hash/index.js +8 -0
  90. package/dist/hash/stableStringify.d.ts +19 -0
  91. package/dist/hash/stableStringify.js +102 -0
  92. package/dist/id/index.d.ts +7 -0
  93. package/dist/id/index.js +7 -0
  94. package/dist/id/nanoid.d.ts +16 -0
  95. package/dist/id/nanoid.js +65 -0
  96. package/dist/id/uniqueId.d.ts +14 -0
  97. package/dist/id/uniqueId.js +20 -0
  98. package/dist/id/uuid.d.ts +25 -0
  99. package/dist/id/uuid.js +64 -0
  100. package/dist/index.d.ts +15 -8
  101. package/dist/index.js +15 -8
  102. package/dist/internal/bytes.d.ts +11 -0
  103. package/dist/internal/bytes.js +33 -0
  104. package/dist/internal/codec.d.ts +11 -0
  105. package/dist/internal/codec.js +84 -0
  106. package/dist/internal/compare.d.ts +10 -0
  107. package/dist/internal/compare.js +26 -0
  108. package/dist/internal/crypto.d.ts +5 -0
  109. package/dist/internal/crypto.js +11 -0
  110. package/dist/internal/keys.d.ts +12 -0
  111. package/dist/internal/keys.js +23 -0
  112. package/dist/internal/kind.d.ts +44 -0
  113. package/dist/internal/kind.js +139 -0
  114. package/dist/internal/sparse.d.ts +51 -0
  115. package/dist/internal/sparse.js +104 -0
  116. package/dist/internal/text.d.ts +7 -0
  117. package/dist/internal/text.js +15 -0
  118. package/dist/internal/timer.d.ts +10 -0
  119. package/dist/internal/timer.js +17 -0
  120. package/dist/internal/truncate.d.ts +10 -0
  121. package/dist/internal/truncate.js +22 -0
  122. package/dist/internal/walk.d.ts +47 -0
  123. package/dist/internal/walk.js +100 -0
  124. package/dist/is/index.d.ts +8 -0
  125. package/dist/is/index.js +8 -0
  126. package/dist/is/isArrayLike.d.ts +18 -0
  127. package/dist/is/isArrayLike.js +25 -0
  128. package/dist/is/isError.d.ts +13 -0
  129. package/dist/is/isError.js +18 -0
  130. package/dist/is/isNil.d.ts +12 -0
  131. package/dist/is/isNil.js +14 -0
  132. package/dist/is/isPlainObject.d.ts +15 -0
  133. package/dist/is/isPlainObject.js +34 -0
  134. package/dist/number/index.d.ts +7 -0
  135. package/dist/number/index.js +7 -0
  136. package/dist/number/round.d.ts +86 -0
  137. package/dist/number/round.js +130 -0
  138. package/dist/number/stats.d.ts +52 -0
  139. package/dist/number/stats.js +115 -0
  140. package/dist/object/cloneDeep.d.ts +28 -0
  141. package/dist/object/cloneDeep.js +200 -0
  142. package/dist/object/index.d.ts +14 -0
  143. package/dist/object/index.js +13 -0
  144. package/dist/object/isEqual.d.ts +64 -0
  145. package/dist/object/isEqual.js +289 -0
  146. package/dist/object/matches.d.ts +40 -0
  147. package/dist/object/matches.js +284 -0
  148. package/dist/object/merge.d.ts +66 -0
  149. package/dist/object/merge.js +272 -0
  150. package/dist/object/parsePath.d.ts +22 -0
  151. package/dist/object/parsePath.js +111 -0
  152. package/dist/object/path.d.ts +85 -0
  153. package/dist/object/path.js +208 -0
  154. package/dist/object/pick.d.ts +91 -0
  155. package/dist/object/pick.js +180 -0
  156. package/dist/object/reshape.d.ts +73 -0
  157. package/dist/object/reshape.js +144 -0
  158. package/dist/random/index.d.ts +96 -32
  159. package/dist/random/index.js +215 -50
  160. package/dist/string/case.d.ts +71 -0
  161. package/dist/string/case.js +152 -0
  162. package/dist/string/fold.d.ts +35 -0
  163. package/dist/string/fold.js +100 -0
  164. package/dist/string/index.d.ts +6 -187
  165. package/dist/string/index.js +6 -226
  166. package/dist/string/truncate.d.ts +25 -0
  167. package/dist/string/truncate.js +44 -0
  168. package/dist/string/words.d.ts +27 -0
  169. package/dist/string/words.js +241 -0
  170. package/package.json +101 -58
  171. package/dist/collections/BTree.d.ts +0 -229
  172. package/dist/collections/BTree.js +0 -1165
  173. package/dist/collections/Heap.d.ts +0 -69
  174. package/dist/collections/Heap.js +0 -181
  175. package/dist/collections/LRUCache.d.ts +0 -80
  176. package/dist/collections/LRUCache.js +0 -126
  177. package/dist/collections/SortedMap.d.ts +0 -92
  178. package/dist/collections/SortedMap.js +0 -131
  179. package/dist/collections/SortedSet.d.ts +0 -69
  180. package/dist/collections/SortedSet.js +0 -99
  181. package/dist/collections/SortedTree.d.ts +0 -103
  182. package/dist/collections/SortedTree.js +0 -141
  183. package/dist/collections/SplayTree.d.ts +0 -105
  184. package/dist/collections/SplayTree.js +0 -338
  185. package/dist/collections/Trie.d.ts +0 -42
  186. package/dist/collections/Trie.js +0 -104
  187. package/dist/collections/abc.d.ts +0 -152
  188. package/dist/collections/abc.js +0 -39
  189. package/dist/collections/frozenset.d.ts +0 -19
  190. package/dist/collections/frozenset.js +0 -30
  191. package/dist/functools/index.d.ts +0 -130
  192. package/dist/functools/index.js +0 -235
  193. package/dist/globals/index.d.ts +0 -285
  194. package/dist/globals/index.js +0 -463
  195. package/dist/i18n/currency.d.ts +0 -24
  196. package/dist/i18n/currency.js +0 -85
  197. package/dist/i18n/date/index.d.ts +0 -203
  198. package/dist/i18n/date/index.js +0 -531
  199. package/dist/i18n/date/utils.d.ts +0 -65
  200. package/dist/i18n/date/utils.js +0 -290
  201. package/dist/i18n/duration.d.ts +0 -112
  202. package/dist/i18n/duration.js +0 -392
  203. package/dist/i18n/format.d.ts +0 -31
  204. package/dist/i18n/format.js +0 -506
  205. package/dist/i18n/index.d.ts +0 -8
  206. package/dist/i18n/index.js +0 -8
  207. package/dist/itertools/index.d.ts +0 -255
  208. package/dist/itertools/index.js +0 -437
  209. package/dist/math/index.d.ts +0 -96
  210. package/dist/math/index.js +0 -98
  211. package/dist/mod.d.ts +0 -1
  212. package/dist/mod.js +0 -1
  213. package/dist/operators/index.d.ts +0 -152
  214. package/dist/operators/index.js +0 -305
  215. package/dist/types.d.ts +0 -19
  216. package/dist/types.js +0 -1
@@ -1,291 +1,239 @@
1
- import { KeyError, ValueError } from '../globals/index.js';
2
- import { IterableIterator } from '../itertools/index.js';
3
- import { eq } from '../operators/index.js';
4
- import { Sequence } from './abc.js';
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
- * Fixed capacity double-ended queue implemented as ring deque.
7
- * @template T
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 extends Sequence {
10
- items;
11
- start = 0;
12
- count = 0;
13
- capacity;
14
- ArrayConstructor;
15
- /**
16
- * Creates a new `Deque` instance of a fixed size.
17
- * @param {Array} [arrType = []] The initial elements or array type to use (accepts any kind of typed array).
18
- * @param {number} [capacity=1024] The fixed size of the deque. Defaults to `1024`.
19
- */
20
- constructor(arrType = [], capacity = 1024) {
21
- super();
22
- if (typeof capacity !== 'number' || capacity <= 0)
23
- throw new ValueError(`Deque capacity should be a positive integer.`);
24
- this.ArrayConstructor = arrType.constructor;
25
- this.capacity = capacity;
26
- this.items = new this.ArrayConstructor(arrType.length || this.capacity);
27
- this.clear();
28
- if (arrType.length) {
29
- for (const item of arrType) {
30
- this.append(item);
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
- /** Returns the total number of elements in the deque. */
61
+ /** The number of elements. */
35
62
  get size() {
36
- return this.count;
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
- * Removes and returns the element at the end of the deque.
83
- * @returns {?T} Returns the popped item.
66
+ * Maximum size when constructed with a finite `maxlen`, otherwise `undefined`.
84
67
  */
85
- pop() {
86
- if (this.count === 0)
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
- * Alias of {@link Deque.pop}
94
- * @returns {?T} Returns the popped item.
95
- */
96
- remove() {
97
- return this.pop();
71
+ /** `'Deque'`, for `Object.prototype.toString`. */
72
+ get [Symbol.toStringTag]() {
73
+ return 'Deque';
98
74
  }
99
- /**
100
- * Removes and returns the element at the beginning of the deque.
101
- * @returns {?T} Returns the removed deque element.
102
- */
103
- popleft() {
104
- if (this.count === 0)
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
- * Returns the element at the beginning of the deque.
115
- * @returns {?T} The element if exists
83
+ * Append one or more elements at the end.
84
+ * @returns The new size.
116
85
  */
117
- first() {
118
- if (this.count === 0)
119
- return;
120
- return this.items[this.start];
86
+ push(...xs) {
87
+ for (const x of xs)
88
+ this.#pushOne(x);
89
+ return this.#size;
121
90
  }
122
91
  /**
123
- * Returns the element at a specified index position in the deque.
124
- * @param {number} index The given index
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
- get(index) {
128
- if (this.count === 0)
129
- return;
130
- index = this.start + index;
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
- * Update the element at a given `index`.
139
- * @param {number} index The given index
101
+ * Remove and return the last element, or `undefined` when empty.
140
102
  */
141
- set(index, value) {
142
- if (index < 0)
143
- index += this.count;
144
- if (index > this.count)
145
- throw new KeyError(`Invalid index: ${index} not in Deque.`);
146
- this.items[index] = value;
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
- * Check if a given element is in the deque.
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
- contains(x) {
154
- for (const value of this.values()) {
155
- if (eq(x, value))
156
- return true;
157
- }
158
- return false;
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
- * Returns the first element that matches the `iteratee` function.
162
- * @param {Iteratee<T>} iteratee A function that will be invoked per element
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
- find(iteratee) {
166
- for (const [key, value] of this.entries()) {
167
- if (iteratee(value, key, this))
168
- return value;
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
- * Calls `iteratee` function for every element in the deque.
173
- * @param {Iteratee<T>} iteratee A function that will be invoked per element
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
- forEach(iteratee) {
176
- const c = this.capacity;
177
- const l = this.count;
178
- let i = this.start;
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
- * Returns a new array with all the elements in reverse order.
190
- * @returns {Array<T>} The elements reversed
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
- * Returns a new array with all the elements in the order they were added to the deque.
197
- * @returns {Array<T>} The elements array
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
- * Returns an iterator over the deque's values.
220
- * @returns {Iterator}
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
- * Alias of {@link Deque.values}. Returns iterator of values.
244
- */
245
- keys() {
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
- * Creates an iterator of `[index, value]` pairs for all elements in the deque.
250
- * @returns {Iterator}
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
- [Symbol.for('nodejs.util.inspect.custom')]() {
277
- return this.inspect();
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
- // This is just for debugging in nodejs
280
- inspect() {
281
- const array = this.toArray();
282
- array.type = this.ArrayConstructor.name;
283
- array.capacity = this.capacity;
284
- // Trick so that node displays the name of the constructor
285
- Object.defineProperty(array, 'constructor', {
286
- value: Deque,
287
- enumerable: false
288
- });
289
- return array;
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;