"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PathMapImpl = exports.IndexAllocator = void 0;
class PathMapNode {
    constructor() {
        this.further = new Map();
    }
    *entries(existing) {
        if (this.value !== undefined)
            yield [existing, this.value];
        for (const [step, child] of this.further) {
            yield* child.entries([...existing, step]);
        }
    }
    *postRootEntries(existing) {
        if (this.value !== undefined)
            yield [existing, this.value];
        for (const [step, child] of this.further) {
            yield* child.postRootEntries([...existing, step]);
        }
    }
    *values() {
        if (this.value !== undefined)
            yield this.value;
        for (const child of this.further.values())
            yield* child.values();
    }
}
class IndexAllocator {
    constructor() {
        this.index = 0;
    }
    next() {
        return this.index++;
    }
    get count() {
        return this.index;
    }
}
exports.IndexAllocator = IndexAllocator;
class PathMapLensImpl {
    constructor(node) {
        this.current = node;
    }
    get() {
        return this.current.value;
    }
    set(value) {
        this.current.value = value;
    }
    getOrPut(value) {
        const existing = this.current.value;
        if (existing === undefined) {
            this.current.value = value;
            return value;
        }
        else {
            return existing;
        }
    }
    getOrAlloc(alloc, ...r) {
        const existing = this.current.value;
        if (existing === undefined) {
            const value = alloc.next(...r);
            this.current.value = value;
            return value;
        }
        else {
            return existing;
        }
    }
    advance(step) {
        const nextNode = this.current.further.get(step);
        if (nextNode) {
            this.current = nextNode;
            return true;
        }
        else {
            return false;
        }
    }
    focusGet(steps) {
        for (const step of steps) {
            const result = this.advance(step);
            if (!result)
                return false;
        }
        return true;
    }
    advanceCreate(step) {
        const nextNode = this.current.further.get(step);
        if (nextNode) {
            this.current = nextNode;
        }
        else {
            const n = new PathMapNode();
            this.current.further.set(step, n);
            this.current = n;
        }
    }
    focus(steps) {
        for (const step of steps) {
            this.advanceCreate(step);
        }
    }
}
class PathMapImpl {
    constructor() {
        this.root = new PathMapNode();
    }
    createLens() {
        return new PathMapLensImpl(this.root);
    }
    get(steps) {
        const lens = this.createLens();
        const focused = lens.focusGet(steps);
        if (!focused)
            return undefined;
        else
            return lens.get();
    }
    set(steps, value) {
        const lens = this.createLens();
        lens.focus(steps);
        lens.set(value);
    }
    entries() {
        return this.root.entries([]);
    }
    postRootEntries() {
        return this.root.postRootEntries([]);
    }
    values() {
        return this.root.values();
    }
    static create(iter) {
        const pm = new PathMapImpl();
        if (iter)
            for (const [key, value] of iter)
                pm.set(key, value);
        return pm;
    }
}
exports.PathMapImpl = PathMapImpl;
//# sourceMappingURL=index.js.map