import { asAsyncEqualityComparer } from "../equality-comparer/async.js"; import { asEqualityComparer } from "../equality-comparer/sync.js"; import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { MaybeAsyncIterable } from "../types.js"; import { AsyncEqualitySet, EqualitySet } from "./types.js"; export class NativeEqualitySet implements EqualitySet { readonly #set = new Set(); get size() { return this.#set.size; } add(value: T) { const exists = this.contains(value); this.#set.add(value); return !exists; } addAll(values: Iterable) { let result = 0; for (const value of values) { if (this.add(value)) { result++; } } return result; } contains(value: T) { return this.#set.has(value); } remove(value: T) { return this.#set.delete(value); } clear() { this.#set.clear(); } values() { return this.#set.values(); } [Symbol.iterator]() { return this.#set[Symbol.iterator](); } } export class CustomEqualitySet implements EqualitySet { readonly #list: T[] = []; readonly #equater: EqualityComparer; constructor(equater: EqualityComparisonOrComparer) { this.#equater = asEqualityComparer(equater); } get size() { return this.#list.length; } add(value: T) { if (this.contains(value)) { return false; } this.#list.push(value); return true; } addAll(values: Iterable) { let result = 0; for (const value of values) { if (this.add(value)) { result++; } } return result; } contains(value: T) { for (const val of this.#list) { if (this.#equater.equals(value, val)) { return true; } } return false; } remove(value: T) { const length = this.#list.length; for (let i = 0; i < length; i++) { if (this.#equater.equals(value, this.#list[i])) { this.#list.splice(i, 1); return true; } } return false; } clear() { this.#list.length = 0; } values() { return this.#list.values(); } [Symbol.iterator]() { return this.#list[Symbol.iterator](); } } export class NativeAsyncEqualitySet implements AsyncEqualitySet { readonly #set = new Set(); get size() { return this.#set.size; } async add(value: T) { const exists = await this.contains(value); this.#set.add(value); return !exists; } async addAll(values: MaybeAsyncIterable) { let result = 0; for await (const value of values) { if (await this.add(value)) { result++; } } return result; } async contains(value: T) { return this.#set.has(value); } async remove(value: T) { return this.#set.delete(value); } clear() { this.#set.clear(); } values() { return this.#set.values(); } [Symbol.iterator]() { return this.#set[Symbol.iterator](); } } export class CustomAsyncEqualitySet implements AsyncEqualitySet { readonly #list: T[] = []; readonly #equater: AsyncEqualityComparer; constructor(equater: MaybeAsyncEqualityComparisonOrComparer) { this.#equater = asAsyncEqualityComparer(equater); } get size() { return this.#list.length; } async add(value: T) { if (await this.contains(value)) { return false; } this.#list.push(value); return true; } async addAll(values: MaybeAsyncIterable) { let result = 0; for await (const value of values) { if (await this.add(value)) { result++; } } return result; } async contains(value: T) { for (const val of this.#list) { if (await this.#equater.equals(value, val)) { return true; } } return false; } async remove(value: T) { const length = this.#list.length; for (let i = 0; i < length; i++) { if (await this.#equater.equals(value, this.#list[i])) { this.#list.splice(i, 1); return true; } } return false; } clear() { this.#list.length = 0; } values() { return this[Symbol.iterator](); } [Symbol.iterator]() { return this.#list[Symbol.iterator](); } }