"use strict";
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.readElements = void 0;
/*
 * This public interface for reading part of the encrypted header is provided for
 * the use of the Encryption SDK for JavaScript only.  It can be used
 * as a reference but is not intended to be use by any packages other
 * than the Encryption SDK for JavaScript.
 *
 * This is used to read the AAD Section and the Encrypted Data Key(s) section.
 *
 * See:
 * https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad
 * https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-data-keys
 */
const material_management_1 = require("@aws-crypto/material-management");
/**
 *
 * The encryption SDK stores elements in the form of length data.
 * e.g. 04data.  The length element is Uint16 Big Endian.
 * So knowing the number of elements of this form I can
 * advance through a buffer.  The rub comes when streaming
 * data.  The I may know the number of elements, but not
 * yet have all the data.  In this case I check the lengths and
 * return false.
 *
 * @param elementCount
 * @param buffer
 * @param readPos
 */
function readElements(elementCount, fieldsPerElement, buffer, readPos = 0) {
    /* Uint8Array is a view on top of the underlying ArrayBuffer.
     * This means that raw underlying memory stored in the ArrayBuffer
     * may be larger than the Uint8Array.  This is especially true of
     * the Node.js Buffer object.  The offset and length *must* be
     * passed to the DataView otherwise I will get unexpected results.
     */
    const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
    const elements = [];
    /* Precondition: readPos must be non-negative and within the byte length of the buffer given. */
    (0, material_management_1.needs)(readPos >= 0 && dataView.byteLength >= readPos, 'readPos out of bounds.');
    /* Precondition: elementCount and fieldsPerElement must be non-negative. */
    (0, material_management_1.needs)(elementCount >= 0 && fieldsPerElement >= 0, 'elementCount and fieldsPerElement must be positive.');
    while (elementCount--) {
        const element = [];
        let fieldCount = fieldsPerElement;
        while (fieldCount--) {
            /* Check for early return (Postcondition): Enough data must exist to read the Uint16 length value. */
            if (readPos + 2 > dataView.byteLength)
                return false;
            const length = dataView.getUint16(readPos, false); // big endian
            readPos += 2;
            /* Check for early return (Postcondition): Enough data must exist length of the value. */
            if (readPos + length > dataView.byteLength)
                return false;
            const fieldBinary = buffer.slice(readPos, readPos + length);
            element.push(fieldBinary);
            readPos += length;
        }
        elements.push(element);
    }
    return { elements, readPos };
}
exports.readElements = readElements;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhZF9lbGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JlYWRfZWxlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsb0VBQW9FO0FBQ3BFLHNDQUFzQzs7O0FBRXRDOzs7Ozs7Ozs7OztHQVdHO0FBRUgseUVBQXVEO0FBQ3ZEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxTQUFnQixZQUFZLENBQzFCLFlBQW9CLEVBQ3BCLGdCQUF3QixFQUN4QixNQUFrQixFQUNsQixPQUFPLEdBQUcsQ0FBQztJQUVYOzs7OztPQUtHO0lBQ0gsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLENBQzNCLE1BQU0sQ0FBQyxNQUFNLEVBQ2IsTUFBTSxDQUFDLFVBQVUsRUFDakIsTUFBTSxDQUFDLFVBQVUsQ0FDbEIsQ0FBQTtJQUNELE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQTtJQUVuQixnR0FBZ0c7SUFDaEcsSUFBQSwyQkFBSyxFQUNILE9BQU8sSUFBSSxDQUFDLElBQUksUUFBUSxDQUFDLFVBQVUsSUFBSSxPQUFPLEVBQzlDLHdCQUF3QixDQUN6QixDQUFBO0lBRUQsMkVBQTJFO0lBQzNFLElBQUEsMkJBQUssRUFDSCxZQUFZLElBQUksQ0FBQyxJQUFJLGdCQUFnQixJQUFJLENBQUMsRUFDMUMscURBQXFELENBQ3RELENBQUE7SUFFRCxPQUFPLFlBQVksRUFBRSxFQUFFO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQTtRQUNsQixJQUFJLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQTtRQUNqQyxPQUFPLFVBQVUsRUFBRSxFQUFFO1lBQ25CLHFHQUFxRztZQUNyRyxJQUFJLE9BQU8sR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLFVBQVU7Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFDbkQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUEsQ0FBQyxhQUFhO1lBQy9ELE9BQU8sSUFBSSxDQUFDLENBQUE7WUFDWix5RkFBeUY7WUFDekYsSUFBSSxPQUFPLEdBQUcsTUFBTSxHQUFHLFFBQVEsQ0FBQyxVQUFVO2dCQUFFLE9BQU8sS0FBSyxDQUFBO1lBQ3hELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQTtZQUMzRCxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBQ3pCLE9BQU8sSUFBSSxNQUFNLENBQUE7U0FDbEI7UUFDRCxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0tBQ3ZCO0lBQ0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQTtBQUM5QixDQUFDO0FBaERELG9DQWdEQyJ9