"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.decodeEncryptionContextFactory = void 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
 */
const material_management_1 = require("@aws-crypto/material-management");
const read_element_1 = require("./read_element");
// To deal with Browser and Node.js I inject a function to handle utf8 encoding.
function decodeEncryptionContextFactory(toUtf8) {
    return decodeEncryptionContext;
    /**
     * Exported for testing.  Used by deserializeMessageHeader to compose a complete solution.
     * @param encodedEncryptionContext Uint8Array
     */
    function decodeEncryptionContext(encodedEncryptionContext) {
        const encryptionContext = Object.create(null);
        /* Check for early return (Postcondition): The case of 0 length is defined as an empty object. */
        if (!encodedEncryptionContext.byteLength) {
            return Object.freeze(encryptionContext);
        }
        /* 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(encodedEncryptionContext.buffer, encodedEncryptionContext.byteOffset, encodedEncryptionContext.byteLength);
        const pairsCount = dataView.getUint16(0, false); // big endian
        const elementInfo = (0, read_element_1.readElements)(pairsCount, 2, encodedEncryptionContext, 2);
        /* Postcondition: Since the encryption context has a length, it must have pairs.
         * Unlike the encrypted data key section, the encryption context has a length
         * element.  This means I should always pass the entire section.
         */
        if (!elementInfo)
            throw new Error('context parse error');
        const { elements, readPos } = elementInfo;
        /* Postcondition: The byte length of the encodedEncryptionContext must match the readPos. */
        (0, material_management_1.needs)(encodedEncryptionContext.byteLength === readPos, 'Overflow, too much data.');
        for (let count = 0; count < pairsCount; count++) {
            const [key, value] = elements[count].map(toUtf8);
            /* Postcondition: The number of keys in the encryptionContext must match the pairsCount.
             * If the same Key value is serialized...
             */
            (0, material_management_1.needs)(encryptionContext[key] === undefined, 'Duplicate encryption context key value.');
            encryptionContext[key] = value;
        }
        Object.freeze(encryptionContext);
        return encryptionContext;
    }
}
exports.decodeEncryptionContextFactory = decodeEncryptionContextFactory;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb2RlX2VuY3J5cHRpb25fY29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvZGVfZW5jcnlwdGlvbl9jb250ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxvRUFBb0U7QUFDcEUsc0NBQXNDOzs7QUFFdEM7Ozs7Ozs7R0FPRztBQUVILHlFQUEwRTtBQUMxRSxpREFBNkM7QUFFN0MsZ0ZBQWdGO0FBQ2hGLFNBQWdCLDhCQUE4QixDQUM1QyxNQUFxQztJQUVyQyxPQUFPLHVCQUF1QixDQUFBO0lBRTlCOzs7T0FHRztJQUNILFNBQVMsdUJBQXVCLENBQzlCLHdCQUFvQztRQUVwQyxNQUFNLGlCQUFpQixHQUFzQixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ2hFLGlHQUFpRztRQUNqRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFO1lBQ3hDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1NBQ3hDO1FBQ0Q7Ozs7O1dBS0c7UUFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FDM0Isd0JBQXdCLENBQUMsTUFBTSxFQUMvQix3QkFBd0IsQ0FBQyxVQUFVLEVBQ25DLHdCQUF3QixDQUFDLFVBQVUsQ0FDcEMsQ0FBQTtRQUNELE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBLENBQUMsYUFBYTtRQUM3RCxNQUFNLFdBQVcsR0FBRyxJQUFBLDJCQUFZLEVBQUMsVUFBVSxFQUFFLENBQUMsRUFBRSx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUM1RTs7O1dBR0c7UUFDSCxJQUFJLENBQUMsV0FBVztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQTtRQUN4RCxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQTtRQUV6Qyw0RkFBNEY7UUFDNUYsSUFBQSwyQkFBSyxFQUNILHdCQUF3QixDQUFDLFVBQVUsS0FBSyxPQUFPLEVBQy9DLDBCQUEwQixDQUMzQixDQUFBO1FBRUQsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLFVBQVUsRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUMvQyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDaEQ7O2VBRUc7WUFDSCxJQUFBLDJCQUFLLEVBQ0gsaUJBQWlCLENBQUMsR0FBRyxDQUFDLEtBQUssU0FBUyxFQUNwQyx5Q0FBeUMsQ0FDMUMsQ0FBQTtZQUNELGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQTtTQUMvQjtRQUNELE1BQU0sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQTtRQUNoQyxPQUFPLGlCQUFpQixDQUFBO0lBQzFCLENBQUM7QUFDSCxDQUFDO0FBekRELHdFQXlEQyJ9