UNPKG

scontainers

Version:

A container/collection/iterator library for JavaScript, comfortable to use, performant and versatile.

145 lines (107 loc) 3.44 kB
"use strict"; function _implSymbol(target, sym, value) { Object.defineProperty(target, sym, { value, configurable: true }); return target[sym]; } function _getSymbol(targetSymName, ...traitSets) { let symbol; traitSets.forEach(traitSet => { const sym = traitSet[targetSymName]; if (typeof sym === 'symbol') { if (!!symbol && symbol !== sym) { throw new Error(`Symbol ${targetSymName} offered by multiple trait sets.`); } symbol = sym; } }); if (!symbol) { throw new Error(`No trait set is providing symbol ${targetSymName}.`); } return symbol; } function _testTraitSet(traitSet) { if (!traitSet || typeof traitSet === 'boolean' || typeof traitSet === 'number' || typeof traitSet === 'string') { throw new Error(`${traitSet} cannot be used as a trait set.`); } } const { traits, id, KVN } = require('../utils.js'); _testTraitSet(traits.utils); _testTraitSet(traits.scontainers); _testTraitSet(traits.semantics); const _hasKey = _getSymbol("hasKey", traits.utils, traits.scontainers, traits.semantics); const _describeScontainer = _getSymbol("describeScontainer", traits.utils, traits.scontainers, traits.semantics); const _implCoreTraits = _getSymbol("implCoreTraits", traits.utils, traits.scontainers, traits.semantics); const _nthKVN = _getSymbol("nthKVN", traits.utils, traits.scontainers, traits.semantics); const _getKVN = _getSymbol("getKVN", traits.utils, traits.scontainers, traits.semantics); const _nToKey = _getSymbol("nToKey", traits.utils, traits.scontainers, traits.semantics); const _get = _getSymbol("get", traits.utils, traits.scontainers, traits.semantics); const _set = _getSymbol("set", traits.utils, traits.scontainers, traits.semantics); const _len = _getSymbol("len", traits.utils, traits.scontainers, traits.semantics); module.exports = function (ParentCollection) { if (!ParentCollection.prototype[_hasKey]) { return; } return function () { class Cache { static get name() { return `${ParentCollection.name}::Cache`; } constructor(coll, CacheType = Map) { this.wrapped = coll; this.cache = new CacheType(); } toString() { return `${this.wrapped}.cache(${this.cache.constructor.name})`; } } const parentProto = ParentCollection.prototype; Cache[_describeScontainer]({ InnerCollection: ParentCollection, innerCollectionKey: id`wrapped`, argKeys: [id`mapFn`] }); Cache[_implCoreTraits]({ stage(kvn) { return kvn; }, indexToParentIndex(index) { return index; }, nthKVN() { if (parentProto[_nthKVN]) { return function (n) { return this[_getKVN](this[_nToKey](n)); }; } }, getKVN() { if (parentProto[_getKVN]) { return function (key) { if (this.cache[_hasKey](key)) { const kvn = this.cache[_get](key); return new KVN(kvn.key, kvn.value, kvn.n); } const kvn = this.wrapped[_getKVN](key); this.cache[_set](key, kvn); return new KVN(kvn.key, kvn.value, kvn.n); }; } }, len() { if (parentProto[_len]) { return function () { return this.wrapped[_len](); }; } } }); return Cache; }; };