UNPKG

veffect

Version:

powerful TypeScript validation library built on the robust foundation of Effect combining exceptional type safety, high performance, and developer experience. Taking inspiration from Effect's functional principles, VEffect delivers a balanced approach tha

201 lines (186 loc) 4.55 kB
import * as Option from "../../Option.js" import * as ReadonlyArray from "../../ReadonlyArray.js" import type * as RBT from "../../RedBlackTree.js" import type { RedBlackTreeImpl } from "../redBlackTree.js" import type * as Node from "./node.js" /** @internal */ export const Direction = { Forward: 0 as RBT.RedBlackTree.Direction, Backward: 1 << 0 as RBT.RedBlackTree.Direction } as const /** @internal */ export class RedBlackTreeIterator<in out K, out V> implements Iterator<[K, V]> { private count = 0 constructor( readonly self: RBT.RedBlackTree<K, V>, readonly stack: Array<Node.Node<K, V>>, readonly direction: RBT.RedBlackTree.Direction ) {} /** * Clones the iterator */ clone(): RedBlackTreeIterator<K, V> { return new RedBlackTreeIterator(this.self, this.stack.slice(), this.direction) } /** * Reverse the traversal direction */ reversed(): RedBlackTreeIterator<K, V> { return new RedBlackTreeIterator( this.self, this.stack.slice(), this.direction === Direction.Forward ? Direction.Backward : Direction.Forward ) } /** * Iterator next */ next(): IteratorResult<[K, V], number> { const entry = this.entry this.count++ if (this.direction === Direction.Forward) { this.moveNext() } else { this.movePrev() } switch (entry._tag) { case "None": { return { done: true, value: this.count } } case "Some": { return { done: false, value: entry.value } } } } /** * Returns the key */ get key(): Option.Option<K> { if (this.stack.length > 0) { return Option.some(this.stack[this.stack.length - 1]!.key) } return Option.none() } /** * Returns the value */ get value(): Option.Option<V> { if (this.stack.length > 0) { return Option.some(this.stack[this.stack.length - 1]!.value) } return Option.none() } /** * Returns the key */ get entry(): Option.Option<[K, V]> { return Option.map(ReadonlyArray.last(this.stack), (node) => [node.key, node.value]) } /** * Returns the position of this iterator in the sorted list */ get index(): number { let idx = 0 const stack = this.stack if (stack.length === 0) { const r = (this.self as RedBlackTreeImpl<K, V>)._root if (r != null) { return r.count } return 0 } else if (stack[stack.length - 1]!.left != null) { idx = stack[stack.length - 1]!.left!.count } for (let s = stack.length - 2; s >= 0; --s) { if (stack[s + 1] === stack[s]!.right) { ;++idx if (stack[s]!.left != null) { idx += stack[s]!.left!.count } } } return idx } /** * Advances iterator to next element in list */ moveNext() { const stack = this.stack if (stack.length === 0) { return } let n: Node.Node<K, V> | undefined = stack[stack.length - 1]! if (n.right != null) { n = n.right while (n != null) { stack.push(n) n = n.left } } else { stack.pop() while (stack.length > 0 && stack[stack.length - 1]!.right === n) { n = stack[stack.length - 1] stack.pop() } } } /** * Checks if there is a next element */ get hasNext() { const stack = this.stack if (stack.length === 0) { return false } if (stack[stack.length - 1]!.right != null) { return true } for (let s = stack.length - 1; s > 0; --s) { if (stack[s - 1]!.left === stack[s]) { return true } } return false } /** * Advances iterator to previous element in list */ movePrev() { const stack = this.stack if (stack.length === 0) { return } let n: Node.Node<K, V> | undefined = stack[stack.length - 1] if (n != null && n.left != null) { n = n.left while (n != null) { stack.push(n) n = n.right } } else { stack.pop() while (stack.length > 0 && stack[stack.length - 1]!.left === n) { n = stack[stack.length - 1] stack.pop() } } } /** * Checks if there is a previous element */ get hasPrev() { const stack = this.stack if (stack.length === 0) { return false } if (stack[stack.length - 1]!.left != null) { return true } for (let s = stack.length - 1; s > 0; --s) { if (stack[s - 1]!.right === stack[s]) { return true } } return false } }