@matter/general 0.14.0 → 0.14.1-alpha.0-20250605-9fc134af0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@
3
3
  * Copyright 2022-2025 Matter.js Authors
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { ImplementationError } from "#MatterError.js";
6
7
  import { Observable } from "./Observable.js";
7
8
  /**
8
9
  * A read-only set.
@@ -31,9 +32,19 @@ export interface ObservableSet<T> {
31
32
  }
32
33
  /**
33
34
  * An interface for index set lookup.
35
+ *
36
+ * Note that this interface only supports a single item for each key. If multiple items associate with a key only the
37
+ * first is returned.
34
38
  */
35
39
  export interface IndexedSet<T> {
40
+ /**
41
+ * Retrieve an item with the named {@link field} set to {@link value}.
42
+ */
36
43
  get<F extends keyof T>(field: F, value: T[F]): T | undefined;
44
+ /**
45
+ * Obtain a {@link Map} of values in {@link field} to the associated item in the set.
46
+ */
47
+ mapOf<F extends keyof T>(field: F): Map<T[F], T>;
37
48
  }
38
49
  /**
39
50
  * A generic set implementation supporting all interfaces in this module.
@@ -51,10 +62,50 @@ export declare class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSe
51
62
  has(item: T): boolean;
52
63
  add(item: AddT): void;
53
64
  get<F extends keyof T>(field: F, value: T[F]): T | undefined;
65
+ /**
66
+ * Obtain key/value map using specific field as key.
67
+ *
68
+ * Note we use {@link This} to constrain usage to sets where {@link T} === {@link AddT} as required by {@link Map}.
69
+ */
70
+ mapOf<This extends BasicSet<T, T>, F extends keyof T>(this: This, field: F): Map<T[F], T>;
54
71
  delete(item: T): boolean;
55
72
  clear(): void;
56
73
  get added(): Observable<[T], void>;
57
74
  get deleted(): Observable<[T], void>;
58
75
  protected create(definition: AddT): T;
59
76
  }
77
+ /**
78
+ * A {@link Map} backed by an {@link IndexedSet}.
79
+ *
80
+ * This supports the common case where sets must be looked up by key. Implementations like {@link BasicSet} offer
81
+ * efficient lookup by key using {@link IndexedSet#get}, but usage like a {@link Map} is still cumbersome. This class
82
+ * works as an adapter to make key/value access patterns more natural.
83
+ */
84
+ export declare class MapOfIndexedSet<T, S extends ImmutableSet<T> & MutableSet<T> & IndexedSet<T>, K extends keyof T> implements Map<T[K], T> {
85
+ #private;
86
+ /**
87
+ * Create a new map.
88
+ *
89
+ * @param set the backing data
90
+ * @param key a property of {@link T} used as the key
91
+ * @param index optional index that optimizes lookup by bypassing {@link IndexedSet#get}
92
+ */
93
+ constructor(set: S, key: K, index?: Map<T[K], T>);
94
+ clear(): void;
95
+ delete(key: T[K]): boolean;
96
+ forEach(callbackfn: (value: T, key: T[K], map: Map<T[K], T>) => void, thisArg?: any): void;
97
+ get(key: T[K]): T | undefined;
98
+ has(key: T[K]): boolean;
99
+ set(key: T[K], value: T): this;
100
+ get size(): number;
101
+ entries(): MapIterator<[T[K], T]>;
102
+ keys(): MapIterator<T[K]>;
103
+ values(): MapIterator<T>;
104
+ [Symbol.iterator](): MapIterator<[T[K], T]>;
105
+ [Symbol.toStringTag]: string;
106
+ }
107
+ export declare namespace MapOfIndexedSet {
108
+ class KeyValueMismatchError extends ImplementationError {
109
+ }
110
+ }
60
111
  //# sourceMappingURL=Set.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Set.d.ts","sourceRoot":"","sources":["../../../src/util/Set.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IACnB,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;CAC5D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC;IACnC,GAAG,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC;IAC/B,KAAK,IAAI,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC5B,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;CAChE;AAED;;;;GAIG;AACH,qBAAa,QAAQ,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;;gBAQnG,GAAG,YAAY,EAAE,IAAI,EAAE;IAMnC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAIjB,IAAI,IAAI,WAEP;IAED,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;IAI7B,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS;IAQhD,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS;IAUlD,GAAG,CAAC,IAAI,EAAE,CAAC;IAIX,GAAG,CAAC,IAAI,EAAE,IAAI;IA4Bd,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAmB5C,MAAM,CAAC,IAAI,EAAE,CAAC;IAwBd,KAAK;IAIL,IAAI,KAAK,0BAKR;IAED,IAAI,OAAO,0BAKV;IAED,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GACG,CAAC;CAExC"}
