Skip to content

Commit

Permalink
feat: add iterator and enum value handling helpers (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcr authored Nov 1, 2023
1 parent 49efc26 commit cb263b8
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './iterators';
export * from './time';
export * from './values';
78 changes: 78 additions & 0 deletions src/helpers/iterators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { logger } from '../logger';
import { isDevEnv } from './values';

/**
* Iterate over an array, yielding multiple items at a time. If the size of the given array
* is not divisible by the given batch size, then the length of the last items returned will
* be smaller than the given batch size, i.e.:
* ```typescript
* items.length % batchSize
* ```
* @param items - The array to iterate over.
* @param batchSize - Maximum number of items to return at a time.
* @param printBenchmark - If we should print benchmark of items per second
*/
export function* batchIterate<T>(
items: T[],
batchSize: number,
printBenchmark = isDevEnv
): Generator<T[]> {
if (items.length === 0) return;
const startTime = Date.now();
for (let i = 0; i < items.length; ) {
const itemsRemaining = items.length - i;
const sliceSize = Math.min(batchSize, itemsRemaining);
yield items.slice(i, i + sliceSize);
i += sliceSize;
}
if (printBenchmark) {
const itemsPerSecond = Math.round((items.length / (Date.now() - startTime)) * 1000);
const caller = new Error().stack?.split('at ')[3].trim();
logger.debug(`Iterated ${itemsPerSecond} items/second at ${caller}`);
}
}

/**
* Iterate over an `AsyncIterable`, yielding multiple items at a time. If the size of the given
* array is not divisible by the given batch size, then the length of the last items returned will
* be smaller than the given batch size.
*
* @param items - AsyncIterable
* @param batchSize - Batch size
* @param printBenchmark - If we should print benchmark of items per second
*/
export async function* asyncBatchIterate<T>(
items: AsyncIterable<T>,
batchSize: number,
printBenchmark = isDevEnv
): AsyncGenerator<T[], void, unknown> {
const startTime = Date.now();
let itemCount = 0;
let itemBatch: T[] = [];
for await (const item of items) {
itemBatch.push(item);
itemCount++;
if (itemBatch.length >= batchSize) {
yield itemBatch;
itemBatch = [];
if (printBenchmark) {
const itemsPerSecond = Math.round((itemCount / (Date.now() - startTime)) * 1000);
const caller = new Error().stack?.split('at ')[3].trim();
logger.debug(`Iterated ${itemsPerSecond} items/second at ${caller}`);
}
}
}
if (itemBatch.length > 0) {
yield itemBatch;
}
}

/**
* Convert an `AsyncIterable` to a generator
* @param iter - AsyncIterable
*/
export async function* asyncIterableToGenerator<T>(iter: AsyncIterable<T>) {
for await (const entry of iter) {
yield entry;
}
}
12 changes: 12 additions & 0 deletions src/helpers/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,15 @@ export function numberToHex(number: number, paddingBytes: number = 4): string {
* @returns Boolean
*/
export const has0xPrefix = (val: string) => val.substring(0, 2).toLowerCase() === '0x';

/**
* Converts a string to an enum value.
* @param enumType - The enum type
* @param value - The string value to convert
* @returns Enum item or undefined
*/
export function toEnumValue<T>(enm: { [s: string]: T }, value: string): T | undefined {
return (Object.values(enm) as unknown as string[]).includes(value)
? (value as unknown as T)
: undefined;
}

0 comments on commit cb263b8

Please sign in to comment.