var TypedArrayType;
(function (TypedArrayType) {
    TypedArrayType[TypedArrayType["Uint8"] = 0] = "Uint8";
    TypedArrayType[TypedArrayType["Uint16"] = 1] = "Uint16";
    TypedArrayType[TypedArrayType["Uint32"] = 2] = "Uint32";
    TypedArrayType[TypedArrayType["Float32"] = 3] = "Float32";
})(TypedArrayType || (TypedArrayType = {}));
const TYPED_ARRAYS = {
    [TypedArrayType.Uint8]: Uint8Array,
    [TypedArrayType.Uint16]: Uint16Array,
    [TypedArrayType.Uint32]: Uint32Array,
    [TypedArrayType.Float32]: Float32Array
};
// TODO: It would probably be good to validate that we're staying within bounds.
// TDOO: Data view might be a good option
export class ArrayBufferReader {
    buffer;
    offsetInBytes;
    static _typedArrayByteAlignment = 4;
    constructor(buffer, offsetInBytes = 0) {
        this.buffer = buffer;
        this.offsetInBytes = offsetInBytes;
    }
    uint8(n) {
        const result = new Uint8Array(this.buffer, this.offsetInBytes, n);
        this.offsetInBytes += n * Uint8Array.BYTES_PER_ELEMENT;
        return result;
    }
    uint16(n) {
        const result = new Uint16Array(this.buffer, this.offsetInBytes, n);
        this.offsetInBytes += n * Uint16Array.BYTES_PER_ELEMENT;
        return result;
    }
    uint32(n) {
        const result = new Uint32Array(this.buffer, this.offsetInBytes, n);
        this.offsetInBytes += n * Uint32Array.BYTES_PER_ELEMENT;
        return result;
    }
    float32(n) {
        const result = new Float32Array(this.buffer, this.offsetInBytes, n);
        this.offsetInBytes += n * Float32Array.BYTES_PER_ELEMENT;
        return result;
    }
    float64(n) {
        const result = new Float64Array(this.buffer, this.offsetInBytes, n);
        this.offsetInBytes += n * Float64Array.BYTES_PER_ELEMENT;
        return result;
    }
    typedArray(n) {
        const arrayType = this.uint32(1)[0];
        const constructor = TYPED_ARRAYS[arrayType];
        if (constructor == null) {
            throw new Error(`Unsupported array type: ${arrayType}`);
        }
        const array = new constructor(this.buffer, this.offsetInBytes, n);
        const sizeInBytes = n * constructor.BYTES_PER_ELEMENT;
        this.offsetInBytes += sizeInBytes;
        this.readPadding(ArrayBufferReader._typedArrayByteAlignment, true);
        return { array, sizeInBytes };
    }
    readPadding(alignmentInBytes, throwOnInvalidPadding) {
        const padCount = this.getPadByteCount(alignmentInBytes);
        if (padCount === 0) {
            return 0;
        }
        if (throwOnInvalidPadding) {
            const bytes = this.uint8(padCount);
            for (let i = 0; i < padCount; ++i) {
                const isValid = bytes[i] === 1 << i % 8;
                if (!isValid) {
                    throw new Error('Invalid padding');
                }
            }
        }
        return padCount;
    }
    getPadByteCount(alignmentInBytes) {
        if (this.offsetInBytes % alignmentInBytes === 0) {
            return 0;
        }
        return alignmentInBytes - (this.offsetInBytes % alignmentInBytes);
    }
}
//# sourceMappingURL=ArrayBufferReader.js.map