/** * @module * * Utility types and functions. */ import type { MemberClassKeys, MemberedClass } from './members.js'; import type { Type } from './type.js'; const dataViews = new WeakMap(); /** * Get reusable data view of buffer. * * @param buffer Array buffer. * @returns Data view. */ export function dataView(buffer: ArrayBufferLike): DataView { let r = dataViews.get(buffer); if (!r) { dataViews.set(buffer, r = new DataView(buffer)); } return r; } /** * Parse property key to array index (see CanonicalNumericIndexString). * * @param key Property key. * @returns Number or undefined if not a numeric index. */ export function parseIndex(key: string | symbol): number | undefined { let i; return key === '-0' ? -0 : (key === '' + (i = +String(key)) ? i : undefined); } /** * Get byte offset of member. * * @template T Type class. * @param Type Type class. * @param name Member name. * @returns Byte offset. */ export function getByteOffset( Type: T, name: MemberClassKeys, ): number { return Type.MEMBERS[name].byteOffset; } /** * Get byte length of member. * * @template T Type class. * @param Type Type class. * @param name Member name. * @returns Byte length. */ export function getByteLength( Type: T, name: MemberClassKeys, ): number { return Type.MEMBERS[name].byteLength; } /** * Get members of type. * Array indexes then member keys from highest to lowest inheritance. * * @template T Type class. * @param Type Type class. * @returns Member list. */ export function getMembers( Type: T, ): (keyof InstanceType)[] { const props: Set | PropertyKey[] = new Set(); for (let m = Type.MEMBERS; m; m = Object.getPrototypeOf(m)) { const keys = Reflect.ownKeys(m); for (let i = keys.length; i--;) { const k = keys[i]; props.delete(k); props.add(k); } } if ('LENGTH' in Type) { for (let i = Type.LENGTH; i--;) { props.delete(`${i}`); props.add(i); } } return [...props].reverse() as (keyof InstanceType)[]; } /** * Assign ArrayBuffer data from one view to another. * * @template D Destination type. * @param dst Destination memory. * @param src Source memory of equal or greater size. * @returns Destination memory. */ export function assignView( dst: D, src: ArrayBufferView, ): D { const { byteLength } = dst; new Uint8Array(dst.buffer, dst.byteOffset, byteLength).set( new Uint8Array(src.buffer, src.byteOffset, byteLength), ); return dst; } /** * Assign ArrayBuffer data from one type to another. * * @template D Destination type. * @template S Source type. * @param dst Destination type. * @param src Source type, must extend destination type. * @returns Destination type. */ export function assignType( dst: D, src: S, ): D { return assignView(dst, src); }