1
+ {"version":3,"file":"Set.d.ts","sourceRoot":"","sources":["../../../src/util/Set.ts"],"names":[],"mappings":"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"}
@@ -18,9 +18,11 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var Set_exports = {};
20
20
  __export(Set_exports, {
21
- BasicSet: () => BasicSet
21
+ BasicSet: () => BasicSet,
22
+ MapOfIndexedSet: () => MapOfIndexedSet
22
23
  });
23
24
  module.exports = __toCommonJS(Set_exports);
25
+ var import_MatterError = require("#MatterError.js");
24
26
  var import_Observable = require("./Observable.js");
25
27
  /**
26
28
  * @license
@@ -32,6 +34,7 @@ class BasicSet {
32
34
  #added;
33
35
  #deleted;
34
36
  #indices;
37
+ #maps;
35
38
  constructor(...initialItems) {
36
39
  for (const item of initialItems) {
37
40
  this.add(item);
@@ -87,6 +90,9 @@ class BasicSet {
87
90
  this.#added?.emit(created);
88
91
  }
89
92
  get(field, value) {
93
+ return this.#indexOf(field).get(value);
94
+ }
95
+ #indexOf(field) {
90
96
  if (!this.#indices) {
91
97
  this.#indices = {};
92
98
  }
@@ -94,15 +100,31 @@ class BasicSet {
94
100
  if (index === void 0) {
95
101
  index = /* @__PURE__ */ new Map();
96
102
  for (const item of this) {
97
- const value2 = item[field];
98
- if (value2 === void 0 || index.has(value2)) {
103
+ const value = item[field];
104
+ if (value === void 0 || index.has(value)) {
99
105
  continue;
100
106
  }
101
- index.set(value2, item);
107
+ index.set(value, item);
102
108
  }
103
109
  this.#indices[field] = index;
104
110
  }
