UNPKG

@btc-vision/transaction

Version:

OPNet transaction library allows you to create and sign transactions for the OPNet network.

127 lines (102 loc) 3.39 kB
import { FastMap, type PropertyExtendedKey } from './FastMap.js'; export class DeterministicMap<K extends PropertyExtendedKey, V> implements Disposable { private map: FastMap<K, V>; #keys: K[]; constructor(private compareFn: (a: K, b: K) => number) { this.map = new FastMap<K, V>(); this.#keys = []; } public get size(): number { return this.map.size; } public static fromMap<K extends PropertyExtendedKey, V>( map: FastMap<K, V>, compareFn: (a: K, b: K) => number, ): DeterministicMap<K, V> { const deterministicMap = new DeterministicMap<K, V>(compareFn); for (const [key, value] of map) { deterministicMap.set(key, value); } return deterministicMap; } public set(key: K, value: V): void { if (!this.map.has(key)) { // Binary search for insertion position let left = 0, right = this.#keys.length; while (left < right) { const mid = Math.floor((left + right) / 2); if (this.compareFn(this.#keys[mid] as K, key) < 0) { left = mid + 1; } else { right = mid; } } this.#keys.splice(left, 0, key); } this.map.set(key, value); } public get(key: K): V | undefined { return this.map.get(key); } public *entries(): IterableIterator<[K, V]> { for (const key of this.#keys) { yield [key, this.map.get(key) as V]; } } public *keys(): IterableIterator<K> { yield* this.#keys; } public *values(): IterableIterator<V> { for (const key of this.#keys) { const value = this.map.get(key); if (value === undefined && !this.map.has(key)) { throw new Error('Value not found'); } yield value as V; } } public has(key: K): boolean { return this.map.has(key); } public delete(key: K): boolean { if (this.map.has(key)) { this.map.delete(key); // Binary search to find the key's index let left = 0, right = this.#keys.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); const cmp = this.compareFn(this.#keys[mid] as K, key); if (cmp === 0) { // Found it, remove at this index this.#keys.splice(mid, 1); return true; } else if (cmp < 0) { left = mid + 1; } else { right = mid - 1; } } } return false; } public clear(): void { this.map.clear(); this.#keys = []; } public [Symbol.dispose](): void { this.clear(); } public forEach(callback: (value: V, key: K, map: DeterministicMap<K, V>) => void): void { for (const key of this.#keys) { const value = this.map.get(key) as V; callback(value, key, this); } } *[Symbol.iterator](): IterableIterator<[K, V]> { for (const key of this.#keys) { yield [key, this.map.get(key) as V]; } } }