happy-rusty 1.9.2 → 1.10.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/CHANGELOG.md +10 -0
- package/README.md +8 -3
- package/dist/main.cjs +138 -13
- package/dist/main.cjs.map +1 -1
- package/dist/main.mjs +138 -14
- package/dist/main.mjs.map +1 -1
- package/dist/types.d.ts +299 -2
- package/package.json +10 -10
package/dist/main.mjs
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*
|
|
22
22
|
* @internal
|
|
23
23
|
*/
|
|
24
|
-
const OptionKindSymbol =
|
|
24
|
+
const OptionKindSymbol = /*#__PURE__*/ Symbol("Option kind");
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/core/option/guards.ts
|
|
27
27
|
/**
|
|
@@ -66,7 +66,7 @@ function isOption(o) {
|
|
|
66
66
|
*
|
|
67
67
|
* @internal
|
|
68
68
|
*/
|
|
69
|
-
const ResultKindSymbol =
|
|
69
|
+
const ResultKindSymbol = /*#__PURE__*/ Symbol("Result kind");
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/core/result/guards.ts
|
|
72
72
|
/**
|
|
@@ -101,8 +101,8 @@ function isResult(r) {
|
|
|
101
101
|
* - `Err<T, E>(error)` - Creates a failed Result
|
|
102
102
|
* - `None` interface - Type overrides for better type inference
|
|
103
103
|
*/
|
|
104
|
-
const ASYNC_TRUE$1 =
|
|
105
|
-
const ASYNC_FALSE$1 =
|
|
104
|
+
const ASYNC_TRUE$1 = /*#__PURE__*/ Promise.resolve(true);
|
|
105
|
+
const ASYNC_FALSE$1 = /*#__PURE__*/ Promise.resolve(false);
|
|
106
106
|
/**
|
|
107
107
|
* Creates an `Option<T>` representing the presence of a value.
|
|
108
108
|
* This function is typically used to construct an `Option` that contains a value, indicating that the operation yielding the value was successful.
|
|
@@ -263,7 +263,7 @@ function Some(value) {
|
|
|
263
263
|
* const name = None.unwrapOr('Anonymous'); // 'Anonymous'
|
|
264
264
|
* ```
|
|
265
265
|
*/
|
|
266
|
-
const None =
|
|
266
|
+
const None = /*#__PURE__*/ Object.freeze({
|
|
267
267
|
[Symbol.toStringTag]: "Option",
|
|
268
268
|
[OptionKindSymbol]: "None",
|
|
269
269
|
*[Symbol.iterator]() {},
|
|
@@ -402,7 +402,7 @@ const None = /* @__PURE__ */ Object.freeze({
|
|
|
402
402
|
* }
|
|
403
403
|
* ```
|
|
404
404
|
*/
|
|
405
|
-
const ASYNC_NONE =
|
|
405
|
+
const ASYNC_NONE = /*#__PURE__*/ Promise.resolve(None);
|
|
406
406
|
function Ok(value) {
|
|
407
407
|
const ok = Object.freeze({
|
|
408
408
|
[Symbol.toStringTag]: "Result",
|
|
@@ -802,7 +802,7 @@ async function tryAsyncOption(task, ...args) {
|
|
|
802
802
|
* const value: boolean = RESULT_TRUE.intoOk(); // Safe extraction
|
|
803
803
|
* ```
|
|
804
804
|
*/
|
|
805
|
-
const RESULT_TRUE =
|
|
805
|
+
const RESULT_TRUE = /*#__PURE__*/ Ok(true);
|
|
806
806
|
/**
|
|
807
807
|
* Result constant for `false`.
|
|
808
808
|
* Can be used anywhere due to immutability.
|
|
@@ -817,7 +817,7 @@ const RESULT_TRUE = /* @__PURE__ */ Ok(true);
|
|
|
817
817
|
* const value: boolean = RESULT_FALSE.intoOk(); // Safe extraction
|
|
818
818
|
* ```
|
|
819
819
|
*/
|
|
820
|
-
const RESULT_FALSE =
|
|
820
|
+
const RESULT_FALSE = /*#__PURE__*/ Ok(false);
|
|
821
821
|
/**
|
|
822
822
|
* Result constant for `0`.
|
|
823
823
|
* Can be used anywhere due to immutability.
|
|
@@ -832,7 +832,7 @@ const RESULT_FALSE = /* @__PURE__ */ Ok(false);
|
|
|
832
832
|
* const value: number = RESULT_ZERO.intoOk(); // Safe extraction
|
|
833
833
|
* ```
|
|
834
834
|
*/
|
|
835
|
-
const RESULT_ZERO =
|
|
835
|
+
const RESULT_ZERO = /*#__PURE__*/ Ok(0);
|
|
836
836
|
/**
|
|
837
837
|
* Result constant for `void` or `()`.
|
|
838
838
|
* Can be used anywhere due to immutability.
|
|
@@ -847,7 +847,7 @@ const RESULT_ZERO = /* @__PURE__ */ Ok(0);
|
|
|
847
847
|
* RESULT_VOID.intoOk(); // Safe extraction (returns undefined)
|
|
848
848
|
* ```
|
|
849
849
|
*/
|
|
850
|
-
const RESULT_VOID =
|
|
850
|
+
const RESULT_VOID = /*#__PURE__*/ Ok();
|
|
851
851
|
//#endregion
|
|
852
852
|
//#region src/core/result/extensions.ts
|
|
853
853
|
/**
|
|
@@ -934,7 +934,7 @@ async function tryAsyncResult(task, ...args) {
|
|
|
934
934
|
*
|
|
935
935
|
* @internal
|
|
936
936
|
*/
|
|
937
|
-
const ControlFlowKindSymbol =
|
|
937
|
+
const ControlFlowKindSymbol = /*#__PURE__*/ Symbol("ControlFlow kind");
|
|
938
938
|
//#endregion
|
|
939
939
|
//#region src/std/ops/control_flow.ts
|
|
940
940
|
/**
|
|
@@ -1147,8 +1147,8 @@ function isControlFlow(cf) {
|
|
|
1147
1147
|
* Supports rendezvous (capacity=0) for synchronous handoff between sender and receiver.
|
|
1148
1148
|
*
|
|
1149
1149
|
*/
|
|
1150
|
-
const ASYNC_TRUE =
|
|
1151
|
-
const ASYNC_FALSE =
|
|
1150
|
+
const ASYNC_TRUE = /*#__PURE__*/ Promise.resolve(true);
|
|
1151
|
+
const ASYNC_FALSE = /*#__PURE__*/ Promise.resolve(false);
|
|
1152
1152
|
/**
|
|
1153
1153
|
* Creates a new MPMC channel with the specified capacity.
|
|
1154
1154
|
*
|
|
@@ -2214,6 +2214,17 @@ function RwLock(value) {
|
|
|
2214
2214
|
if (released) return;
|
|
2215
2215
|
released = true;
|
|
2216
2216
|
releaseWrite();
|
|
2217
|
+
},
|
|
2218
|
+
downgrade() {
|
|
2219
|
+
if (released) throw new Error("RwLockWriteGuard has been released");
|
|
2220
|
+
released = true;
|
|
2221
|
+
writer = false;
|
|
2222
|
+
readers = 1;
|
|
2223
|
+
while (readWaitQueue.length > 0) {
|
|
2224
|
+
readers++;
|
|
2225
|
+
readWaitQueue.shift()();
|
|
2226
|
+
}
|
|
2227
|
+
return createReadGuard();
|
|
2217
2228
|
}
|
|
2218
2229
|
});
|
|
2219
2230
|
}
|
|
@@ -2302,6 +2313,119 @@ function RwLock(value) {
|
|
|
2302
2313
|
});
|
|
2303
2314
|
}
|
|
2304
2315
|
//#endregion
|
|
2305
|
-
|
|
2316
|
+
//#region src/std/sync/semaphore.ts
|
|
2317
|
+
/**
|
|
2318
|
+
* @module
|
|
2319
|
+
* Counting semaphore for limiting async concurrency.
|
|
2320
|
+
*
|
|
2321
|
+
* Inspired by [tokio's `Semaphore`](https://docs.rs/tokio/latest/tokio/sync/struct.Semaphore.html)
|
|
2322
|
+
* (Rust std does not include one). Unlike `Mutex<T>` which binds to a value,
|
|
2323
|
+
* `Semaphore` is a pure concurrency counter: it limits how many async
|
|
2324
|
+
* operations can run concurrently without protecting any data.
|
|
2325
|
+
*
|
|
2326
|
+
* **When to use `Semaphore` vs `Mutex<T>`:**
|
|
2327
|
+
* - Use `Mutex<T>` for exclusive access to a value (n=1, with data)
|
|
2328
|
+
* - Use `Semaphore` to limit concurrency to N (e.g. fetch rate limiting,
|
|
2329
|
+
* connection pools, task queues)
|
|
2330
|
+
*
|
|
2331
|
+
* `Semaphore(1)` behaves like a `Mutex` without a value (a binary semaphore),
|
|
2332
|
+
* but `Mutex<T>` is preferred when you need to protect a value since the
|
|
2333
|
+
* guard provides typed access via `value`.
|
|
2334
|
+
*/
|
|
2335
|
+
/**
|
|
2336
|
+
* Creates a new `Semaphore` with the given capacity.
|
|
2337
|
+
*
|
|
2338
|
+
* @param permits - The maximum number of concurrent operations allowed.
|
|
2339
|
+
* Must be a non-negative integer. Use `0` to disallow any
|
|
2340
|
+
* concurrent acquire (acquire will wait forever).
|
|
2341
|
+
* @returns A new `Semaphore` instance.
|
|
2342
|
+
* @throws {RangeError} If `permits` is negative or not an integer.
|
|
2343
|
+
* @example
|
|
2344
|
+
* ```ts
|
|
2345
|
+
* // Limit to 5 concurrent operations
|
|
2346
|
+
* const sem = Semaphore(5);
|
|
2347
|
+
*
|
|
2348
|
+
* // Binary semaphore (equivalent to a value-less Mutex)
|
|
2349
|
+
* const binary = Semaphore(1);
|
|
2350
|
+
* ```
|
|
2351
|
+
*
|
|
2352
|
+
* @example
|
|
2353
|
+
* ```ts
|
|
2354
|
+
* // Task queue: process 2 jobs at a time
|
|
2355
|
+
* const sem = Semaphore(2);
|
|
2356
|
+
*
|
|
2357
|
+
* async function processJob(job: Job) {
|
|
2358
|
+
* return sem.withPermit(async () => {
|
|
2359
|
+
* return await runJob(job);
|
|
2360
|
+
* });
|
|
2361
|
+
* }
|
|
2362
|
+
*
|
|
2363
|
+
* await Promise.all(jobs.map(processJob));
|
|
2364
|
+
* ```
|
|
2365
|
+
*/
|
|
2366
|
+
function Semaphore(permits) {
|
|
2367
|
+
if (!Number.isInteger(permits) || permits < 0) throw new RangeError(`Semaphore capacity must be a non-negative integer, got ${permits}`);
|
|
2368
|
+
const capacity = permits;
|
|
2369
|
+
let available = permits;
|
|
2370
|
+
const waitQueue = [];
|
|
2371
|
+
function releasePermit() {
|
|
2372
|
+
if (waitQueue.length > 0) waitQueue.shift()();
|
|
2373
|
+
else available++;
|
|
2374
|
+
}
|
|
2375
|
+
function createPermit() {
|
|
2376
|
+
let released = false;
|
|
2377
|
+
return Object.freeze({
|
|
2378
|
+
[Symbol.toStringTag]: "SemaphorePermit",
|
|
2379
|
+
toString() {
|
|
2380
|
+
return released ? "SemaphorePermit(<released>)" : "SemaphorePermit";
|
|
2381
|
+
},
|
|
2382
|
+
release() {
|
|
2383
|
+
if (released) return;
|
|
2384
|
+
released = true;
|
|
2385
|
+
releasePermit();
|
|
2386
|
+
}
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
function acquire() {
|
|
2390
|
+
if (available > 0) {
|
|
2391
|
+
available--;
|
|
2392
|
+
return Promise.resolve(createPermit());
|
|
2393
|
+
}
|
|
2394
|
+
return new Promise((resolve) => {
|
|
2395
|
+
waitQueue.push(() => {
|
|
2396
|
+
resolve(createPermit());
|
|
2397
|
+
});
|
|
2398
|
+
});
|
|
2399
|
+
}
|
|
2400
|
+
function tryAcquire() {
|
|
2401
|
+
if (available > 0) {
|
|
2402
|
+
available--;
|
|
2403
|
+
return Some(createPermit());
|
|
2404
|
+
}
|
|
2405
|
+
return None;
|
|
2406
|
+
}
|
|
2407
|
+
return Object.freeze({
|
|
2408
|
+
[Symbol.toStringTag]: "Semaphore",
|
|
2409
|
+
toString() {
|
|
2410
|
+
return `Semaphore(${available}/${capacity})`;
|
|
2411
|
+
},
|
|
2412
|
+
capacity,
|
|
2413
|
+
async withPermit(fn) {
|
|
2414
|
+
const permit = await acquire();
|
|
2415
|
+
try {
|
|
2416
|
+
return await fn();
|
|
2417
|
+
} finally {
|
|
2418
|
+
permit.release();
|
|
2419
|
+
}
|
|
2420
|
+
},
|
|
2421
|
+
acquire,
|
|
2422
|
+
tryAcquire,
|
|
2423
|
+
availablePermits() {
|
|
2424
|
+
return available;
|
|
2425
|
+
}
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
//#endregion
|
|
2429
|
+
export { ASYNC_NONE, Break, Channel, Continue, Err, FnOnce, FnOnceAsync, Lazy, LazyAsync, Mutex, None, Ok, Once, OnceAsync, RESULT_FALSE, RESULT_TRUE, RESULT_VOID, RESULT_ZERO, RwLock, Semaphore, Some, isControlFlow, isOption, isResult, tryAsyncOption, tryAsyncResult, tryOption, tryResult };
|
|
2306
2430
|
|
|
2307
2431
|
//# sourceMappingURL=main.mjs.map
|