"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DirectoryContents = void 0;
const _1 = require(".");
const blake3_1 = require("@noble/hashes/blake3");
const varint_1 = require("./varint");
const __1 = require("..");
class DirectoryContents {
    constructor(contents) {
        this.contents = contents;
    }
    static async deserialize(source, header, sighash, maxSize) {
        const position = header.nextU64();
        const size = header.nextU64();
        if (size > maxSize) {
            throw new Error('size is greater than signed');
        }
        const tocReader = new _1.ArrayBufferReader(await source
            .slice(Number(position), Number(position + size))
            .arrayBuffer());
        const len = tocReader.nextVarint();
        const entries = {};
        for (let i = 0; i < len; i++) {
            const name = tocReader.nextVarstring();
            const entry = await _1.Entry.deserialize(source, tocReader);
            entries[name] = entry;
        }
        const res = new DirectoryContents(entries);
        if (!(0, __1.compare)(res.sighash(), sighash)) {
            throw new Error('hash sum does not match');
        }
        return res;
    }
    sighash() {
        const hasher = blake3_1.blake3.create({});
        const names = Object.keys(this.contents).sort();
        hasher.update(new Uint8Array((0, varint_1.serializeVarint)(names.length)));
        for (const name of names) {
            const entry = this.contents[name];
            const nameBuf = new TextEncoder().encode(name);
            hasher.update(new Uint8Array((0, varint_1.serializeVarint)(nameBuf.length)));
            hasher.update(nameBuf);
            hasher.update(new Uint8Array(entry.hash));
            const sizeBuf = new Uint8Array(8);
            new DataView(sizeBuf.buffer).setBigUint64(0, entry.size);
            hasher.update(sizeBuf);
            hasher.update(new Uint8Array([0]));
        }
        return hasher.digest();
    }
    getPath(path) {
        if (path.length === 0) {
            return null;
        }
        const next = this.contents[path[0]];
        const rest = path.slice(1);
        if (next === undefined) {
            return null;
        }
        if (rest.length === 0) {
            return next;
        }
        if (next.contents instanceof DirectoryContents) {
            return next.contents.getPath(rest);
        }
        return null;
    }
}
exports.DirectoryContents = DirectoryContents;
DirectoryContents.headerSize = 8 + // position: u64 BE
    8; // size: u64 BE
//# sourceMappingURL=directoryContents.js.map