Source: types/vector.js

"use strict";
/** @module types */

const util = require("node:util");
class Vector {
    /**
     *
     * @param {Float32Array | Array<any>} elements
     * @param {string} [subtype]
     */
    constructor(elements, subtype) {
        if (elements instanceof Float32Array) {
            this.elements = Array.from(elements);
        } else if (Array.isArray(elements)) {
            this.elements = elements;
        } else {
            throw new TypeError(
                "Vector must be constructed with a Float32Array or an Array",
            );
        }
        if (this.elements.length === 0) {
            throw new TypeError("Vector must contain at least one value");
        }
        /**
         * Returns the number of the elements.
         * @type Number
         */
        this.length = this.elements.length;
        this.subtype = subtype;

        // eslint-disable-next-line no-constructor-return
        return new Proxy(this, {
            get: function (obj, key) {
                if (key === "IDENTITY") {
                    return "Vector";
                } else if (
                    typeof key === "string" &&
                    Number.isInteger(Number(key))
                ) {
                    // key is an index
                    return obj.elements[key];
                }
                return obj[key];
            },
            set: function (obj, key, value) {
                if (typeof key === "string" && Number.isInteger(Number(key))) {
                    // key is an index
                    return (obj.elements[key] = value);
                }
                return (obj[key] = value);
            },
            ownKeys: function (obj) {
                return Reflect.ownKeys(elements);
            },
            getOwnPropertyDescriptor(target, key) {
                if (typeof key === "string" && Number.isInteger(Number(key))) {
                    // array index
                    return { enumerable: true, configurable: true };
                }
                return Reflect.getOwnPropertyDescriptor(target, key);
            },
        });
    }
    /**
     * Returns the string representation of the vector.
     * @returns {string}
     */
    toString() {
        return "[".concat(this.elements.toString(), "]");
    }
    /**
     *
     * @param {number} index
     */
    at(index) {
        return this.elements[index];
    }

    /**
     *
     * @returns {IterableIterator<any>} an iterator over the elements of the vector
     */
    [Symbol.iterator]() {
        return this.elements[Symbol.iterator]();
    }

    static get [Symbol.species]() {
        return Vector;
    }

    forEach(callback) {
        return this.elements.forEach(callback);
    }

    /**
     * @returns {string | undefined} get the subtype string, e.g., "float", but it's optional so it can return undefined
     */
    getSubtype() {
        return this.subtype;
    }
}

Object.defineProperty(Vector, Symbol.hasInstance, {
    value: function (i) {
        return (
            (util.types.isProxy(i) && i.IDENTITY === "Vector") ||
            i instanceof Float32Array
        );
    },
});

module.exports = Vector;