1
0

initial commit

This commit is contained in:
2024-05-04 01:19:44 +02:00
commit a172e6a50f
16 changed files with 6514 additions and 0 deletions

219
src/equality-map.ts Normal file
View File

@@ -0,0 +1,219 @@
import { Equater } from "./sync.js";
import { MaybeAsyncEquater } from "./async.js";
import { asAsyncGenerator } from "./utils.js";
export interface EqualityMap<K, V> extends Iterable<[K, V]> {
get(key: K): V | undefined;
set(key: K, value: V): V | undefined;
contains(key: K): boolean;
remove(key: K): V | undefined;
clear(): void;
}
class NativeEqualityMap<K, V> implements EqualityMap<K, V> {
readonly #map = new Map<K, V>();
get(key: K) {
return this.#map.get(key);
}
set(key: K, value: V) {
const existing = this.get(key);
this.#map.set(key, value);
return existing;
}
contains(key: K) {
return this.#map.has(key);
}
remove(key: K) {
const existing = this.get(key);
this.#map.delete(key);
return existing;
}
clear() {
this.#map.clear();
}
[Symbol.iterator]() {
return this.#map[Symbol.iterator]();
}
}
class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
readonly #keyComparer: Equater<K>;
readonly #list = new Array<[K, V]>();
constructor(keyComparer: Equater<K>) {
this.#keyComparer = keyComparer;
}
get(key: K) {
for (const entry of this.#list) {
if (this.#keyComparer(key, entry[0])) {
return entry[1];
}
}
return undefined;
}
set(key: K, value: V) {
for (const entry of this.#list) {
if (this.#keyComparer(key, entry[0])) {
const previous = entry[1];
entry[1] = value;
return previous;
}
}
this.#list.push([key, value]);
return undefined;
}
contains(key: K) {
for (const entry of this.#list) {
if (this.#keyComparer(key, entry[0])) {
return true;
}
}
return false;
}
remove(key: K) {
const length = this.#list.length;
for (let i = 0; i < length; i++) {
if (this.#keyComparer(key, this.#list[i][0])) {
const removed = this.#list.splice(i, 1);
return removed[0][1];
}
}
return undefined;
}
clear() {
this.#list.length = 0;
}
[Symbol.iterator]() {
return this.#list[Symbol.iterator]();
}
}
export function createEqualityMap<K, V>(keyComparer?: Equater<K>): EqualityMap<K, V> {
return keyComparer ? new CustomEqualityMap<K, V>(keyComparer) : new NativeEqualityMap<K, V>();
}
export interface AsyncEqualityMap<K, V> extends AsyncIterable<[K, V]> {
get(key: K): Promise<V | undefined>;
set(key: K, value: V): Promise<V | undefined>;
contains(key: K): Promise<boolean>;
remove(key: K): Promise<V | undefined>;
clear(): Promise<void>;
}
class NativeAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
readonly #map = new Map<K, V>();
async get(key: K) {
return this.#map.get(key);
}
async set(key: K, value: V) {
const existing = await this.get(key);
this.#map.set(key, value);
return existing;
}
async contains(key: K) {
return this.#map.has(key);
}
async remove(key: K) {
const existing = await this.get(key);
this.#map.delete(key);
return existing;
}
async clear() {
this.#map.clear();
}
[Symbol.asyncIterator]() {
return asAsyncGenerator(this.#map[Symbol.iterator]());
}
}
class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
readonly #keyComparer: MaybeAsyncEquater<K>;
readonly #list = new Array<[K, V]>();
constructor(keyComparer: MaybeAsyncEquater<K>) {
this.#keyComparer = keyComparer;
}
async get(key: K) {
for (const entry of this.#list) {
if (await this.#keyComparer(key, entry[0])) {
return entry[1];
}
}
return undefined;
}
async set(key: K, value: V) {
for (const entry of this.#list) {
if (await this.#keyComparer(key, entry[0])) {
const previous = entry[1];
entry[1] = value;
return previous;
}
}
this.#list.push([key, value]);
return undefined;
}
async contains(key: K) {
for (const entry of this.#list) {
if (await this.#keyComparer(key, entry[0])) {
return true;
}
}
return false;
}
async remove(key: K) {
const length = this.#list.length;
for (let i = 0; i < length; i++) {
if (await this.#keyComparer(key, this.#list[i][0])) {
const removed = this.#list.splice(i, 1);
return removed[0][1];
}
}
return undefined;
}
async clear() {
this.#list.length = 0;
}
[Symbol.asyncIterator]() {
return asAsyncGenerator(this.#list[Symbol.iterator]());
}
}
export function createAsyncEqualityMap<K, V>(keyComparer?: MaybeAsyncEquater<K>): AsyncEqualityMap<K, V> {
return keyComparer ? new CustomAsyncEqualityMap<K, V>(keyComparer) : new NativeAsyncEqualityMap<K, V>();
}