diff --git a/src/ImmutableSet.ts b/src/ImmutableSet.ts new file mode 100644 index 0000000..750c3f8 --- /dev/null +++ b/src/ImmutableSet.ts @@ -0,0 +1,78 @@ +export class ImmutableSet implements ReadonlySet { + #set: Set; + + constructor(values?: Iterable | null) { + this.#set = values instanceof Set ? values : new Set(values); + } + + [Symbol.iterator](): SetIterator { + return this.#set[Symbol.iterator](); + } + + get size(): number { + return this.#set.size; + } + + has(value: T): boolean { + return this.#set.has(value); + } + + keys(): SetIterator { + return this.#set.keys(); + } + + values(): SetIterator { + return this.#set.values(); + } + + entries(): SetIterator<[T, T]> { + return this.#set.entries(); + } + + forEach( + callbackfn: (value: T, value2: T, set: Set) => void, + thisArg?: TSelf, + ): void { + this.#set.forEach(callbackfn, thisArg); + } + + union(other: ReadonlySetLike): Set { + return this.#set.union(other); + } + + intersection(other: ReadonlySet): Set { + return this.#set.intersection(other); + } + + difference(other: ReadonlySet): Set { + return this.#set.difference(other); + } + + symmetricDifference(other: ReadonlySet): Set { + return this.#set.symmetricDifference(other); + } + + isSubsetOf(other: ReadonlySet): boolean { + return this.#set.isSubsetOf(other); + } + + isSupersetOf(other: ReadonlySet): boolean { + return this.#set.isSupersetOf(other); + } + + isDisjointFrom(other: ReadonlySet): boolean { + return this.#set.isDisjointFrom(other); + } + + get [Symbol.toStringTag](): string { + return "ImmutableSet"; + } + + [Symbol.for("nodejs.util.inspect.custom")](): string { + return `ImmutableSet(${this.size}) { ${ + [...this.#set] + .map((value) => Deno.inspect(value, { colors: !Deno.noColor })) + .join(", ") + } }`; + } +} diff --git a/src/MultiDict.ts b/src/MultiDict.ts index ec1fc45..aa72fd5 100644 --- a/src/MultiDict.ts +++ b/src/MultiDict.ts @@ -1,3 +1,5 @@ +import { ImmutableSet } from "./ImmutableSet.ts"; + /** * A multi-key multi-value map implementation. * @@ -82,8 +84,12 @@ export class MultiDict */ get(key: K): ReadonlySet | undefined; get(key: V): ReadonlySet | undefined; - get(key: K | V) { - return this.#map.get(key) as ReadonlySet | undefined; + get(key: K | V): ReadonlySet | undefined { + const set = this.#map.get(key); + + if (set) { + return new ImmutableSet(set); + } } /** @@ -111,10 +117,8 @@ export class MultiDict } #set(key: K | V, value: K | V) { - const set = this.#map.get(key) ?? new Set(); - set.add(value); - - this.#map.set(key, set); + this.#map.get(key)?.add(value) ?? + this.#map.set(key, new Set([value])); return this; }