import { Compare, Relation, freeze, nat } from "../index.js"; import { RedBlackSet } from "./RedBlackSet.js" export interface RedBlackMap extends Iterable<[K, V]> { keyValues : RedBlackSet<[K, V]> size : nat has(key : K) : boolean get(elem : K) : V | undefined set(key : K, value : V) : RedBlackMap setMultiple(keyValuePairs : Iterable<[K, V]>) : RedBlackMap delete(key : K) : RedBlackMap deleteMultiple(keys : Iterable) : RedBlackMap minimum() : [K, V] | undefined maximum() : [K, V] | undefined filter(predicate : (key : K, value : V) => boolean) : RedBlackMap } function promote(key : K) : [K, V] { return [key, undefined as V]; } function* promoteMultiple(keys : Iterable) : Generator<[K, V], void, void> { for (const key of keys) yield promote(key); } export function promoteCompare(key : Compare) : Compare<[K, any]> { const order : Compare<[K, any]> = { compare: function (x: [K, any], y: [K, any]): Relation { return key.compare(x[0], y[0]); }, }; return order; } class RedBlackMapImpl implements Iterable<[K, V]> { keyValues : RedBlackSet<[K, V]> constructor(keyValues : RedBlackSet<[K, V]>) { this.keyValues = keyValues; freeze(this); } get size() : nat { return this.keyValues.size; } has(key : K) : boolean { return this.keyValues.has(promote(key)); } get(elem : K) : V | undefined { const kv = this.keyValues.findEqual(promote(elem)); if (kv === undefined) return undefined; return kv[1]; } set(key : K, value : V) : RedBlackMapImpl { return new RedBlackMapImpl(this.keyValues.insert([key, value])); } setMultiple(keyValuePairs : Iterable<[K, V]>) : RedBlackMapImpl { return new RedBlackMapImpl(this.keyValues.insertMultiple(keyValuePairs)); } delete(key : K) : RedBlackMapImpl { return new RedBlackMapImpl(this.keyValues.delete(promote(key))); } deleteMultiple(keys : Iterable) : RedBlackMapImpl { return new RedBlackMapImpl(this.keyValues.deleteMultiple(promoteMultiple(keys))); } minimum() : [K, V] | undefined { return this.keyValues.minimum(); } maximum() : [K, V] | undefined { return this.keyValues.maximum(); } [Symbol.iterator]() { return this.keyValues[Symbol.iterator](); } filter(predicate : (key : K, value : V) => boolean) : RedBlackMapImpl { return new RedBlackMapImpl(this.keyValues.filter(kv => predicate(kv[0], kv[1]))); } } freeze(RedBlackMapImpl); export function RedBlackMap(order : Compare, keyValuePairs? : Iterable<[K, V]>) : RedBlackMap { return new RedBlackMapImpl(RedBlackSet(promoteCompare(order), keyValuePairs)); } freeze(RedBlackMap);