105
- return index?.get(value);
111
+ return index;
112
+ }
113
+ /**
114
+ * Obtain key/value map using specific field as key.
115
+ *
116
+ * Note we use {@link This} to constrain usage to sets where {@link T} === {@link AddT} as required by {@link Map}.
117
+ */
118
+ mapOf(field) {
119
+ if (!this.#maps) {
120
+ this.#maps = {};
121
+ }
122
+ let map = this.#maps[field];
123
+ if (map === void 0) {
124
+ map = new MapOfIndexedSet(this, field, this.#indexOf(field));
125
+ this.#maps[field] = map;
126
+ }
127
+ return map;
106
128
  }
107
129
  delete(item) {
108
130
  if (!this.#entries.delete(item)) {
@@ -142,4 +164,99 @@ class BasicSet {
142
164
  return definition;
143
165
  }
144
166
  }
167
+ class MapOfIndexedSet {
168
+ #set;
169
+ #key;
170
+ // This is an optimization for lookup
171
+ #index;
172
+ /**
173
+ * Create a new map.
174
+ *
175
+ * @param set the backing data
176
+ * @param key a property of {@link T} used as the key
177
+ * @param index optional index that optimizes lookup by bypassing {@link IndexedSet#get}
178
+ */
179
+ constructor(set, key, index) {
180
+ this.#set = set;
181
+ this.#key = key;
182
+ this.#index = index;
183
+ }
184
+ clear() {
185
+ this.#set.clear();
186
+ }
187
+ delete(key) {
188
+ const item = this.get(key);
189
+ if (item) {
190
+ return this.#set.delete(item);
191
+ }
192
+ return false;
193
+ }
194
+ forEach(callbackfn, thisArg) {
195
+ if (thisArg) {
196
+ callbackfn = callbackfn.bind(thisArg);
197
+ }
198
+ for (const [k, v] of this) {
199
+ callbackfn(v, k, this);
200
+ }
201
+ }
202
+ get(key) {
203
+ if (this.#index) {
204
+ return this.#index.get(key);
205
+ }
206
+ return this.#set.get(this.#key, key);
207
+ }
208
+ has(key) {
209
+ return this.#index ? this.#index.has(key) : this.#set.get(this.#key, key) !== void 0;
210
+ }
211
+ set(key, value) {
212
+ if (value[this.#key] !== key) {
213
+ throw new MapOfIndexedSet.KeyValueMismatchError(
214
+ `Cannot set key "${key}" because value property ${String(this.#key)} is "${value[this.#key]}"`
215
+ );
216
+ }
217
+ if (this.has(key)) {
218
+ if (this.get(key) === value) {
219
+ return this;
220
+ }
221
+ this.#set.delete(this.#index ? this.#index.get(key) : this.#set.get(this.#key, key));
222
+ }
223
+ this.#set.add(value);
224
+ return this;
225
+ }
226
+ get size() {
227
+ return this.#set.size;
228
+ }
229
+ entries() {
230
+ return this[Symbol.iterator]();
231
+ }
232
+ keys() {
233
+ if (this.#index) {
234
+ return this.#index.keys();
235
+ }
236
+ const keys = [...this.#set].map((item) => item[this.#key]).filter((key) => key !== void 0);
237
+ return keys[Symbol.iterator]();
238
+ }
239
+ values() {
240
+ if (this.#index) {
241
+ return this.#index.values();
242
+ }
243
+ const values = [...this.#set].map((item) => item);
244
+ return values[Symbol.iterator]();
245
+ }
246
+ *[Symbol.iterator]() {
247
+ for (const item of this.#set) {
248
+ const k = item[this.#key];
249
+ if (k === void 0) {
250
+ continue;
251
+ }
252
+ yield [k, item];
253
+ }
254
+ }
255
+ [Symbol.toStringTag] = "Map";
256
+ }
257
+ ((MapOfIndexedSet2) => {
258
+ class KeyValueMismatchError extends import_MatterError.ImplementationError {
259
+ }
260
+ MapOfIndexedSet2.KeyValueMismatchError = KeyValueMismatchError;
261
+ })(MapOfIndexedSet || (MapOfIndexedSet = {}));
145
262
  //# sourceMappingURL=Set.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/util/Set.ts"],
4
- "mappings": "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",
5
- "names": ["value"]
4
+ "mappings": "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",
5
+ "names": ["MapOfIndexedSet"]
6
6
  }
@@ -3,6 +3,7 @@
3
3
  * Copyright 2022-2025 Matter.js Authors
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { ImplementationError } from "#MatterError.js";
6
7
  import { Observable } from "./Observable.js";
7
8
  /**
8
9
  * A read-only set.
@@ -31,9 +32,19 @@ export interface ObservableSet<T> {
31
32
  }
32
33
  /**
33
34
  * An interface for index set lookup.
35
+ *
36
+ * Note that this interface only supports a single item for each key. If multiple items associate with a key only the
37
+ * first is returned.
34
38
  */
35
39
  export interface IndexedSet<T> {
40
+ /**
41
+ * Retrieve an item with the named {@link field} set to {@link value}.
42
+ */
36
43
  get<F extends keyof T>(field: F, value: T[F]): T | undefined;
44
+ /**
45
+ * Obtain a {@link Map} of values in {@link field} to the associated item in the set.
46
+ */
47
+ mapOf<F extends keyof T>(field: F): Map<T[F], T>;
37
48
  }
38
49
  /**
39
50
  * A generic set implementation supporting all interfaces in this module.
@@ -51,10 +62,50 @@ export declare class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSe
51
62
  has(item: T): boolean;
52
63
  add(item: AddT): void;
53
64
  get<F extends keyof T>(field: F, value: T[F]): T | undefined;
65
+ /**
66
+ * Obtain key/value map using specific field as key.
67
+ *
68
+ * Note we use {@link This} to constrain usage to sets where {@link T} === {@link AddT} as required by {@link Map}.
69
+ */
70
+ mapOf<This extends BasicSet<T, T>, F extends keyof T>(this: This, field: F): Map<T[F], T>;
54
71
  delete(item: T): boolean;
55
72
  clear(): void;
56
73
  get added(): Observable<[T], void>;
57
74
  get deleted(): Observable<[T], void>;
58
75
  protected create(definition: AddT): T;
59
76
  }
77
+ /**
78
+ * A {@link Map} backed by an {@link IndexedSet}.
79
+ *
80
+ * This supports the common case where sets must be looked up by key. Implementations like {@link BasicSet} offer
81
+ * efficient lookup by key using {@link IndexedSet#get}, but usage like a {@link Map} is still cumbersome. This class
82
+ * works as an adapter to make key/value access patterns more natural.
83
+ */
84
+ export declare class MapOfIndexedSet<T, S extends ImmutableSet<T> & MutableSet<T> & IndexedSet<T>, K extends keyof T> implements Map<T[K], T> {
85
+ #private;
86
+ /**
87
+ * Create a new map.
88
+ *
89
+ * @param set the backing data
90
+ * @param key a property of {@link T} used as the key
91
+ * @param index optional index that optimizes lookup by bypassing {@link IndexedSet#get}
92
+ */
93
+ constructor(set: S, key: K, index?: Map<T[K], T>);
94
+ clear(): void;
95
+ delete(key: T[K]): boolean;
96
+ forEach(callbackfn: (value: T, key: T[K], map: Map<T[K], T>) => void, thisArg?: any): void;
97
+ get(key: T[K]): T | undefined;
98
+ has(key: T[K]): boolean;
99
+ set(key: T[K], value: T): this;
100
+ get size(): number;
101
+ entries(): MapIterator<[T[K], T]>;
102
+ keys(): MapIterator<T[K]>;
103
+ values(): MapIterator<T>;
104
+ [Symbol.iterator](): MapIterator<[T[K], T]>;
105
+ [Symbol.toStringTag]: string;
106
+ }
107
+ export declare namespace MapOfIndexedSet {
108
+ class KeyValueMismatchError extends ImplementationError {
109
+ }
110
+ }
60
111
  //# sourceMappingURL=Set.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Set.d.ts","sourceRoot":"","sources":["../../../src/util/Set.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IACnB,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;CAC5D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC;IACnC,GAAG,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC;IAC/B,KAAK,IAAI,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC5B,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;CAChE;AAED;;;;GAIG;AACH,qBAAa,QAAQ,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;;gBAQnG,GAAG,YAAY,EAAE,IAAI,EAAE;IAMnC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAIjB,IAAI,IAAI,WAEP;IAED,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;IAI7B,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS;IAQhD,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS;IAUlD,GAAG,CAAC,IAAI,EAAE,CAAC;IAIX,GAAG,CAAC,IAAI,EAAE,IAAI;IA4Bd,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAmB5C,MAAM,CAAC,IAAI,EAAE,CAAC;IAwBd,KAAK;IAIL,IAAI,KAAK,0BAKR;IAED,IAAI,OAAO,0BAKV;IAED,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GACG,CAAC;CAExC"}
1
+ {"version":3,"file":"Set.d.ts","sourceRoot":"","sources":["../../../src/util/Set.ts"],"names":[],"mappings":"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"}
@@ -3,12 +3,14 @@
3
3
  * Copyright 2022-2025 Matter.js Authors
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { ImplementationError } from "#MatterError.js";
6
7
  import { Observable } from "./Observable.js";
7
8
  class BasicSet {
8
9
  #entries = /* @__PURE__ */ new Set();
9
10
  #added;
10
11
  #deleted;
11
12
  #indices;
13
+ #maps;
12
14
  constructor(...initialItems) {
13
15
  for (const item of initialItems) {
14
16
  this.add(item);
@@ -64,6 +66,9 @@ class BasicSet {
64
66
  this.#added?.emit(created);
65
67
  }
66
68
  get(field, value) {
69
+ return this.#indexOf(field).get(value);
70
+ }
71
+ #indexOf(field) {
67
72
  if (!this.#indices) {
68
73
  this.#indices = {};
69
74
  }
@@ -71,15 +76,31 @@ class BasicSet {
71
76
  if (index === void 0) {
72
77
  index = /* @__PURE__ */ new Map();
73
78
  for (const item of this) {
74
- const value2 = item[field];
75
- if (value2 === void 0 || index.has(value2)) {
79
+ const value = item[field];
80
+ if (value === void 0 || index.has(value)) {
76
81
  continue;
77
82
  }
78
- index.set(value2, item);
83
+ index.set(value, item);
79
84
  }
80
85
  this.#indices[field] = index;
81
86
  }
82
- return index?.get(value);
87
+ return index;
88
+ }
89
+ /**
90
+ * Obtain key/value map using specific field as key.
91
+ *
92
+ * Note we use {@link This} to constrain usage to sets where {@link T} === {@link AddT} as required by {@link Map}.
93
+ */
94
+ mapOf(field) {
95
+ if (!this.#maps) {
96
+ this.#maps = {};
97
+ }
98
+ let map = this.#maps[field];
99
+ if (map === void 0) {
100
+ map = new MapOfIndexedSet(this, field, this.#indexOf(field));
101
+ this.#maps[field] = map;
102
+ }
103
+ return map;
83
104
  }
84
105
  delete(item) {
85
106
  if (!this.#entries.delete(item)) {
@@ -119,7 +140,103 @@ class BasicSet {
119
140
  return definition;
120
141
  }
121
142
  }
143
+ class MapOfIndexedSet {
144
+ #set;
145
+ #key;
146
+ // This is an optimization for lookup
147
+ #index;
148
+ /**
149
+ * Create a new map.
150
+ *
151
+ * @param set the backing data
152
+ * @param key a property of {@link T} used as the key
153
+ * @param index optional index that optimizes lookup by bypassing {@link IndexedSet#get}
154
+ */
155
+ constructor(set, key, index) {
156
+ this.#set = set;
157
+ this.#key = key;
158
+ this.#index = index;
159
+ }
160
+ clear() {
161
+ this.#set.clear();
162
+ }
163
+ delete(key) {
164
+ const item = this.get(key);
165
+ if (item) {
166
+ return this.#set.delete(item);
167
+ }
168
+ return false;
169
+ }
170
+ forEach(callbackfn, thisArg) {
171
+ if (thisArg) {
172
+ callbackfn = callbackfn.bind(thisArg);
173
+ }
174
+ for (const [k, v] of this) {
175
+ callbackfn(v, k, this);
176
+ }
177
+ }
178
+ get(key) {
179
+ if (this.#index) {
180
+ return this.#index.get(key);
181
+ }
182
+ return this.#set.get(this.#key, key);
183
+ }
184
+ has(key) {
185
+ return this.#index ? this.#index.has(key) : this.#set.get(this.#key, key) !== void 0;
186
+ }
187
+ set(key, value) {
188
+ if (value[this.#key] !== key) {
189
+ throw new MapOfIndexedSet.KeyValueMismatchError(
190
+ `Cannot set key "${key}" because value property ${String(this.#key)} is "${value[this.#key]}"`
191
+ );
192
+ }
193
+ if (this.has(key)) {
194
+ if (this.get(key) === value) {
195
+ return this;
196
+ }
197
+ this.#set.delete(this.#index ? this.#index.get(key) : this.#set.get(this.#key, key));
198
+ }
199
+ this.#set.add(value);
200
+ return this;
201
+ }
202
+ get size() {
203
+ return this.#set.size;
204
+ }
205
+ entries() {
206
+ return this[Symbol.iterator]();
207
+ }
208
+ keys() {
209
+ if (this.#index) {
210
+ return this.#index.keys();
211
+ }
212
+ const keys = [...this.#set].map((item) => item[this.#key]).filter((key) => key !== void 0);
213
+ return keys[Symbol.iterator]();
214
+ }
215
+ values() {
216
+ if (this.#index) {
217
+ return this.#index.values();
218
+ }
219
+ const values = [...this.#set].map((item) => item);
220
+ return values[Symbol.iterator]();
221
+ }
222
+ *[Symbol.iterator]() {
223
+ for (const item of this.#set) {
224
+ const k = item[this.#key];
225
+ if (k === void 0) {
226
+ continue;
227
+ }
228
+ yield [k, item];
229
+ }
230
+ }
231
+ [Symbol.toStringTag] = "Map";
232
+ }
233
+ ((MapOfIndexedSet2) => {
234
+ class KeyValueMismatchError extends ImplementationError {
235
+ }
236
+ MapOfIndexedSet2.KeyValueMismatchError = KeyValueMismatchError;
237
+ })(MapOfIndexedSet || (MapOfIndexedSet = {}));
122
238
  export {
123
- BasicSet
239
+ BasicSet,
240
+ MapOfIndexedSet
124
241
  };
125
242
  //# sourceMappingURL=Set.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/util/Set.ts"],
4
- "mappings": "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",
5
- "names": ["value"]
4
+ "mappings": "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",
5
+ "names": ["MapOfIndexedSet"]
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter/general",
3
- "version": "0.14.0",
3
+ "version": "0.14.1-alpha.0-20250605-9fc134af0",
4
4
  "description": "Non-Matter support for Matter.js",
5
5
  "keywords": [
6
6
  "iot",
@@ -36,7 +36,7 @@
36
36
  "@noble/curves": "^1.9.1"
37
37
  },
38
38
  "devDependencies": {
39
- "@matter/testing": "0.14.0"
39
+ "@matter/testing": "0.14.1-alpha.0-20250605-9fc134af0"
40
40
  },
41
41
  "files": [
42
42
  "dist/**/*",
package/src/util/Set.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { ImplementationError } from "#MatterError.js";
7
8
  import { Observable } from "./Observable.js";
8
9
 
9
10
  /**
@@ -36,9 +37,20 @@ export interface ObservableSet<T> {
36
37
 
37
38
  /**
38
39
  * An interface for index set lookup.
40
+ *
41
+ * Note that this interface only supports a single item for each key. If multiple items associate with a key only the
42
+ * first is returned.
39
43
  */
40
44
  export interface IndexedSet<T> {
45
+ /**
46
+ * Retrieve an item with the named {@link field} set to {@link value}.
47
+ */
41
48
  get<F extends keyof T>(field: F, value: T[F]): T | undefined;
49
+
50
+ /**
51
+ * Obtain a {@link Map} of values in {@link field} to the associated item in the set.
52
+ */
53
+ mapOf<F extends keyof T>(field: F): Map<T[F], T>;
42
54
  }
43
55
 
44
56
  /**
@@ -51,7 +63,10 @@ export class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSet<T, Add
51
63
  #added?: Observable<[T]>;
52
64
  #deleted?: Observable<[T]>;
53
65
  #indices?: {
54
- [field in keyof T]?: Map<any, T>;
66
+ [field in keyof T]?: Map<T[field], T>;
67
+ };
68
+ #maps?: {
69
+ [field in keyof T]?: Map<T[field], T>;
55
70
  };
56
71
 
57
72
  constructor(...initialItems: AddT[]) {
@@ -123,6 +138,10 @@ export class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSet<T, Add
123
138
  }
124
139
 
125
140
  get<F extends keyof T>(field: F, value: T[F]) {
141
+ return this.#indexOf(field).get(value);
142
+ }
143
+
144
+ #indexOf<F extends keyof T>(field: F) {
126
145
  if (!this.#indices) {
127
146
  this.#indices = {};
128
147
  }
@@ -138,7 +157,24 @@ export class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSet<T, Add
138
157
  }
139
158
  this.#indices[field] = index;
140
159
  }
141
- return index?.get(value);
160
+ return index!; // Need "!" due to (apparent) TS bug
161
+ }
162
+
163
+ /**
164
+ * Obtain key/value map using specific field as key.
165
+ *
166
+ * Note we use {@link This} to constrain usage to sets where {@link T} === {@link AddT} as required by {@link Map}.
167
+ */
168
+ mapOf<This extends BasicSet<T, T>, F extends keyof T>(this: This, field: F): Map<T[F], T> {
169
+ if (!this.#maps) {
170
+ this.#maps = {};
171
+ }
172
+ let map = this.#maps[field];
173
+ if (map === undefined) {
174
+ map = new MapOfIndexedSet(this, field, this.#indexOf(field));
175
+ this.#maps[field] = map;
176
+ }
177
+ return map;
142
178
  }
143
179
 
144
180
  delete(item: T) {
@@ -187,3 +223,121 @@ export class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSet<T, Add
187
223
  return definition as unknown as T;
188
224
  }
189
225
  }
226
+
227
+ /**
228
+ * A {@link Map} backed by an {@link IndexedSet}.
229
+ *
230
+ * This supports the common case where sets must be looked up by key. Implementations like {@link BasicSet} offer
231
+ * efficient lookup by key using {@link IndexedSet#get}, but usage like a {@link Map} is still cumbersome. This class
232
+ * works as an adapter to make key/value access patterns more natural.
233
+ */
234
+ export class MapOfIndexedSet<T, S extends ImmutableSet<T> & MutableSet<T> & IndexedSet<T>, K extends keyof T>
235
+ implements Map<T[K], T>
236
+ {
237
+ #set: S;
238
+ #key: K;
239
+
240
+ // This is an optimization for lookup
241
+ #index?: Map<T[K], T>;
242
+
243
+ /**
244
+ * Create a new map.
245
+ *
246
+ * @param set the backing data
247
+ * @param key a property of {@link T} used as the key
248
+ * @param index optional index that optimizes lookup by bypassing {@link IndexedSet#get}
249
+ */
250
+ constructor(set: S, key: K, index?: Map<T[K], T>) {
251
+ this.#set = set;
252
+ this.#key = key;
253
+ this.#index = index;
254
+ }
255
+
256
+ clear(): void {
257
+ this.#set.clear();
258
+ }
259
+
260
+ delete(key: T[K]): boolean {
261
+ const item = this.get(key);
262
+ if (item) {
263
+ return this.#set.delete(item);
264
+ }
265
+ return false;
266
+ }
267
+
268
+ forEach(callbackfn: (value: T, key: T[K], map: Map<T[K], T>) => void, thisArg?: any): void {
269
+ if (thisArg) {
270
+ callbackfn = callbackfn.bind(thisArg);
271
+ }
272
+ for (const [k, v] of this) {
273
+ callbackfn(v, k, this);
274
+ }
275
+ }
276
+
277
+ get(key: T[K]): T | undefined {
278
+ if (this.#index) {
279
+ return this.#index.get(key);
280
+ }
281
+ return this.#set.get(this.#key, key);
282
+ }
283
+
284
+ has(key: T[K]): boolean {
285
+ return this.#index ? this.#index.has(key) : this.#set.get(this.#key, key) !== undefined;
286
+ }
287
+
288
+ set(key: T[K], value: T): this {
289
+ if (value[this.#key] !== key) {
290
+ throw new MapOfIndexedSet.KeyValueMismatchError(
291
+ `Cannot set key "${key}" because value property ${String(this.#key)} is "${value[this.#key]}"`,
292
+ );
293
+ }
294
+ if (this.has(key)) {
295
+ if (this.get(key) === value) {
296
+ return this;
297
+ }
298
+ this.#set.delete((this.#index ? this.#index.get(key) : this.#set.get(this.#key, key)) as T);
299
+ }
300
+ this.#set.add(value);
301
+ return this;
302
+ }
303
+
304
+ get size() {
305
+ return this.#set.size;
306
+ }
307
+
308
+ entries(): MapIterator<[T[K], T]> {
309
+ return this[Symbol.iterator]();
310
+ }
311
+
312
+ keys(): MapIterator<T[K]> {
313
+ if (this.#index) {
314
+ return this.#index.keys();
315
+ }
316
+ const keys = [...this.#set].map(item => item[this.#key]).filter(key => key !== undefined);
317
+ return keys[Symbol.iterator]();
318
+ }
319
+
320
+ values(): MapIterator<T> {
321
+ if (this.#index) {
322
+ return this.#index.values();
323
+ }
324
+ const values = [...this.#set].map(item => item);
325
+ return values[Symbol.iterator]();
326
+ }
327
+
328
+ *[Symbol.iterator](): MapIterator<[T[K], T]> {
329
+ for (const item of this.#set) {
330
+ const k = item[this.#key];
331
+ if (k === undefined) {
332
+ continue;
333
+ }
334
+ yield [k, item];
335
+ }
336
+ }
337
+
338
+ [Symbol.toStringTag] = "Map";
339
+ }
340
+
341
+ export namespace MapOfIndexedSet {
342
+ export class KeyValueMismatchError extends ImplementationError {}
343
+ }