Skip to content

Commit

Permalink
feat(api): replace Type enum w/ strings consts
Browse files Browse the repository at this point in the history
BREAKING CHANGE: replace Type enum w/ string consts

- update Type, UintType, IntType, FloatType aliases
- update GL2TYPE, TYPE2GL, SIZEOF, TYPEDARRAY_CTORS tables
- add asNativeType(), asGLType() conversions
- add sizeOf()
- add uintTypeForBits(), intTypeForBits()
- update/rename uintTypeForSize(), intTypeForSize()
  • Loading branch information
postspectacular committed Feb 2, 2021
1 parent 6460e4d commit a333d41
Showing 1 changed file with 129 additions and 88 deletions.
217 changes: 129 additions & 88 deletions packages/api/src/api/typedarray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,27 @@ export type TypedArrayConstructor =
| Float64ArrayConstructor;

/**
* Type enums for Typedarray-backed buffers.
* Type IDs for typed array backed buffers and generally describing binary data
* values.
*
* {@link GLType}
* {@link GL2TYPE}
* {@link TYPE2GL}
* {@link GLType} {@link GL2TYPE} {@link TYPE2GL}
*/
export enum Type {
U8,
U8C,
I8,
U16,
I16,
U32,
I32,
F32,
F64,
}
export type Type =
| "u8"
| "u8c"
| "i8"
| "u16"
| "i16"
| "u32"
| "i32"
| "f32"
| "f64";

export type UintType = Type.U8 | Type.U16 | Type.U32;
export type UintType = "u8" | "u16" | "u32";

export type IntType = Type.I8 | Type.I16 | Type.I32;
export type IntType = "i8" | "i16" | "i32";

export type FloatType = Type.F32 | Type.F64;
export type FloatType = "f32" | "f64";

/**
* WebGL numeric type constants. Use {@link GL2TYPE} to convert, if needed.
Expand All @@ -74,13 +72,13 @@ export enum GLType {
* Conversion from {@link GLType} to {@link Type} enums.
*/
export const GL2TYPE: Record<GLType, Type> = {
[GLType.I8]: Type.I8,
[GLType.U8]: Type.U8,
[GLType.I16]: Type.I16,
[GLType.U16]: Type.U16,
[GLType.I32]: Type.I32,
[GLType.U32]: Type.U32,
[GLType.F32]: Type.F32,
[GLType.I8]: "i8",
[GLType.U8]: "u8",
[GLType.I16]: "i16",
[GLType.U16]: "u16",
[GLType.I32]: "i32",
[GLType.U32]: "u32",
[GLType.F32]: "f32",
};

/**
Expand All @@ -89,66 +87,57 @@ export const GL2TYPE: Record<GLType, Type> = {
* Not all enums are mappable:
*
* - `F64` maps to `undefined`, since unsupported by WebGL
* - `U8C` maps to U8
* - `U8C` maps to "u8"
*/
export const TYPE2GL: Record<Type, GLType | undefined> = {
[Type.I8]: GLType.I8,
[Type.U8]: GLType.U8,
[Type.U8C]: GLType.U8,
[Type.I16]: GLType.I16,
[Type.U16]: GLType.U16,
[Type.I32]: GLType.I32,
[Type.I32]: GLType.I32,
[Type.U32]: GLType.U32,
[Type.F32]: GLType.F32,
[Type.F64]: undefined,
i8: GLType.I8,
u8: GLType.U8,
u8c: GLType.U8,
i16: GLType.I16,
u16: GLType.U16,
i32: GLType.I32,
u32: GLType.U32,
f32: GLType.F32,
f64: undefined,
};

/**
* Size information (in bytes) for {@link Type} enums. For {@link GLType}, use this
* form, e.g. `SIZEOF[GL2TYPE[GLType.F32]]`
* Size information (in bytes) for {@link Type}. Also see {@link sizeOf}.
*/
export const SIZEOF = {
[Type.U8]: 1,
[Type.U8C]: 1,
[Type.I8]: 1,
[Type.U16]: 2,
[Type.I16]: 2,
[Type.U32]: 4,
[Type.I32]: 4,
[Type.F32]: 4,
[Type.F64]: 8,
u8: 1,
u8c: 1,
i8: 1,
u16: 2,
i16: 2,
u32: 4,
i32: 4,
f32: 4,
f64: 8,
};

