rc-js-util
Version:
A collection of TS and C++ utilities to help writing performant and correct applications, achieved through strict typing and (removable) invariant checking.
123 lines (104 loc) • 2.93 kB
text/typescript
import { ISetLike } from "../typescript/i-set-like.js";
/**
* @public
* Provides a unique array with O(1) add & remove, with dirty checking on `getArray`.
*/
export interface IDirtyCheckedUniqueCollection<TItem> extends ISetLike<TItem>
{
readonly isDirty: boolean;
/**
* @returns true if the item was added.
*/
reportingAdd(item: TItem): boolean;
getArray(): readonly TItem[];
getSet(): ReadonlySet<TItem>;
}
/**
* @public
* {@inheritDoc IDirtyCheckedUniqueCollection}
*/
export class DirtyCheckedUniqueCollection<TItem>
implements IDirtyCheckedUniqueCollection<TItem>,
ISetLike<TItem>
{
public get size(): number
{
return this.itemsSet.size;
}
public isDirty = true;
public static mapInitializeAdd<TKey, TValue>(map: Map<TKey, IDirtyCheckedUniqueCollection<TValue>>, key: TKey, value: TValue): boolean;
public static mapInitializeAdd<TKey extends object, TValue>(map: WeakMap<TKey, IDirtyCheckedUniqueCollection<TValue>>, key: TKey, value: TValue): boolean;
public static mapInitializeAdd<TKey extends object, TValue>
(
map: Map<TKey, IDirtyCheckedUniqueCollection<TValue>> | WeakMap<TKey, IDirtyCheckedUniqueCollection<TValue>>,
key: TKey,
value: TValue,
)
: boolean
{
const collection = map.get(key);
if (collection == null)
{
const collection = new DirtyCheckedUniqueCollection<TValue>();
collection.add(value);
map.set(key, collection);
return true;
}
else
{
return collection.reportingAdd(value);
}
}
public constructor
(
itemsToCopy?: readonly TItem[] | ReadonlySet<TItem>,
)
{
this.itemsSet = new Set(itemsToCopy);
}
public add(item: TItem): void
{
this.itemsSet.add(item);
this.isDirty = true;
}
public reportingAdd(item: TItem): boolean
{
if (this.itemsSet.has(item))
{
return false;
}
this.itemsSet.add(item);
this.isDirty = true;
return true;
}
public delete(item: TItem): boolean
{
const deletedItem = this.itemsSet.delete(item);
this.isDirty ||= deletedItem;
return deletedItem;
}
public has(item: TItem): boolean
{
return this.itemsSet.has(item);
}
public clear(): void
{
this.isDirty ||= this.itemsSet.size > 0;
this.itemsSet.clear();
}
public getArray(): readonly TItem[]
{
if (this.isDirty)
{
this.itemsArray = Array.from(this.itemsSet);
this.isDirty = false;
}
return this.itemsArray;
}
public getSet(): ReadonlySet<TItem>
{
return this.itemsSet;
}
private readonly itemsSet: Set<TItem>;
private itemsArray: TItem[] = [];
}