mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-09-23 23:13:42 +02:00
Add many typed array helpers
This commit is contained in:
parent
0ebdc1b0ef
commit
284df1ac1a
526
src/@types/typed-arrays.ts
Normal file
526
src/@types/typed-arrays.ts
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Pagefault Games
|
||||
* SPDX-FileContributor: SirzBenjie
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collection of utility types for working with
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray}
|
||||
* with enhanced type safety and usability.
|
||||
* @module
|
||||
*/
|
||||
|
||||
/**
|
||||
* Union type of all {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray}s
|
||||
*/
|
||||
export type TypedArray =
|
||||
| Int8Array
|
||||
| Uint8Array
|
||||
| Uint8ClampedArray
|
||||
| Int16Array
|
||||
| Uint16Array
|
||||
| Int32Array
|
||||
| Uint32Array
|
||||
| Float32Array
|
||||
| Float64Array
|
||||
| BigInt64Array
|
||||
| BigUint64Array;
|
||||
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array | Int8Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Int8Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyInt8Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Int8Array, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyInt8Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array | Uint8Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Uint8Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyUint8Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Uint8Array, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyUint8Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray | Uint8ClampedArray}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Uint8ClampedArray` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyUint8ClampedArray<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Uint8ClampedArray<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyUint8ClampedArray<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array | Int16Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Int16Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyInt16Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Int16Array<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyInt16Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array | Uint16Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Uint16Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyUint16Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Uint16Array<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyUint16Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array | Int32Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Int32Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyInt32Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Int32Array<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyInt32Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array | Uint32Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Uint32Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyUint32Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Uint32Array<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyUint32Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array | Float32Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Float32Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyFloat32Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Float32Array<TArrayBuffer>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyFloat32Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array | Float64Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `Float64Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyFloat64Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<Float64Array, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyFloat64Array<TArrayBuffer>;
|
||||
readonly [index: number]: number;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array | BigInt64Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `BigInt64Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyBigInt64Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<BigInt64Array, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyBigInt64Array<TArrayBuffer>;
|
||||
readonly [index: number]: bigint;
|
||||
}
|
||||
/**
|
||||
* A readonly version of {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array | BigUint64Array}
|
||||
*
|
||||
* @remarks
|
||||
* Is to `BigUint64Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyBigUint64Array<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>
|
||||
extends Omit<BigUint64Array, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyBigUint64Array<TArrayBuffer>;
|
||||
readonly [index: number]: bigint;
|
||||
}
|
||||
|
||||
export type ReadonlyTypedArray =
|
||||
| ReadonlyInt8Array
|
||||
| ReadonlyUint8Array
|
||||
| ReadonlyUint8ClampedArray
|
||||
| ReadonlyInt16Array
|
||||
| ReadonlyUint16Array
|
||||
| ReadonlyInt32Array
|
||||
| ReadonlyUint32Array
|
||||
| ReadonlyFloat32Array
|
||||
| ReadonlyFloat64Array
|
||||
| ReadonlyBigInt64Array
|
||||
| ReadonlyBigUint64Array;
|
||||
|
||||
/**
|
||||
* Either {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array | BigInt64Array}
|
||||
* or {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array | BigUint64Array}
|
||||
*/
|
||||
export type BigIntArray = BigInt64Array | BigUint64Array;
|
||||
|
||||
/** Any {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} whose elements are not `bigint`s */
|
||||
export type NumberCompatibleTypedArray = Exclude<TypedArray, BigIntArray>;
|
||||
|
||||
/**
|
||||
* A partial interface of `Uint8Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialUint8Array<T extends number> extends Uint8Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Uint8Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericUint8Array<T extends number> extends PartialUint8Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericUint8Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericUint8Array<T>;
|
||||
toReversed(): GenericUint8Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericUint8Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericUint8Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial interface of `Uint16Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialUint16Array<T extends number> extends Uint16Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Uint16Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericUint16Array<T extends number> extends PartialUint16Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericUint16Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericUint16Array<T>;
|
||||
toReversed(): GenericUint16Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericUint16Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericUint16Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial interface of `Uint32Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialUint32Array<T extends number> extends Uint32Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Uint32Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericUint32Array<T extends number> extends PartialUint32Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericUint32Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericUint32Array<T>;
|
||||
toReversed(): GenericUint32Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericUint32Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericUint32Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial interface of `Int8Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialInt8Array<T extends number> extends Int8Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Int8Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericInt8Array<T extends number> extends PartialInt8Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericInt8Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericInt8Array<T>;
|
||||
toReversed(): GenericInt8Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericInt8Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericInt8Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial interface of `Int16Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialInt16Array<T extends number> extends Int16Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Int16Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericInt16Array<T extends number> extends PartialInt16Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericInt16Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericInt16Array<T>;
|
||||
toReversed(): GenericInt16Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericInt16Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericInt16Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial interface of `Int32Array` where methods that return the array type have been modified to return a more specific type.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Excludes methods that return a new array (e.g. `subarray`, `slice`, `toReversed`, `toSorted`, `with`) as these cannot be resolved by typescript
|
||||
* @internal
|
||||
*/
|
||||
interface PartialInt32Array<T extends number> extends Int32Array {
|
||||
at(index: number): T | undefined; // ES2022
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
find(predicate: (value: T, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
findLast(predicate: (value: number, index: number, array: this) => boolean, thisArg?: any): T | undefined;
|
||||
forEach(callbackfn: (value: T, index: number, array: this) => void, thisArg?: any): void;
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
||||
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: this) => T): T;
|
||||
set(array: ArrayLike<T>, offset?: number): void;
|
||||
some(predicate: (value: T, index: number, obj: this) => boolean, thisArg?: any): boolean;
|
||||
sort(compareFn?: (a: T, b: T) => number): this;
|
||||
values(): ArrayIterator<T>;
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Int32Array` whose elements typescript considers to be of type `T`, allowing for type-safe iteration and access.
|
||||
*
|
||||
* @remarks
|
||||
* Useful to leverage the benefits of `TypedArrays` without losing type information. Typescript will consider the elements to be of type `T` instead of just `number`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
*/
|
||||
// @ts-expect-error - These methods _will_ error, as we are overriding the return type to be more specific
|
||||
// in a way that makes typescript unhappy
|
||||
export interface GenericInt32Array<T extends number> extends PartialInt32Array<T> {
|
||||
// map(callbackfn: (value: T, index: number, array: this) => T, thisArg?: any): GenericInt32Array<T>;
|
||||
// this method does not trigger a typescript error on its own, but if we add in `toReversed` it causes issues....
|
||||
subarray(begin?: number, end?: number): GenericInt32Array<T>;
|
||||
toReversed(): GenericInt32Array<T>;
|
||||
toSorted(compareFn?: (a: T, b: T) => number): GenericInt32Array<T>;
|
||||
filter(predicate: (value: T, index: number, array: this) => any, thisArg?: any): GenericInt32Array<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericUint8Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericUint8Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericUint8Array<T extends number>
|
||||
extends Omit<GenericUint8Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericUint8Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericUint16Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericUint16Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericUint16Array<T extends number>
|
||||
extends Omit<GenericUint16Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericUint16Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericUint32Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericUint32Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericUint32Array<T extends number>
|
||||
extends Omit<GenericUint32Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericUint32Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericInt8Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericInt8Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericInt8Array<T extends number>
|
||||
extends Omit<GenericInt8Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericInt8Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericInt16Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericInt16Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericInt16Array<T extends number>
|
||||
extends Omit<GenericInt16Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericInt16Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A readonly version of {@link GenericInt32Array} where elements are of type `T`.
|
||||
* @typeParam T - The specific numeric type of the elements in the array.
|
||||
* @remarks
|
||||
* Is to `GenericInt32Array` what `ReadonlyArray` is to `Array`
|
||||
*/
|
||||
export interface ReadonlyGenericInt32Array<T extends number>
|
||||
extends Omit<GenericInt32Array<T>, "fill" | "set" | "sort" | "reverse" | "copyWithin" | "subarray"> {
|
||||
subarray(begin?: number, end?: number): ReadonlyGenericInt32Array<T>;
|
||||
readonly [index: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A union type of all `GenericTypedArray`s
|
||||
*/
|
||||
export type ReadonlyGenericArray<T extends number = number> =
|
||||
| ReadonlyGenericUint8Array<T>
|
||||
| ReadonlyGenericUint16Array<T>
|
||||
| ReadonlyGenericUint32Array<T>
|
||||
| ReadonlyGenericInt8Array<T>
|
||||
| ReadonlyGenericInt16Array<T>
|
||||
| ReadonlyGenericInt32Array<T>;
|
@ -866,7 +866,7 @@ export class BattleScene extends SceneBase {
|
||||
gender?: Gender,
|
||||
shiny?: boolean,
|
||||
variant?: Variant,
|
||||
ivs?: Uint8Array,
|
||||
ivs?: number[],
|
||||
nature?: Nature,
|
||||
dataSource?: Pokemon | PokemonData,
|
||||
postProcess?: (playerPokemon: PlayerPokemon) => void,
|
||||
|
@ -16,6 +16,7 @@ import type { AttackMoveResult } from "#types/attack-move-result";
|
||||
import type { IllusionData } from "#types/illusion-data";
|
||||
import type { TurnMove } from "#types/turn-move";
|
||||
import type { CoerceNullPropertiesToUndefined } from "#types/type-helpers";
|
||||
import { setTypedArray } from "#utils/common";
|
||||
import { getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
|
||||
/**
|
||||
@ -129,7 +130,7 @@ export class PokemonSummonData {
|
||||
public passiveAbility: AbilityId | undefined;
|
||||
public gender: Gender | undefined;
|
||||
public fusionGender: Gender | undefined;
|
||||
public stats: number[] = [0, 0, 0, 0, 0, 0];
|
||||
public stats: Uint32Array = new Uint32Array(6);
|
||||
public moveset: PokemonMove[] | null;
|
||||
|
||||
// If not initialized this value will not be populated from save data.
|
||||
@ -165,6 +166,11 @@ export class PokemonSummonData {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "stats") {
|
||||
setTypedArray(this.stats, source.stats);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "illusion" && typeof value === "object") {
|
||||
// Make a copy so as not to mutate provided value
|
||||
const illusionData = {
|
||||
@ -221,8 +227,10 @@ export class PokemonSummonData {
|
||||
// We coerce null to undefined in the type, as the for loop below replaces `null` with `undefined`
|
||||
...(this as Omit<
|
||||
CoerceNullPropertiesToUndefined<PokemonSummonData>,
|
||||
"speciesForm" | "fusionSpeciesForm" | "illusion"
|
||||
"speciesForm" | "fusionSpeciesForm" | "illusion" | "stats"
|
||||
>),
|
||||
// TypedArrays do not serialize to JSON as an array.
|
||||
stats: Array.from(this.stats),
|
||||
speciesForm: speciesForm == null ? undefined : { id: speciesForm.speciesId, formIdx: speciesForm.formIndex },
|
||||
fusionSpeciesForm:
|
||||
fusionSpeciesForm == null
|
||||
|
@ -168,6 +168,7 @@ import {
|
||||
rgbaToInt,
|
||||
rgbHexToRgba,
|
||||
rgbToHsv,
|
||||
subArray,
|
||||
toDmgValue,
|
||||
} from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
@ -203,7 +204,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public levelExp: number;
|
||||
public gender: Gender;
|
||||
public hp: number;
|
||||
public stats: number[];
|
||||
public stats = new Uint32Array(6).fill(1);
|
||||
public ivs: Uint8Array;
|
||||
public nature: Nature;
|
||||
public moveset: PokemonMove[];
|
||||
@ -311,7 +312,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
gender?: Gender,
|
||||
shiny?: boolean,
|
||||
variant?: Variant,
|
||||
ivs?: Uint8Array,
|
||||
ivs?: Uint8Array | number[],
|
||||
nature?: Nature,
|
||||
dataSource?: Pokemon | PokemonData,
|
||||
) {
|
||||
@ -345,9 +346,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (dataSource) {
|
||||
this.id = dataSource.id;
|
||||
this.hp = dataSource.hp;
|
||||
this.stats = dataSource.stats;
|
||||
|
||||
this.ivs = new Uint8Array(dataSource.ivs);
|
||||
this.stats.set(subArray(dataSource.stats, 6));
|
||||
this.ivs.set(subArray(dataSource.ivs, 6));
|
||||
this.passive = !!dataSource.passive;
|
||||
if (this.variant === undefined) {
|
||||
this.variant = 0;
|
||||
@ -386,7 +386,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.stellarTypesBoosted = dataSource.stellarTypesBoosted ?? [];
|
||||
} else {
|
||||
this.id = randSeedInt(4294967296);
|
||||
this.ivs = new Uint8Array(ivs || getIvsFromId(this.id));
|
||||
this.ivs.set(subArray(ivs ?? getIvsFromId(this.id), 6));
|
||||
|
||||
if (this.gender === undefined) {
|
||||
this.gender = this.species.generateGender();
|
||||
@ -1320,7 +1320,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @param bypassSummonData - Whether to prefer actual stats (`true`) or in-battle overridden stats (`false`); default `true`
|
||||
* @returns The numeric values of this {@linkcode Pokemon}'s stats as an array.
|
||||
*/
|
||||
getStats(bypassSummonData = true): number[] {
|
||||
getStats(bypassSummonData = true): ArrayLike<number> {
|
||||
if (!bypassSummonData) {
|
||||
// Only grab summon data stats if nonzero
|
||||
return this.summonData.stats.map((s, i) => s || this.stats[i]);
|
||||
@ -1552,10 +1552,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
calculateStats(): void {
|
||||
if (!this.stats) {
|
||||
this.stats = [0, 0, 0, 0, 0, 0];
|
||||
}
|
||||
|
||||
// Get and manipulate base stats
|
||||
const baseStats = this.calculateBaseStats();
|
||||
// Using base stats, calculate and store stats one by one
|
||||
@ -1588,7 +1584,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
globalScene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, s, statHolder);
|
||||
}
|
||||
|
||||
statHolder.value = Phaser.Math.Clamp(statHolder.value, 1, Number.MAX_SAFE_INTEGER);
|
||||
statHolder.value = Phaser.Math.Clamp(statHolder.value, 1, 0xffffffff);
|
||||
|
||||
this.setStat(s, statHolder.value);
|
||||
}
|
||||
@ -5705,7 +5701,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
gender?: Gender,
|
||||
shiny?: boolean,
|
||||
variant?: Variant,
|
||||
ivs?: Uint8Array,
|
||||
ivs?: Uint8Array | number[],
|
||||
nature?: Nature,
|
||||
dataSource?: Pokemon | PokemonData,
|
||||
) {
|
||||
|
@ -99,8 +99,8 @@ export class PokemonData {
|
||||
this.levelExp = source.levelExp;
|
||||
this.gender = source.gender;
|
||||
this.hp = source.hp;
|
||||
this.stats = source.stats;
|
||||
this.ivs = source.ivs;
|
||||
this.stats = Array.from(source.stats);
|
||||
this.ivs = Array.from(source.ivs);
|
||||
|
||||
// TODO: Can't we move some of this verification stuff to an upgrade script?
|
||||
this.nature = source.nature ?? Nature.HARDY;
|
||||
@ -162,7 +162,7 @@ export class PokemonData {
|
||||
this.gender,
|
||||
this.shiny,
|
||||
this.variant,
|
||||
this.ivs,
|
||||
new Uint8Array(this.ivs.slice(0, 6)),
|
||||
this.nature,
|
||||
this,
|
||||
playerPokemon => {
|
||||
|
@ -1,6 +1,13 @@
|
||||
import { pokerogueApi } from "#api/pokerogue-api";
|
||||
import { MoneyFormat } from "#enums/money-format";
|
||||
import type { Variant } from "#sprites/variant";
|
||||
import type {
|
||||
BigIntArray,
|
||||
NumberCompatibleTypedArray,
|
||||
ReadonlyGenericArray,
|
||||
ReadonlyTypedArray,
|
||||
TypedArray,
|
||||
} from "#types/typed-arrays";
|
||||
import i18next from "i18next";
|
||||
|
||||
export type nil = null | undefined;
|
||||
@ -176,15 +183,15 @@ export function getPlayTimeString(totalSeconds: number): string {
|
||||
* @param id 32-bit number
|
||||
* @returns An array of six numbers corresponding to 5-bit chunks from {@linkcode id}
|
||||
*/
|
||||
export function getIvsFromId(id: number): number[] {
|
||||
return [
|
||||
export function getIvsFromId(id: number): Uint8Array {
|
||||
return Uint8Array.of(
|
||||
(id & 0x3e000000) >>> 25,
|
||||
(id & 0x01f00000) >>> 20,
|
||||
(id & 0x000f8000) >>> 15,
|
||||
(id & 0x00007c00) >>> 10,
|
||||
(id & 0x000003e0) >>> 5,
|
||||
id & 0x0000001f,
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
export function formatLargeNumber(count: number, threshold: number): string {
|
||||
@ -515,3 +522,86 @@ export function coerceArray<T>(input: T): T extends any[] ? T : [T];
|
||||
export function coerceArray<T>(input: T): T | [T] {
|
||||
return Array.isArray(input) ? input : [input];
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard to check if an input is a typed array, defined as an `ArrayBufferView` that is not a `DataView`.
|
||||
*/
|
||||
export function isTypedArray(input: unknown): input is TypedArray {
|
||||
return ArrayBuffer.isView(input) && !(input instanceof DataView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a subarray view of the first `n` elements of an array-like object, to use
|
||||
* with constructing a new one, with minimal allocaitons.
|
||||
*
|
||||
* @remarks
|
||||
* This is primarily useful for setting elements of a `TypedArray` using its `set` method.
|
||||
*
|
||||
* @privateRemarks
|
||||
* Note that if this is used with a tuple type, typescript will improperly set
|
||||
* the return type to be a tuple of the same length as input.
|
||||
*
|
||||
* @param arr - The array-like object to take elements from
|
||||
* @param n - The maximum number of elements to take. If
|
||||
* @returns An array-like object whose `length` property is guaranteed to be <= `n`
|
||||
*
|
||||
* @typeParam T - The element type of the array-like object
|
||||
* @typeParam A - The type of the array-like object
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* const arr = new Uint8Array(3);
|
||||
* const other = [1, 2, 3, 4, 5];
|
||||
* // Using arr.set(other) would throw, as other.length > arr.length
|
||||
* arr.set(subArray(other, arr.length));
|
||||
*
|
||||
* @throws {TypeError}
|
||||
* If `arr` is not an array or typed array (though typescript should prevent this)
|
||||
*/
|
||||
export function subArray<const A extends TypedArray | readonly unknown[]>(arr: A, n: number): typeof arr {
|
||||
if (arr.length <= n) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
const len = Math.min(arr.length, n);
|
||||
|
||||
if (Array.isArray(arr)) {
|
||||
// The only path with a new allocation
|
||||
return arr.slice(0, len) as typeof arr;
|
||||
}
|
||||
if (isTypedArray(arr)) {
|
||||
return arr.subarray(0, len) as typeof arr;
|
||||
}
|
||||
throw new TypeError("Expecting an array or typed array");
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple values in the typed array, from input values from a specified array, without
|
||||
* the possibility of a `RangeError` being thrown.
|
||||
*
|
||||
* @remarks
|
||||
* Almost equivalent to calling `target.set(source, offset)`, though ensures that
|
||||
* `RangeError` can never be thrown by clamping the number of elements taken from `source`
|
||||
* to the available space in `target` starting at `offset`.
|
||||
*
|
||||
* @param target - The typed array to set values in
|
||||
* @param source - The array-like object to take values from
|
||||
* @param offset - The offset in `target` to start writing values at. Defaults to `0`
|
||||
*
|
||||
* @see {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set | TypedArray#set}
|
||||
*/
|
||||
export function setTypedArray<const T extends ReadonlyTypedArray | ReadonlyGenericArray>(
|
||||
target: T,
|
||||
source: T extends BigIntArray
|
||||
? Readonly<BigIntArray> | readonly bigint[]
|
||||
: Readonly<NumberCompatibleTypedArray> | readonly number[],
|
||||
offset = 0,
|
||||
): void {
|
||||
if (offset < 0 || offset >= target.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS can't link the conditional type of source to the conditional type of target
|
||||
// in the body here, despite the fact that the function signature guarantees it.
|
||||
target.set(subArray(source, target.length - offset), offset);
|
||||
}
|
||||
|
122
test/utils/common.test.ts
Normal file
122
test/utils/common.test.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { setTypedArray, subArray } from "#utils/common";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
/**
|
||||
* Unit tests for the utility methods in `src/utils/common.ts`
|
||||
* @module
|
||||
*/
|
||||
|
||||
describe("subArray", () => {
|
||||
it("returns the same array if length <= n (plain array)", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = subArray(arr, 5);
|
||||
expect(result).toBe(arr);
|
||||
expect(result).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("returns a sliced array if length > n (plain array)", () => {
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
const result = subArray(arr, 3);
|
||||
expect(result).not.toBe(arr);
|
||||
expect(result).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("returns the same typed array if length <= n", () => {
|
||||
const arr = new Uint8Array([1, 2, 3]);
|
||||
const result = subArray(arr, 5);
|
||||
expect(result).toBe(arr);
|
||||
expect(Array.from(result)).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("returns a subarray if length > n (typed array)", () => {
|
||||
const arr = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const result = subArray(arr, 2);
|
||||
expect(result).not.toBe(arr);
|
||||
expect(Array.from(result)).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it("returns empty array if n is 0 (plain array)", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = subArray(arr, 0);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it("returns empty typed array if n is 0", () => {
|
||||
const arr = new Uint8Array([1, 2, 3]);
|
||||
const result = subArray(arr, 0);
|
||||
expect(Array.from(result)).toEqual([]);
|
||||
});
|
||||
|
||||
it("throws TypeError for non-array-like input", () => {
|
||||
// @ts-expect-error
|
||||
expect(() => subArray({ length: 4 }, 2)).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setTypedArray", () => {
|
||||
it("sets values from source to target with no offset (fits exactly)", () => {
|
||||
const target = new Uint8Array(3);
|
||||
const source = [1, 2, 3];
|
||||
setTypedArray(target, source);
|
||||
expect(Array.from(target)).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("sets values from source to target with offset", () => {
|
||||
const target = new Uint8Array([0, 0, 0, 0, 0]);
|
||||
const source = [9, 8];
|
||||
setTypedArray(target, source, 2);
|
||||
expect(Array.from(target)).toEqual([0, 0, 9, 8, 0]);
|
||||
});
|
||||
|
||||
it("clamps source if it would overflow target", () => {
|
||||
const target = new Uint8Array(4);
|
||||
const source = [1, 2, 3, 4, 5, 6];
|
||||
setTypedArray(target, source, 2);
|
||||
expect(Array.from(target)).toEqual([0, 0, 1, 2]);
|
||||
});
|
||||
|
||||
it("does nothing if offset < 0", () => {
|
||||
const target = new Uint8Array([1, 2, 3]);
|
||||
const source = [4, 5, 6];
|
||||
setTypedArray(target, source, -1);
|
||||
expect(Array.from(target)).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("does nothing if offset >= target.length", () => {
|
||||
const target = new Uint8Array([1, 2, 3]);
|
||||
const source = [4, 5, 6];
|
||||
setTypedArray(target, source, 3);
|
||||
expect(Array.from(target)).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("does nothing if source is empty", () => {
|
||||
const target = new Uint8Array([1, 2, 3]);
|
||||
const source: number[] = [];
|
||||
setTypedArray(target, source, 1);
|
||||
expect(Array.from(target)).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("works with typed array as source", () => {
|
||||
const target = new Uint8Array(4);
|
||||
const source = new Uint8Array([7, 8, 9]);
|
||||
setTypedArray(target, source, 1);
|
||||
expect(Array.from(target)).toEqual([0, 7, 8, 9]);
|
||||
});
|
||||
|
||||
it("clamps source typed array if it would overflow target", () => {
|
||||
const target = new Uint8Array(3);
|
||||
const source = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
setTypedArray(target, source, 1);
|
||||
expect(Array.from(target)).toEqual([0, 1, 2]);
|
||||
});
|
||||
|
||||
it("works with BigUint64Array and bigint[]", () => {
|
||||
if (typeof BigUint64Array !== "undefined") {
|
||||
const target = new BigUint64Array(3);
|
||||
const source = [1n, 2n, 3n, 4n];
|
||||
|
||||
setTypedArray(target, source, 1);
|
||||
expect(Array.from(target)).toEqual([0n, 1n, 2n]);
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user