2023-08-28 10:43:09 +00:00
|
|
|
/**
|
|
|
|
* data-structure-typed
|
|
|
|
*
|
|
|
|
* @author Tyler Zeng
|
|
|
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
|
|
* @license MIT License
|
|
|
|
*/
|
2023-09-22 02:43:16 +00:00
|
|
|
import type {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from '../types';
|
2023-08-28 10:43:09 +00:00
|
|
|
|
2023-06-15 16:34:28 +00:00
|
|
|
export const uuidV4 = function () {
|
2023-09-12 03:15:20 +00:00
|
|
|
return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {
|
2023-09-21 04:52:17 +00:00
|
|
|
const r = (Math.random() * 16) | 0,
|
|
|
|
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
2023-09-12 03:15:20 +00:00
|
|
|
return v.toString(16);
|
|
|
|
});
|
2023-06-15 16:34:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export const arrayRemove = function <T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): T[] {
|
2023-09-21 04:52:17 +00:00
|
|
|
let i = -1,
|
|
|
|
len = array ? array.length : 0;
|
2023-09-12 03:15:20 +00:00
|
|
|
const result = [];
|
|
|
|
|
|
|
|
while (++i < len) {
|
|
|
|
const value = array[i];
|
|
|
|
if (predicate(value, i, array)) {
|
|
|
|
result.push(value);
|
|
|
|
Array.prototype.splice.call(array, i--, 1);
|
|
|
|
len--;
|
2023-06-15 16:34:28 +00:00
|
|
|
}
|
2023-09-12 03:15:20 +00:00
|
|
|
}
|
2023-06-15 16:34:28 +00:00
|
|
|
|
2023-09-12 03:15:20 +00:00
|
|
|
return result;
|
2023-06-15 16:34:28 +00:00
|
|
|
};
|
|
|
|
|
2023-09-21 04:52:17 +00:00
|
|
|
export const THUNK_SYMBOL = Symbol('thunk');
|
2023-08-15 17:35:16 +00:00
|
|
|
|
|
|
|
export const isThunk = (fnOrValue: any) => {
|
2023-09-21 04:52:17 +00:00
|
|
|
return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;
|
|
|
|
};
|
2023-08-15 17:35:16 +00:00
|
|
|
|
|
|
|
export const toThunk = (fn: ToThunkFn): Thunk => {
|
2023-09-21 04:52:17 +00:00
|
|
|
const thunk = () => fn();
|
|
|
|
thunk.__THUNK__ = THUNK_SYMBOL;
|
|
|
|
return thunk;
|
|
|
|
};
|
2023-08-15 17:35:16 +00:00
|
|
|
|
|
|
|
export const trampoline = (fn: TrlFn) => {
|
2023-09-21 04:52:17 +00:00
|
|
|
const cont = (...args: [...Parameters<TrlFn>]) => toThunk(() => fn(...args));
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-12 03:15:20 +00:00
|
|
|
return Object.assign(
|
|
|
|
(...args: [...Parameters<TrlFn>]) => {
|
2023-09-21 04:52:17 +00:00
|
|
|
let result = fn(...args);
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-12 03:15:20 +00:00
|
|
|
while (isThunk(result) && typeof result === 'function') {
|
2023-09-21 04:52:17 +00:00
|
|
|
result = result();
|
2023-09-12 03:15:20 +00:00
|
|
|
}
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-21 04:52:17 +00:00
|
|
|
return result;
|
2023-09-12 03:15:20 +00:00
|
|
|
},
|
2023-09-22 02:43:16 +00:00
|
|
|
{cont}
|
2023-09-21 04:52:17 +00:00
|
|
|
);
|
|
|
|
};
|
2023-08-15 17:35:16 +00:00
|
|
|
|
|
|
|
export const trampolineAsync = (fn: TrlAsyncFn) => {
|
2023-09-21 04:52:17 +00:00
|
|
|
const cont = (...args: [...Parameters<TrlAsyncFn>]) => toThunk(() => fn(...args));
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-12 03:15:20 +00:00
|
|
|
return Object.assign(
|
|
|
|
async (...args: [...Parameters<TrlAsyncFn>]) => {
|
2023-09-21 04:52:17 +00:00
|
|
|
let result = await fn(...args);
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-12 03:15:20 +00:00
|
|
|
while (isThunk(result) && typeof result === 'function') {
|
2023-09-21 04:52:17 +00:00
|
|
|
result = await result();
|
2023-09-12 03:15:20 +00:00
|
|
|
}
|
2023-08-15 17:35:16 +00:00
|
|
|
|
2023-09-21 04:52:17 +00:00
|
|
|
return result;
|
2023-09-12 03:15:20 +00:00
|
|
|
},
|
2023-09-22 02:43:16 +00:00
|
|
|
{cont}
|
2023-09-21 04:52:17 +00:00
|
|
|
);
|
|
|
|
};
|
2023-10-25 01:57:04 +00:00
|
|
|
|
|
|
|
export const getMSB = (value: number): number => {
|
|
|
|
if (value <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1 << (31 - Math.clz32(value));
|
|
|
|
};
|