"use strict";
/*
This is inspired by emscripten's MIT-licensed src/library_dylink.js.
*/
Object.defineProperty(exports, "__esModule", { value: true });
function getMetadata(binary) {
    var offset = 0;
    var end = 0;
    function getU8() {
        return binary[offset++];
    }
    function getLEB() {
        var ret = 0;
        var mul = 1;
        while (1) {
            var byte = binary[offset++];
            ret += (byte & 0x7f) * mul;
            mul *= 0x80;
            if (!(byte & 0x80))
                break;
        }
        return ret;
    }
    function getString() {
        var len = getLEB();
        offset += len;
        return UTF8ArrayToString(binary, offset - len, len);
    }
    function failIf(condition, message) {
        if (condition)
            throw new Error(message);
    }
    var name = "dylink.0";
    var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer);
    var magicNumberFound = int32View[0] == 0x6d736100;
    failIf(!magicNumberFound, "need to see wasm magic number"); // \0asm
    // we should see the dylink custom section right after the magic number and wasm version
    failIf(binary[8] !== 0, "need the dylink section to be first");
    offset = 9;
    var section_size = getLEB(); //section size
    end = offset + section_size;
    name = getString();
    var customSection = {
        neededDynlibs: [],
        tlsExports: new Set(),
        weakImports: new Set(),
    };
    if (customSection.neededDynlibs == null)
        throw Error("bug: typescript");
    if (customSection.tlsExports == null)
        throw Error("bug: typescript");
    if (customSection.weakImports == null)
        throw Error("bug: typescript");
    if (name == "dylink") {
        customSection.memorySize = getLEB();
        customSection.memoryAlign = getLEB();
        customSection.tableSize = getLEB();
        customSection.tableAlign = getLEB();
        // shared libraries this module needs. We need to load them first, so that
        // current module could resolve its imports. (see tools/shared.py
        // WebAssembly.make_shared_library() for "dylink" section extension format)
        var neededDynlibsCount = getLEB();
        for (var i = 0; i < neededDynlibsCount; ++i) {
            var libname = getString();
            customSection.neededDynlibs.push(libname);
        }
    }
    else {
        failIf(name !== "dylink.0", "invalid format -- name must be dylink.0 or dylink");
        var WASM_DYLINK_MEM_INFO = 0x1;
        var WASM_DYLINK_NEEDED = 0x2;
        var WASM_DYLINK_EXPORT_INFO = 0x3;
        var WASM_DYLINK_IMPORT_INFO = 0x4;
        var WASM_SYMBOL_TLS = 0x100;
        var WASM_SYMBOL_BINDING_MASK = 0x3;
        var WASM_SYMBOL_BINDING_WEAK = 0x1;
        while (offset < end) {
            var subsectionType = getU8();
            var subsectionSize = getLEB();
            if (subsectionType === WASM_DYLINK_MEM_INFO) {
                customSection.memorySize = getLEB();
                customSection.memoryAlign = getLEB();
                customSection.tableSize = getLEB();
                customSection.tableAlign = getLEB();
            }
            else if (subsectionType === WASM_DYLINK_NEEDED) {
                var neededDynlibsCount = getLEB();
                for (var i = 0; i < neededDynlibsCount; ++i) {
                    var libname = getString();
                    customSection.neededDynlibs.push(libname);
                }
            }
            else if (subsectionType === WASM_DYLINK_EXPORT_INFO) {
                var count = getLEB();
                while (count--) {
                    var symname = getString();
                    var flags = getLEB();
                    if (flags & WASM_SYMBOL_TLS) {
                        customSection.tlsExports.add(symname);
                    }
                }
            }
            else if (subsectionType === WASM_DYLINK_IMPORT_INFO) {
                var count = getLEB();
                while (count--) {
                    getString(); //  module name -- not used, but have to read to get offset right.
                    var symname = getString();
                    var flags = getLEB();
                    if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
                        customSection.weakImports.add(symname);
                    }
                }
            }
            else {
                // unknown subsection
                offset += subsectionSize;
            }
        }
    }
    return customSection;
}
exports.default = getMetadata;
// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array
// that contains uint8 values, returns a copy of that string as a Javascript
// string object.
var UTF8Decoder = new TextDecoder();
function UTF8ArrayToString(binary, ptr, maxBytesToRead) {
    var endIdx = ptr + maxBytesToRead;
    var endPtr = ptr;
    while (binary[endPtr] && endPtr < endIdx) {
        endPtr++;
    }
    var slice = binary.slice(ptr, endPtr);
    return UTF8Decoder.decode(slice);
}
//# sourceMappingURL=metadata.js.map