export const TYPEDARRAY_CTORS: Record<Type | GLType, TypedArrayConstructor> = {
[Type.U8]: Uint8Array,
[Type.U8C]: Uint8ClampedArray,
[Type.I8]: Int8Array,
[Type.U16]: Uint16Array,
[Type.I16]: Int16Array,
[Type.U32]: Uint32Array,
[Type.I32]: Int32Array,
[Type.F32]: Float32Array,
[Type.F64]: Float64Array,
[GLType.U8]: Uint8Array,
[GLType.I8]: Int8Array,
[GLType.U16]: Uint16Array,
[GLType.I16]: Int16Array,
[GLType.U32]: Uint32Array,
[GLType.I32]: Int32Array,
[GLType.F32]: Float32Array,
export const TYPEDARRAY_CTORS: Record<Type, TypedArrayConstructor> = {
u8: Uint8Array,
u8c: Uint8ClampedArray,
i8: Int8Array,
u16: Uint16Array,
i16: Int16Array,
u32: Uint32Array,
i32: Int32Array,
f32: Float32Array,
f64: Float64Array,
};

export interface TypedArrayTypeMap extends Record<Type | GLType, TypedArray> {
[Type.U8]: Uint8Array;
[Type.U8C]: Uint8ClampedArray;
[Type.I8]: Int8Array;
[Type.U16]: Uint16Array;
[Type.I16]: Int16Array;
[Type.U32]: Uint32Array;
[Type.I32]: Int32Array;
[Type.F32]: Float32Array;
[Type.F64]: Float64Array;
u8: Uint8Array;
u8c: Uint8ClampedArray;
i8: Int8Array;
u16: Uint16Array;
i16: Int16Array;
u32: Uint32Array;
i32: Int32Array;
f32: Float32Array;
f64: Float64Array;
[GLType.U8]: Uint8Array;
[GLType.I8]: Int8Array;
[GLType.U16]: Uint16Array;
Expand All @@ -158,6 +147,46 @@ export interface TypedArrayTypeMap extends Record<Type | GLType, TypedArray> {
[GLType.F32]: Float32Array;
}

/**
* Returns canonical {@link Type} value of `type` by first
* attempting to resolve it as {@link GLType} enum.
*
* @example
* ```ts
* asNativeType(GLType.F32) => "f32"
* asNativeType("f32") => "f32"
* ```
*
* @param type -
*/
export const asNativeType = (type: GLType | Type): Type => {
const t = (<any>GL2TYPE)[type];
return t !== undefined ? t : <Type>type;
};

/**
* Returns suitable {@link GLType} enum of `type`.
*
* @example
* ```ts
* asGLType("f32") => GLType.F32
* asGLType(GLType.F32) => GLType.F32
* ```
*
* @param type -
*/
export const asGLType = (type: GLType | Type): GLType => {
const t = (<any>TYPE2GL)[type];
return t !== undefined ? t : <GLType>type;
};

/**
* Returns byte size for given {@link Type} ID or {@link GLType} enum.
*
* @param type
*/
export const sizeOf = (type: GLType | Type) => SIZEOF[asNativeType(type)];

/**
* Constructs new typed array of given {@link Type}/{@link GLType}. Supports all
* arities of standard typed array ctors.
Expand All @@ -171,41 +200,53 @@ export function typedArray<T extends Type | GLType>(type: T, src: ArrayLike<numb
// prettier-ignore
export function typedArray<T extends Type | GLType>(type: T, buf: ArrayBufferLike, byteOffset: number, length?: number): TypedArrayTypeMap[T];
export function typedArray<T extends Type | GLType>(type: T, ...xs: any[]) {
return new (<any>TYPEDARRAY_CTORS[type])(...xs);
return new (<any>TYPEDARRAY_CTORS[asNativeType(type)])(...xs);
}

/**
* Takes an {@link NumericArray} and returns its corresponding {@link Type} ID.
* Standard JS arrays will default to {@link Type.F64}.
* Standard JS arrays will default to {@link "f64"}.
*
* @param x
*/
export const typedArrayType = (x: NumericArray) => {
if (Array.isArray(x)) return Type.F64;
if (Array.isArray(x)) return "f64";
for (let id in TYPEDARRAY_CTORS) {
if (x instanceof (<any>TYPEDARRAY_CTORS)[id]) return <Type>Number(id);
if (x instanceof (<any>TYPEDARRAY_CTORS)[id]) return <Type>id;
}
return Type.F64;
return "f64";
};

/**
* Returns the smallest possible *unsigned* int type enum for given `x`.
* E.g. if `x <= 256`, the function returns `Type.U8`.
* E.g. if `x <= 256`, the function returns `"u8"`.
*
* @param x - value to classify
*/
export const uintType = (x: number): UintType =>
x <= 0x100 ? Type.U8 : x <= 0x10000 ? Type.U16 : Type.U32;
export const uintTypeForSize = (x: number): UintType =>
x <= 0x100 ? "u8" : x <= 0x10000 ? "u16" : "u32";

/**
* Returns the smallest possible *signed* int type enum for given `x`.
* E.g. if `x >= -128 && x < 128`, the function returns `Type.I8`.
* E.g. if `x >= -128 && x < 128`, the function returns `"i8"`.
*
* @param x - value to classify
*/
export const intType = (x: number): IntType =>
x >= -0x80 && x < 0x80
? Type.I8
: x >= -0x8000 && x < 0x8000
? Type.I16
: Type.I32;
export const intTypeForSize = (x: number): IntType =>
x >= -0x80 && x < 0x80 ? "i8" : x >= -0x8000 && x < 0x8000 ? "i16" : "i32";

/**
* Returns suitable {@link UintType} for given bit size (`[0,32]` range)
*
* @param x
*/
export const uintTypeForBits = (x: number): UintType =>
x > 16 ? "u32" : x > 8 ? "u16" : "u8";

/**
* Returns suitable {@link IntType} for given bit size (`[0,32]` range)
*
* @param x
*/
export const intTypeForBits = (x: number): IntType =>
x > 16 ? "i32" : x > 8 ? "i16" : "i8";

0 comments on commit a333d41

Please sign in to comment.