import { LRUMapWithDelete } from 'mnemonist';
/**
 * A specialized LRU map that enforces limits on both the number of entries and
 * the total character length of the keys.
 *
 * When adding a new item, if the new key's length would exceed `maxDataSize`,
 * it evicts the least recently used items until space is available.
 *
 * @template V - The type of the values stored in the map.
 */
export class DataLimitedLruMap {
    map;
    maxDataSize;
    currentDataSize = 0;
    constructor(maxKeys, maxDataSize) {
        this.map = new LRUMapWithDelete(maxKeys);
        this.maxDataSize = maxDataSize;
    }
    get(key) {
        return this.map.get(key);
    }
    set(key, value) {
        const size = key.length;
        const hasKey = this.map.has(key);
        while (this.currentDataSize + size > this.maxDataSize &&
            this.map.size > 0) {
            const map = this.map;
            const lruKey = map.K[map.tail];
            if (lruKey === undefined) {
                break;
            }
            // If the key is not found in the map, we can't evict it.
            // This can happen if the map is in an inconsistent state.
            // To avoid an infinite loop, we break here.
            // The LRUMap still has its own size limit so it is acceptable
            // for us to make a best effort to stay within the data size limit.
            // The alternative would be to continue searching for a valid key
            // to delete but that would risk making calling set O(n) instead of
            // O(1).
            if (!this.map.delete(lruKey)) {
                break;
            }
            this.currentDataSize -= lruKey.length;
        }
        const result = this.map.setpop(key, value);
        if (result?.evicted) {
            this.currentDataSize -= result.key.length;
        }
        if (hasKey) {
            this.currentDataSize -= size;
        }
        this.currentDataSize += size;
    }
    get size() {
        return this.map.size;
    }
    get currentDataSizeValue() {
        return this.currentDataSize;
    }
    clear() {
        this.map.clear();
        this.currentDataSize = 0;
    }
}
//# sourceMappingURL=data-limited-lru-map.js.map