/** * @since 1.0.0 */ import * as Dual from "@effect/data/Function" import * as HashMap from "@effect/data/HashMap" import { type Inspectable, NodeInspectSymbol, toJSON, toString } from "@effect/data/Inspectable" import * as MutableRef from "@effect/data/MutableRef" import * as Option from "@effect/data/Option" import type { Pipeable } from "@effect/data/Pipeable" import { pipeArguments } from "@effect/data/Pipeable" const TypeId: unique symbol = Symbol.for("@effect/data/MutableHashMap") as TypeId /** * @since 1.0.0 * @category symbol */ export type TypeId = typeof TypeId /** * @since 1.0.0 * @category models */ export interface MutableHashMap extends Iterable, Pipeable, Inspectable { readonly [TypeId]: TypeId /** @internal */ readonly backingMap: MutableRef.MutableRef> } const MutableHashMapProto: Omit, "backingMap"> = { [TypeId]: TypeId, [Symbol.iterator](this: MutableHashMap): Iterator { return this.backingMap.current[Symbol.iterator]() }, toString() { return toString(this.toJSON()) }, toJSON() { return { _id: "MutableHashMap", values: Array.from(this).map(toJSON) } }, [NodeInspectSymbol]() { return this.toJSON() }, pipe() { return pipeArguments(this, arguments) } } const fromHashMap = (backingMap: HashMap.HashMap): MutableHashMap => { const map = Object.create(MutableHashMapProto) map.backingMap = MutableRef.make(backingMap) return map } /** * @since 1.0.0 * @category constructors */ export const empty = (): MutableHashMap => fromHashMap(HashMap.empty()) /** * @since 1.0.0 * @category constructors */ export const make: >( ...entries: Entries ) => MutableHashMap< Entries[number] extends readonly [infer K, any] ? K : never, Entries[number] extends readonly [any, infer V] ? V : never > = (...entries) => fromIterable(entries) /** * @since 1.0.0 * @category conversions */ export const fromIterable = (entries: Iterable): MutableHashMap => fromHashMap(HashMap.fromIterable(entries)) /** * @since 1.0.0 * @category elements */ export const get: { (key: K): (self: MutableHashMap) => Option.Option (self: MutableHashMap, key: K): Option.Option } = Dual.dual< (key: K) => (self: MutableHashMap) => Option.Option, (self: MutableHashMap, key: K) => Option.Option >(2, (self: MutableHashMap, key: K) => HashMap.get(self.backingMap.current, key)) /** * @since 1.0.0 * @category elements */ export const has: { (key: K): (self: MutableHashMap) => boolean (self: MutableHashMap, key: K): boolean } = Dual.dual< (key: K) => (self: MutableHashMap) => boolean, (self: MutableHashMap, key: K) => boolean >(2, (self, key) => Option.isSome(get(self, key))) /** * Updates the value of the specified key within the `MutableHashMap` if it exists. * * @since 1.0.0 */ export const modify: { (key: K, f: (v: V) => V): (self: MutableHashMap) => MutableHashMap (self: MutableHashMap, key: K, f: (v: V) => V): MutableHashMap } = Dual.dual< (key: K, f: (v: V) => V) => (self: MutableHashMap) => MutableHashMap, (self: MutableHashMap, key: K, f: (v: V) => V) => MutableHashMap >( 3, (self: MutableHashMap, key: K, f: (v: V) => V) => { MutableRef.update(self.backingMap, HashMap.modify(key, f)) return self } ) /** * Set or remove the specified key in the `MutableHashMap` using the specified * update function. * * @since 1.0.0 */ export const modifyAt: { (key: K, f: (value: Option.Option) => Option.Option): (self: MutableHashMap) => MutableHashMap (self: MutableHashMap, key: K, f: (value: Option.Option) => Option.Option): MutableHashMap } = Dual.dual< ( key: K, f: (value: Option.Option) => Option.Option ) => (self: MutableHashMap) => MutableHashMap, ( self: MutableHashMap, key: K, f: (value: Option.Option) => Option.Option ) => MutableHashMap >(3, (self, key, f) => { const result = f(get(self, key)) if (Option.isSome(result)) { set(self, key, result.value) } else { remove(self, key) } return self }) /** * @since 1.0.0 */ export const remove: { (key: K): (self: MutableHashMap) => MutableHashMap (self: MutableHashMap, key: K): MutableHashMap } = Dual.dual< (key: K) => (self: MutableHashMap) => MutableHashMap, (self: MutableHashMap, key: K) => MutableHashMap >(2, (self: MutableHashMap, key: K) => { MutableRef.update(self.backingMap, HashMap.remove(key)) return self }) /** * @since 1.0.0 */ export const set: { (key: K, value: V): (self: MutableHashMap) => MutableHashMap (self: MutableHashMap, key: K, value: V): MutableHashMap } = Dual.dual< (key: K, value: V) => (self: MutableHashMap) => MutableHashMap, (self: MutableHashMap, key: K, value: V) => MutableHashMap >(3, (self: MutableHashMap, key: K, value: V) => { MutableRef.update(self.backingMap, HashMap.set(key, value)) return self }) /** * @since 1.0.0 * @category elements */ export const size = (self: MutableHashMap): number => HashMap.size(MutableRef.get(self.backingMap))