UNPKG

minisearch

Version:

Tiny but powerful full-text search engine for browser and Node

92 lines (73 loc) 2.01 kB
import { RadixTree, Entry } from './types' /** @ignore */ const ENTRIES = 'ENTRIES' /** @ignore */ const KEYS = 'KEYS' /** @ignore */ const VALUES = 'VALUES' /** @ignore */ const LEAF = '' type IteratorType = 'ENTRIES' | 'KEYS' | 'VALUES' type IteratorPath<T> = { node: RadixTree<T>, keys: string[] }[] export type IterableSet<T> = { _tree: RadixTree<T>, _prefix: string } /** * @private */ class TreeIterator<T, V> implements Iterator<V> { set: IterableSet<T> _type: IteratorType _path: IteratorPath<T> constructor (set: IterableSet<T>, type: IteratorType) { const node = set._tree const keys = Object.keys(node) this.set = set this._type = type this._path = keys.length > 0 ? [{ node, keys }] : [] } next (): IteratorResult<V> { const value = this.dive() this.backtrack() return value } dive (): IteratorResult<V> { if (this._path.length === 0) { return { done: true, value: undefined } } const { node, keys } = last(this._path)! if (last(keys) === LEAF) { return { done: false, value: this.result() as V } } this._path.push({ node: node[last(keys)!] as RadixTree<T>, keys: Object.keys(node[last(keys)!]) }) return this.dive() } backtrack (): void { if (this._path.length === 0) { return } last(this._path)!.keys.pop() if (last(this._path)!.keys.length > 0) { return } this._path.pop() this.backtrack() } key (): string { return this.set._prefix + this._path .map(({ keys }) => last(keys)) .filter(key => key !== LEAF) .join('') } value (): T { return last(this._path)!.node[LEAF] as T } result (): unknown { if (this._type === VALUES) { return this.value() } if (this._type === KEYS) { return this.key() } return [this.key(), this.value()] as Entry<T> } [Symbol.iterator] () { return this } } const last = <T>(array: T[]): T | undefined => { return array[array.length - 1] } export { TreeIterator, ENTRIES, KEYS, VALUES, LEAF }