add ClassMap data structure

This commit is contained in:
Matthieu Jolimaitre 2024-12-12 18:18:47 +01:00
parent 57e3126702
commit 69494ebd28
2 changed files with 66 additions and 0 deletions

View file

@ -25,3 +25,4 @@ export { Channel } from "./lib/Channel.ts";
export { Range, range } from "./lib/Range.ts";
export { Event } from "./lib/Event.ts";
export { AsyncPool } from "./lib/AsyncPool.ts";
export { ClassMap } from "./lib/ClassMap.ts";

65
src/lib/ClassMap.ts Normal file
View file

@ -0,0 +1,65 @@
import { assert } from "https://deno.land/std@0.224.0/assert/assert.ts";
import { assertInstanceOf } from "https://deno.land/std@0.224.0/assert/assert_instance_of.ts";
export type Prototyped<P = unknown> = { constructor: { prototype: P } };
// deno-lint-ignore no-explicit-any
export type Constructible<I = unknown> = new (...args: any[]) => I;
export class ClassMap<B = unknown> {
private inner;
constructor() {
this.inner = new Map();
}
insert<V extends Prototyped & B>(object: V) {
const prototype = object.constructor.prototype;
if (this.inner.has(prototype)) throw new Error();
this.inner.set(prototype, object);
}
get<I extends B, C extends Constructible<I>>(class_: C) {
const value = this.inner.get(class_.prototype);
if (value === undefined) return null;
assertInstanceOf(value, class_);
return value;
}
has<I extends B, C extends Constructible<I>>(class_: C) {
return this.inner.has(class_.prototype);
}
}
Deno.test("test_classmap", () => {
{
class Truc {}
class Machin {}
class Chose {}
const map = new ClassMap();
const truc = new Truc();
map.insert(truc);
const machin = new Machin();
map.insert(machin);
assert(map.get(Truc) === truc);
assert(map.get(Machin) !== truc);
assert(map.get(Machin) === machin);
assert(map.get(Chose) === null);
}
{
interface Machinable {
machin(): number;
}
// deno-lint-ignore no-unused-vars
class Truc {}
class Machin implements Machinable {
machin = () => 35;
}
const map = new ClassMap<Machinable>();
map.insert(new Machin());
// map.insert(new Truc()); // note : Fails with improper typing.
map.get(Machin);
// map.get(Truc); // note : Fails with improper typing.
}
});