// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/*
 * This public interface for parsing the AWS Encryption SDK Message Header Format
 * 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.
 *
 * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-structure
 */
import { EncryptedDataKey, needs } from '@aws-crypto/material-management';
import { readElements } from './read_element';
// To deal with Browser and Node.js I inject a function to handle utf8 encoding.
export function deserializeEncryptedDataKeysFactory(toUtf8) {
    return deserializeEncryptedDataKeys;
    /**
     * Exported for testing.  Used by deserializeMessageHeader to compose a complete solution.
     * @param buffer Uint8Array
     * @param startPos number
     * @param deserializeOptions DeserializeOptions
     */
    function deserializeEncryptedDataKeys(buffer, startPos, { maxEncryptedDataKeys } = {
        maxEncryptedDataKeys: false,
    }) {
        /* Precondition: startPos must be within the byte length of the buffer given. */
        needs(buffer.byteLength >= startPos && startPos >= 0, 'startPos out of bounds.');
        /* Precondition: deserializeEncryptedDataKeys needs a valid maxEncryptedDataKeys. */
        needs(maxEncryptedDataKeys === false || maxEncryptedDataKeys >= 1, 'Invalid maxEncryptedDataKeys value.');
        /* Check for early return (Postcondition): Need to have at least Uint16 (2) bytes of data. */
        if (startPos + 2 > buffer.byteLength)
            return false;
        /* 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 encryptedDataKeysCount = dataView.getUint16(startPos, false); // big endian
        /* Precondition: There must be at least 1 EncryptedDataKey element. */
        needs(encryptedDataKeysCount, 'No EncryptedDataKey found.');
        /* Precondition: encryptedDataKeysCount must not exceed maxEncryptedDataKeys. */
        needs(maxEncryptedDataKeys === false ||
            encryptedDataKeysCount <= maxEncryptedDataKeys, 'maxEncryptedDataKeys exceeded.');
        const elementInfo = readElements(encryptedDataKeysCount, 3, buffer, startPos + 2);
        /* Check for early return (Postcondition): readElement will return false if there is not enough data.
         * I can only continue if I have at least the entire EDK section.
         */
        if (!elementInfo)
            return false;
        const { elements, readPos } = elementInfo;
        const encryptedDataKeys = elements.map(([rawId, rawInfo, encryptedDataKey]) => {
            const providerId = toUtf8(rawId);
            const providerInfo = toUtf8(rawInfo);
            return new EncryptedDataKey({
                providerInfo,
                providerId,
                encryptedDataKey,
                rawInfo,
            });
        });
        Object.freeze(encryptedDataKeys);
        return { encryptedDataKeys, readPos };
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzZXJpYWxpemVfZW5jcnlwdGVkX2RhdGFfa2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZXNlcmlhbGl6ZV9lbmNyeXB0ZWRfZGF0YV9rZXlzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9FQUFvRTtBQUNwRSxzQ0FBc0M7QUFFdEM7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQTtBQUV6RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFN0MsZ0ZBQWdGO0FBQ2hGLE1BQU0sVUFBVSxtQ0FBbUMsQ0FDakQsTUFBcUM7SUFFckMsT0FBTyw0QkFBNEIsQ0FBQTtJQUVuQzs7Ozs7T0FLRztJQUNILFNBQVMsNEJBQTRCLENBQ25DLE1BQWtCLEVBQ2xCLFFBQWdCLEVBQ2hCLEVBQUUsb0JBQW9CLEtBQXlCO1FBQzdDLG9CQUFvQixFQUFFLEtBQUs7S0FDNUI7UUFJRCxnRkFBZ0Y7UUFDaEYsS0FBSyxDQUNILE1BQU0sQ0FBQyxVQUFVLElBQUksUUFBUSxJQUFJLFFBQVEsSUFBSSxDQUFDLEVBQzlDLHlCQUF5QixDQUMxQixDQUFBO1FBRUQsb0ZBQW9GO1FBQ3BGLEtBQUssQ0FDSCxvQkFBb0IsS0FBSyxLQUFLLElBQUksb0JBQW9CLElBQUksQ0FBQyxFQUMzRCxxQ0FBcUMsQ0FDdEMsQ0FBQTtRQUVELDZGQUE2RjtRQUM3RixJQUFJLFFBQVEsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLFVBQVU7WUFBRSxPQUFPLEtBQUssQ0FBQTtRQUVsRDs7Ozs7V0FLRztRQUNILE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxDQUMzQixNQUFNLENBQUMsTUFBTSxFQUNiLE1BQU0sQ0FBQyxVQUFVLEVBQ2pCLE1BQU0sQ0FBQyxVQUFVLENBQ2xCLENBQUE7UUFDRCxNQUFNLHNCQUFzQixHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFBLENBQUMsYUFBYTtRQUVoRixzRUFBc0U7UUFDdEUsS0FBSyxDQUFDLHNCQUFzQixFQUFFLDRCQUE0QixDQUFDLENBQUE7UUFFM0QsZ0ZBQWdGO1FBQ2hGLEtBQUssQ0FDSCxvQkFBb0IsS0FBSyxLQUFLO1lBQzVCLHNCQUFzQixJQUFJLG9CQUFvQixFQUNoRCxnQ0FBZ0MsQ0FDakMsQ0FBQTtRQUVELE1BQU0sV0FBVyxHQUFHLFlBQVksQ0FDOUIsc0JBQXNCLEVBQ3RCLENBQUMsRUFDRCxNQUFNLEVBQ04sUUFBUSxHQUFHLENBQUMsQ0FDYixDQUFBO1FBQ0Q7O1dBRUc7UUFDSCxJQUFJLENBQUMsV0FBVztZQUFFLE9BQU8sS0FBSyxDQUFBO1FBQzlCLE1BQU0sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsV0FBVyxDQUFBO1FBRXpDLE1BQU0saUJBQWlCLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FDcEMsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsRUFBRSxFQUFFO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNoQyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDcEMsT0FBTyxJQUFJLGdCQUFnQixDQUFDO2dCQUMxQixZQUFZO2dCQUNaLFVBQVU7Z0JBQ1YsZ0JBQWdCO2dCQUNoQixPQUFPO2FBQ1IsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUNGLENBQUE7UUFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDaEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxDQUFBO0lBQ3ZDLENBQUM7QUFDSCxDQUFDIn0=