@thi.ng/bidir-index 1.1.19 → 1.2.0

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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2025-04-16T11:11:14Z
3
+ - **Last updated**: 2025-04-30T12:52:32Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -11,6 +11,19 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
11
11
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
12
12
  and/or version bumps of transitive dependencies.
13
13
 
14
+ ## [1.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/bidir-index@1.2.0) (2025-04-30)
15
+
16
+ #### 🚀 Features
17
+
18
+ - restructure pkg, add `encodeObject()` / `decodeObject()` ([e812cac](https://github.com/thi-ng/umbrella/commit/e812cac))
19
+ - split up source files
20
+ - add new encoding/decoding fns
21
+ - add tests
22
+ - add iterator versions of object encoders/decoders ([f647d5c](https://github.com/thi-ng/umbrella/commit/f647d5c))
23
+ - add `encodeObjectIterator()`
24
+ - add `decodeObjectIterator()`
25
+ - add tests
26
+
14
27
  ## [1.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/bidir-index@1.1.0) (2024-07-22)
15
28
 
16
29
  #### 🚀 Features
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng&style=social)](https://mastodon.thi.ng/@toxi)
8
8
 
9
9
  > [!NOTE]
10
- > This is one of 205 standalone projects, maintained as part
10
+ > This is one of 206 standalone projects, maintained as part
11
11
  > of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
12
12
  > and anti-framework.
13
13
  >
@@ -20,6 +20,7 @@
20
20
  - [Installation](#installation)
21
21
  - [Dependencies](#dependencies)
22
22
  - [API](#api)
23
+ - [Basic usage example](#basic-usage-example)
23
24
  - [Authors](#authors)
24
25
  - [License](#license)
25
26
 
@@ -66,7 +67,7 @@ For Node.js REPL:
66
67
  const bi = await import("@thi.ng/bidir-index");
67
68
  ```
68
69
 
69
- Package sizes (brotli'd, pre-treeshake): ESM: 657 bytes
70
+ Package sizes (brotli'd, pre-treeshake): ESM: 854 bytes
70
71
 
71
72
  ## Dependencies
72
73
 
@@ -78,6 +79,43 @@ None
78
79
 
79
80
  TODO
80
81
 
82
+ ## Basic usage example
83
+
84
+ ```ts tangle:export/readme.ts
85
+ import { defBidirIndex, encodeObject, decodeObject } from "@thi.ng/bidir-index";
86
+
87
+ const index = defBidirIndex<string>();
88
+
89
+ // given object keys are auto-indexed, array initialized with given default
90
+ console.log(
91
+ encodeObject(index, { r: 1, g: 2, b: 3, a: 4 }, 0)
92
+ );
93
+ // [1, 2, 3, 4]
94
+
95
+ // use custom default and without updating index
96
+ console.log(
97
+ encodeObject(index, { b: 3, r: 1, g: 2 }, -1, false)
98
+ );
99
+ // [1, 2, 3, -1] (missing key `a` mapped to given default value)
100
+
101
+ // decode with defaults/fallback
102
+ console.log(
103
+ decodeObject(index, [255, 128, 64], { a: 1 })
104
+ );
105
+ // { r: 255, g: 128, b: 64, a: 1 }
106
+
107
+ // add more keys to index (already known ones will be skipped)
108
+ // returns array of mapped IDs for given keys
109
+ index.addAll(["r", "g", "b", "a", "foo"]);
110
+ // [0, 1, 2, 3, 4]
111
+
112
+ // decoding will skip nullish values
113
+ console.log(
114
+ decodeObject(index, [null, null, null, null, "bar"])
115
+ );
116
+ // { foo: "bar" }
117
+ ```
118
+
81
119
  ## Authors
82
120
 
83
121
  - [Karsten Schmidt](https://thi.ng)
package/api.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export interface SerializedBidirIndex<T> {
2
+ pairs: [T, number][];
3
+ nextID: number;
4
+ }
5
+ export interface BidirIndexOpts<T> {
6
+ /**
7
+ * Custom `key -> id` map implementation (e.g. {@link EquivMap} or
8
+ * {@link HashMap}). If omitted, a native JS `Map` will be used.
9
+ */
10
+ map: Map<T, number>;
11
+ /**
12
+ * Start ID for indexing new keys.
13
+ *
14
+ * @defaultValue 0
15
+ */
16
+ start: number;
17
+ }
18
+ //# sourceMappingURL=api.d.ts.map
package/api.js ADDED
File without changes
@@ -0,0 +1,135 @@
1
+ import type { BidirIndexOpts, SerializedBidirIndex } from "./api.js";
2
+ /**
3
+ * Bi-directional index to map arbitrary keys to numeric IDs and vice versa.
4
+ */
5
+ export declare class BidirIndex<T> {
6
+ fwd: Map<T, number>;
7
+ rev: Map<number, T>;
8
+ nextID: number;
9
+ constructor(keys?: Iterable<T> | null, opts?: Partial<BidirIndexOpts<T>>);
10
+ get size(): number;
11
+ /**
12
+ * Yields same result as {@link BidirIndex.entries}.
13
+ */
14
+ [Symbol.iterator](): MapIterator<[T, number]>;
15
+ /**
16
+ * Returns iterator of `[key,id]` pairs.
17
+ */
18
+ entries(): MapIterator<[T, number]>;
19
+ /**
20
+ * Returns iterator of all indexed keys.
21
+ */
22
+ keys(): MapIterator<T>;
23
+ /**
24
+ * Returns iterator of all indexed IDs.
25
+ */
26
+ values(): MapIterator<number>;
27
+ /**
28
+ * Returns true if given `key` is known/indexed.
29
+ *
30
+ * @param key
31
+ */
32
+ has(key: T): boolean;
33
+ /**
34
+ * Returns true if given `id` has a corresponding known/indexed key.
35
+ *
36
+ * @param id
37
+ */
38
+ hasID(id: number): boolean;
39
+ /**
40
+ * Reverse lookup of {@link BidirIndex.getID}. Returns the matching ID for
41
+ * given `key` or undefined if the key is not known.
42
+ *
43
+ * @param key
44
+ */
45
+ get(key: T): number | undefined;
46
+ /**
47
+ * Reverse lookup of {@link BidirIndex.get}. Returns the matching key for
48
+ * given `id` or undefined if the ID is not known.
49
+ *
50
+ * @param id
51
+ */
52
+ getID(id: number): T | undefined;
53
+ /**
54
+ * Indexes given `key` and assigns & returns a new ID. If `key` is already
55
+ * known/indexed, returns its existing ID.
56
+ *
57
+ * @param key
58
+ */
59
+ add(key: T): number;
60
+ /**
61
+ * Batch version of {@link BidirIndex.add}. Indexes all given keys and
62
+ * returns array of their corresponding IDs.
63
+ *
64
+ * @param keys
65
+ */
66
+ addAll(keys: Iterable<T>): number[];
67
+ /**
68
+ * Removes bi-directional mapping for given `key` from the index. Returns
69
+ * true if successful.
70
+ *
71
+ * @param key
72
+ */
73
+ delete(key: T): boolean;
74
+ /**
75
+ * Removes bi-directional mapping for given `id` from the index. Returns
76
+ * true if successful.
77
+ *
78
+ * @param id
79
+ */
80
+ deleteID(id: number): boolean;
81
+ /**
82
+ * Batch version of {@link BidirIndex.delete}.
83
+ *
84
+ * @param keys
85
+ */
86
+ deleteAll(keys: Iterable<T>): void;
87
+ /**
88
+ * Batch version of {@link BidirIndex.deleteID}.
89
+ *
90
+ * @param ids
91
+ */
92
+ deleteAllIDs(ids: Iterable<number>): void;
93
+ /**
94
+ * Returns array of IDs for all given keys. If `fail` is true (default:
95
+ * false), throws error if any of the given keys is unknown/unindexed (use
96
+ * {@link BidirIndex.add} or {@link BidirIndex.addAll} first).
97
+ *
98
+ * @param keys
99
+ * @param fail
100
+ */
101
+ getAll(keys: Iterable<T>, fail?: boolean): number[];
102
+ /**
103
+ * Returns array of matching keys for all given IDs. If `fail` is true
104
+ * (default: false), throws error if any of the given IDs is
105
+ * unknown/unindexed (use {@link BidirIndex.add} or
106
+ * {@link BidirIndex.addAll} first).
107
+ *
108
+ * @param ids
109
+ * @param fail
110
+ */
111
+ getAllIDs(ids: Iterable<number>, fail?: boolean): T[];
112
+ /**
113
+ * Returns a compact JSON serializable version of the index. Use
114
+ * {@link bidirIndexFromJSON} to instantiate an index from such a JSON
115
+ * serialization.
116
+ */
117
+ toJSON(): SerializedBidirIndex<T>;
118
+ }
119
+ /**
120
+ * Factory function wrapper for {@link BidirIndex}.
121
+ *
122
+ * @param keys
123
+ * @param opts
124
+ */
125
+ export declare const defBidirIndex: <T>(keys?: Iterable<T>, opts?: Partial<BidirIndexOpts<T>>) => BidirIndex<T>;
126
+ /**
127
+ * Instantiates a {@link BidirIndex} from given JSON serialization. The optional
128
+ * `map` arg can be used to provide a customized `key -> id` map implementation
129
+ * (same use as {@link BidirIndexOpts.map}).
130
+ *
131
+ * @param src
132
+ * @param map
133
+ */
134
+ export declare const bidirIndexFromJSON: <T>(src: string | SerializedBidirIndex<T>, map?: Map<T, number>) => BidirIndex<T>;
135
+ //# sourceMappingURL=bidir-index.d.ts.map
package/bidir-index.js ADDED
@@ -0,0 +1,204 @@
1
+ class BidirIndex {
2
+ fwd;
3
+ rev;
4
+ nextID;
5
+ constructor(keys, opts = {}) {
6
+ this.nextID = opts.start || 0;
7
+ this.fwd = opts.map || /* @__PURE__ */ new Map();
8
+ this.rev = /* @__PURE__ */ new Map();
9
+ keys && this.addAll(keys);
10
+ }
11
+ get size() {
12
+ return this.fwd.size;
13
+ }
14
+ /**
15
+ * Yields same result as {@link BidirIndex.entries}.
16
+ */
17
+ [Symbol.iterator]() {
18
+ return this.entries();
19
+ }
20
+ /**
21
+ * Returns iterator of `[key,id]` pairs.
22
+ */
23
+ entries() {
24
+ return this.fwd.entries();
25
+ }
26
+ /**
27
+ * Returns iterator of all indexed keys.
28
+ */
29
+ keys() {
30
+ return this.fwd.keys();
31
+ }
32
+ /**
33
+ * Returns iterator of all indexed IDs.
34
+ */
35
+ values() {
36
+ return this.fwd.values();
37
+ }
38
+ /**
39
+ * Returns true if given `key` is known/indexed.
40
+ *
41
+ * @param key
42
+ */
43
+ has(key) {
44
+ return this.fwd.has(key);
45
+ }
46
+ /**
47
+ * Returns true if given `id` has a corresponding known/indexed key.
48
+ *
49
+ * @param id
50
+ */
51
+ hasID(id) {
52
+ return this.rev.has(id);
53
+ }
54
+ /**
55
+ * Reverse lookup of {@link BidirIndex.getID}. Returns the matching ID for
56
+ * given `key` or undefined if the key is not known.
57
+ *
58
+ * @param key
59
+ */
60
+ get(key) {
61
+ return this.fwd.get(key);
62
+ }
63
+ /**
64
+ * Reverse lookup of {@link BidirIndex.get}. Returns the matching key for
65
+ * given `id` or undefined if the ID is not known.
66
+ *
67
+ * @param id
68
+ */
69
+ getID(id) {
70
+ return this.rev.get(id);
71
+ }
72
+ /**
73
+ * Indexes given `key` and assigns & returns a new ID. If `key` is already
74
+ * known/indexed, returns its existing ID.
75
+ *
76
+ * @param key
77
+ */
78
+ add(key) {
79
+ let id = this.fwd.get(key);
80
+ if (id === void 0) {
81
+ this.fwd.set(key, this.nextID);
82
+ this.rev.set(this.nextID, key);
83
+ id = this.nextID++;
84
+ }
85
+ return id;
86
+ }
87
+ /**
88
+ * Batch version of {@link BidirIndex.add}. Indexes all given keys and
89
+ * returns array of their corresponding IDs.
90
+ *
91
+ * @param keys
92
+ */
93
+ addAll(keys) {
94
+ const res = [];
95
+ for (let k of keys) {
96
+ res.push(this.add(k));
97
+ }
98
+ return res;
99
+ }
100
+ /**
101
+ * Removes bi-directional mapping for given `key` from the index. Returns
102
+ * true if successful.
103
+ *
104
+ * @param key
105
+ */
106
+ delete(key) {
107
+ return __delete(this.fwd, this.rev, key);
108
+ }
109
+ /**
110
+ * Removes bi-directional mapping for given `id` from the index. Returns
111
+ * true if successful.
112
+ *
113
+ * @param id
114
+ */
115
+ deleteID(id) {
116
+ return __delete(this.rev, this.fwd, id);
117
+ }
118
+ /**
119
+ * Batch version of {@link BidirIndex.delete}.
120
+ *
121
+ * @param keys
122
+ */
123
+ deleteAll(keys) {
124
+ for (let k of keys) this.delete(k);
125
+ }
126
+ /**
127
+ * Batch version of {@link BidirIndex.deleteID}.
128
+ *
129
+ * @param ids
130
+ */
131
+ deleteAllIDs(ids) {
132
+ for (let id of ids) this.deleteID(id);
133
+ }
134
+ /**
135
+ * Returns array of IDs for all given keys. If `fail` is true (default:
136
+ * false), throws error if any of the given keys is unknown/unindexed (use
137
+ * {@link BidirIndex.add} or {@link BidirIndex.addAll} first).
138
+ *
139
+ * @param keys
140
+ * @param fail
141
+ */
142
+ getAll(keys, fail = false) {
143
+ return __iterate(this.fwd, keys, fail);
144
+ }
145
+ /**
146
+ * Returns array of matching keys for all given IDs. If `fail` is true
147
+ * (default: false), throws error if any of the given IDs is
148
+ * unknown/unindexed (use {@link BidirIndex.add} or
149
+ * {@link BidirIndex.addAll} first).
150
+ *
151
+ * @param ids
152
+ * @param fail
153
+ */
154
+ getAllIDs(ids, fail = false) {
155
+ return __iterate(this.rev, ids, fail);
156
+ }
157
+ /**
158
+ * Returns a compact JSON serializable version of the index. Use
159
+ * {@link bidirIndexFromJSON} to instantiate an index from such a JSON
160
+ * serialization.
161
+ */
162
+ toJSON() {
163
+ return {
164
+ pairs: [...this.entries()],
165
+ nextID: this.nextID
166
+ };
167
+ }
168
+ }
169
+ const __delete = (fwd, rev, key) => {
170
+ const val = fwd.get(key);
171
+ if (val !== void 0) {
172
+ fwd.delete(key);
173
+ rev.delete(val);
174
+ return true;
175
+ }
176
+ return false;
177
+ };
178
+ const __iterate = (index, keys, fail) => {
179
+ const res = [];
180
+ for (let k of keys) {
181
+ const val = index.get(k);
182
+ if (val === void 0) {
183
+ if (fail) throw new Error(`unknwon key/ID: ${k}`);
184
+ } else {
185
+ res.push(val);
186
+ }
187
+ }
188
+ return res;
189
+ };
190
+ const defBidirIndex = (keys, opts) => new BidirIndex(keys, opts);
191
+ const bidirIndexFromJSON = (src, map) => {
192
+ const $src = typeof src === "string" ? JSON.parse(src) : src;
193
+ const res = new BidirIndex(null, { map, start: $src.nextID });
194
+ $src.pairs.forEach(([k, id]) => {
195
+ res.fwd.set(k, id);
196
+ res.rev.set(id, k);
197
+ });
198
+ return res;
199
+ };
200
+ export {
201
+ BidirIndex,
202
+ bidirIndexFromJSON,
203
+ defBidirIndex
204
+ };
package/encode.d.ts ADDED
@@ -0,0 +1,128 @@
1
+ import type { BidirIndex } from "./bidir-index.js";
2
+ /**
3
+ * Encodes given object into an array, using the given `index` to determine each
4
+ * key's value position. The array will be pre-filled with `defaultValue`.
5
+ * Unless `indexKeys` is disabled, the object's keys are first added to the
6
+ * index.
7
+ *
8
+ * @remarks
9
+ * Also see {@link decodeObject} for reverse operation.
10
+ *
11
+ * @example
12
+ * ```ts tangle:../export/encode-object.ts
13
+ * import { defBidirIndex, encodeObject } from "@thi.ng/bidir-index";
14
+ *
15
+ * const index = defBidirIndex<string>();
16
+ *
17
+ * console.log(
18
+ * encodeObject(index, { r: 255, g: 128, b: 64, a: 1 }, 0)
19
+ * );
20
+ * // [255, 128, 64, 1]
21
+ *
22
+ * // encode without updating index
23
+ * console.log(
24
+ * encodeObject(index, { b: 3, r: 1, g: 2 }, 0, false)
25
+ * );
26
+ * // [1, 2, 3, 0] (key `a` uses default)
27
+ * ```
28
+ *
29
+ * @param index
30
+ * @param obj
31
+ * @param defaultValue
32
+ * @param indexKeys
33
+ */
34
+ export declare const encodeObject: <V, K extends string = string>(index: BidirIndex<K>, obj: Partial<Record<K, V>>, defaultValue: V, indexKeys?: boolean) => V[];
35
+ /**
36
+ * Similar to {@link encodeObject}, but implemented as an iterator for
37
+ * processing multiple objects into a single flat iterable.
38
+ *
39
+ * @example
40
+ * ```ts tangle:../export/encode-object-iterator.ts
41
+ * import { defBidirIndex, encodeObjectIterator } from "@thi.ng/bidir-index";
42
+ *
43
+ * const index = defBidirIndex<string>();
44
+ *
45
+ * // source data objects
46
+ * const data = [
47
+ * { r: 1, g: 2, b: 3},
48
+ * { x: 4, y: 5, z: 6}
49
+ * ];
50
+ *
51
+ * // directly encode into a typedarray
52
+ * const buf = new Uint8Array(encodeObjectIterator(index, data, 0));
53
+ *
54
+ * console.log(buf);
55
+ * // Uint8Array(12) [ 1, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 6 ]
56
+ * ```
57
+ *
58
+ * @param index
59
+ * @param objects
60
+ * @param defaultValue
61
+ * @param indexKeys
62
+ */
63
+ export declare const encodeObjectIterator: <V, K extends string = string>(index: BidirIndex<K>, objects: Partial<Record<K, V>>[], defaultValue: V, indexKeys?: boolean) => Generator<V, void, unknown>;
64
+ /**
65
+ * Reverse op of {@link encodeObject}. Takes an array of `values` and returns an
66
+ * object with values mapped to keys based on their indexed position. If the
67
+ * `values` array has a nullish value for a keyed index, the optionally provided
68
+ * `defaults` object will be used to obtain a value. The result object will only
69
+ * have keys with non-nullish values.
70
+ *
71
+ * @remarks
72
+ * Note: Irrespective of original key type used for this index instance, the
73
+ * keys in the result object will be strings.
74
+ *
75
+ * Also see {@link encodeObject}.
76
+ *
77
+ * @example
78
+ * ```ts tangle:../export/decode-object.ts
79
+ * import { defBidirIndex, decodeObject } from "@thi.ng/bidir-index";
80
+ *
81
+ * const index = defBidirIndex<string>();
82
+ * index.addAll(["r", "g", "b", "a", "foo"]);
83
+ *
84
+ * // decode with defaults/fallback
85
+ * console.log(
86
+ * decodeObject(index, [255, 128, 64], { a: 1 })
87
+ * );
88
+ * // { r: 255, g: 128, b: 64, a: 1 } (key `foo` is omitted in result)
89
+ *
90
+ * console.log(
91
+ * decodeObject(index, [null, null, null, null, "bar"])
92
+ * );
93
+ * // { foo: "bar" }
94
+ * ```
95
+ *
96
+ * @param values
97
+ * @param defaults
98
+ */
99
+ export declare const decodeObject: <V, K extends string = string>(index: Iterable<[K, number]>, values: V[], defaults?: Partial<Record<K, V>>) => Partial<Record<K, V>>;
100
+ /**
101
+ * Reverse op of {@link encodeObjectIterator}. An iterator which takes an array
102
+ * of encoded values and yields sequence of objects decoded via
103
+ * {@link decodeObject}.
104
+ *
105
+ * @example
106
+ * ```ts tangle:../export/decode-object-iterator.ts
107
+ * import { defBidirIndex, decodeObjectIterator } from "@thi.ng/bidir-index";
108
+ *
109
+ * const index = defBidirIndex<string>();
110
+ * index.addAll("rgbxyz");
111
+ *
112
+ * const data = [1, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 6];
113
+ *
114
+ * for(let obj of decodeObjectIterator(index, data, 6)) {
115
+ * console.log(obj);
116
+ * }
117
+ *
118
+ * // { r: 1, g: 2, b: 3, x: 0, y: 0, z: 0 }
119
+ * // { r: 0, g: 0, b: 0, x: 4, y: 5, z: 6 }
120
+ * ```
121
+ *
122
+ * @param index
123
+ * @param values
124
+ * @param size
125
+ * @param defaults
126
+ */
127
+ export declare function decodeObjectIterator<V, K extends string = string>(index: Iterable<[K, number]>, values: V[], size: number, defaults?: Partial<Record<K, V>>): Generator<Partial<Record<K, V>>, void, unknown>;
128
+ //# sourceMappingURL=encode.d.ts.map
package/encode.js ADDED
@@ -0,0 +1,37 @@
1
+ const encodeObject = (index, obj, defaultValue, indexKeys = true) => {
2
+ const keys = Object.keys(obj);
3
+ const ids = indexKeys ? index.addAll(keys) : index.getAll(keys);
4
+ const res = new Array(index.size).fill(defaultValue);
5
+ for (let id of ids) {
6
+ const val = obj[index.getID(id)];
7
+ if (val != null) res[id] = val;
8
+ }
9
+ return res;
10
+ };
11
+ const encodeObjectIterator = function* (index, objects, defaultValue, indexKeys = true) {
12
+ if (indexKeys) {
13
+ for (let o of objects) index.addAll(Object.keys(o));
14
+ }
15
+ for (let o of objects) {
16
+ yield* encodeObject(index, o, defaultValue, false);
17
+ }
18
+ };
19
+ const decodeObject = (index, values, defaults) => {
20
+ const res = {};
21
+ for (let [k, id] of index) {
22
+ const val = values[id] ?? defaults?.[k];
23
+ if (val != null) res[k] = val;
24
+ }
25
+ return res;
26
+ };
27
+ function* decodeObjectIterator(index, values, size, defaults) {
28
+ for (let i = 0, num = values.length; i < num; i += size) {
29
+ yield decodeObject(index, values.slice(i, i + size), defaults);
30
+ }
31
+ }
32
+ export {
33
+ decodeObject,
34
+ decodeObjectIterator,
35
+ encodeObject,
36
+ encodeObjectIterator
37
+ };
package/index.d.ts CHANGED
@@ -1,151 +1,4 @@
1
- export interface SerializedBidirIndex<T> {
2
- pairs: [T, number][];
3
- nextID: number;
4
- }
5
- export interface BidirIndexOpts<T> {
6
- /**
7
- * Custom `key -> id` map implementation (e.g. {@link EquivMap} or
8
- * {@link HashMap}). If omitted, a native JS `Map` will be used.
9
- */
10
- map: Map<T, number>;
11
- /**
12
- * Start ID for indexing new keys.
13
- *
14
- * @defaultValue 0
15
- */
16
- start: number;
17
- }
18
- /**
19
- * Bi-directional index to map arbitrary keys to numeric IDs and vice versa.
20
- */
21
- export declare class BidirIndex<T> {
22
- fwd: Map<T, number>;
23
- rev: Map<number, T>;
24
- nextID: number;
25
- constructor(keys?: Iterable<T> | null, opts?: Partial<BidirIndexOpts<T>>);
26
- get size(): number;
27
- /**
28
- * Yields same result as {@link BidirIndex.entries}.
29
- */
30
- [Symbol.iterator](): MapIterator<[T, number]>;
31
- /**
32
- * Returns iterator of `[key,id]` pairs.
33
- */
34
- entries(): MapIterator<[T, number]>;
35
- /**
36
- * Returns iterator of all indexed keys.
37
- */
38
- keys(): MapIterator<T>;
39
- /**
40
- * Returns iterator of all indexed IDs.
41
- */
42
- values(): MapIterator<number>;
43
- /**
44
- * Returns true if given `key` is known/indexed.
45
- *
46
- * @param key
47
- */
48
- has(key: T): boolean;
49
- /**
50
- * Returns true if given `id` has a corresponding known/indexed key.
51
- *
52
- * @param id
53
- */
54
- hasID(id: number): boolean;
55
- /**
56
- * Reverse lookup of {@link BidirIndex.getID}. Returns the matching ID for
57
- * given `key` or undefined if the key is not known.
58
- *
59
- * @param key
60
- */
61
- get(key: T): number | undefined;
62
- /**
63
- * Reverse lookup of {@link BidirIndex.get}. Returns the matching key for
64
- * given `id` or undefined if the ID is not known.
65
- *
66
- * @param id
67
- */
68
- getID(id: number): T | undefined;
69
- /**
70
- * Indexes given `key` and assigns & returns a new ID. If `key` is already
71
- * known/indexed, returns its existing ID.
72
- *
73
- * @param key
74
- */
75
- add(key: T): number;
76
- /**
77
- * Batch version of {@link BidirIndex.add}. Indexes all given keys and
78
- * returns array of their corresponding IDs.
79
- *
80
- * @param keys
81
- */
82
- addAll(keys: Iterable<T>): number[];
83
- /**
84
- * Removes bi-directional mapping for given `key` from the index. Returns
85
- * true if successful.
86
- *
87
- * @param key
88
- */
89
- delete(key: T): boolean;
90
- /**
91
- * Removes bi-directional mapping for given `id` from the index. Returns
92
- * true if successful.
93
- *
94
- * @param id
95
- */
96
- deleteID(id: number): boolean;
97
- /**
98
- * Batch version of {@link BidirIndex.delete}.
99
- *
100
- * @param keys
101
- */
102
- deleteAll(keys: Iterable<T>): void;
103
- /**
104
- * Batch version of {@link BidirIndex.deleteID}.
105
- *
106
- * @param ids
107
- */
108
- deleteAllIDs(ids: Iterable<number>): void;
109
- /**
110
- * Returns array of IDs for all given keys. If `fail` is true (default:
111
- * false), throws error if any of the given keys is unknown/unindexed (use
112
- * {@link BidirIndex.add} or {@link BidirIndex.addAll} first).
113
- *
114
- * @param keys
115
- * @param fail
116
- */
117
- getAll(keys: Iterable<T>, fail?: boolean): number[];
118
- /**
119
- * Returns array of matching keys for all given IDs. If `fail` is true
120
- * (default: false), throws error if any of the given IDs is
121
- * unknown/unindexed (use {@link BidirIndex.add} or
122
- * {@link BidirIndex.addAll} first).
123
- *
124
- * @param ids
125
- * @param fail
126
- */
127
- getAllIDs(ids: Iterable<number>, fail?: boolean): T[];
128
- /**
129
- * Returns a compact JSON serializable version of the index. Use
130
- * {@link bidirIndexFromJSON} to instantiate an index from such a JSON
131
- * serialization.
132
- */
133
- toJSON(): SerializedBidirIndex<T>;
134
- }
135
- /**
136
- * Factory function wrapper for {@link BidirIndex}.
137
- *
138
- * @param keys
139
- * @param opts
140
- */
141
- export declare const defBidirIndex: <T>(keys?: Iterable<T>, opts?: Partial<BidirIndexOpts<T>>) => BidirIndex<T>;
142
- /**
143
- * Instantiates a {@link BidirIndex} from given JSON serialization. The optional
144
- * `map` arg can be used to provide a customized `key -> id` map implementation
145
- * (same use as {@link BidirIndexOpts.map}).
146
- *
147
- * @param src
148
- * @param map
149
- */
150
- export declare const bidirIndexFromJSON: <T>(src: string | SerializedBidirIndex<T>, map?: Map<T, number>) => BidirIndex<T>;
1
+ export * from "./api.js";
2
+ export * from "./bidir-index.js";
3
+ export * from "./encode.js";
151
4
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,204 +1,3 @@
1
- class BidirIndex {
2
- fwd;
3
- rev;
4
- nextID;
5
- constructor(keys, opts = {}) {
6
- this.nextID = opts.start || 0;
7
- this.fwd = opts.map || /* @__PURE__ */ new Map();
8
- this.rev = /* @__PURE__ */ new Map();
9
- keys && this.addAll(keys);
10
- }
11
- get size() {
12
- return this.fwd.size;
13
- }
14
- /**
15
- * Yields same result as {@link BidirIndex.entries}.
16
- */
17
- [Symbol.iterator]() {
18
- return this.entries();
19
- }
20
- /**
21
- * Returns iterator of `[key,id]` pairs.
22
- */
23
- entries() {
24
- return this.fwd.entries();
25
- }
26
- /**
27
- * Returns iterator of all indexed keys.
28
- */
29
- keys() {
30
- return this.fwd.keys();
31
- }
32
- /**
33
- * Returns iterator of all indexed IDs.
34
- */
35
- values() {
36
- return this.fwd.values();
37
- }
38
- /**
39
- * Returns true if given `key` is known/indexed.
40
- *
41
- * @param key
42
- */
43
- has(key) {
44
- return this.fwd.has(key);
45
- }
46
- /**
47
- * Returns true if given `id` has a corresponding known/indexed key.
48
- *
49
- * @param id
50
- */
51
- hasID(id) {
52
- return this.rev.has(id);
53
- }
54
- /**
55
- * Reverse lookup of {@link BidirIndex.getID}. Returns the matching ID for
56
- * given `key` or undefined if the key is not known.
57
- *
58
- * @param key
59
- */
60
- get(key) {
61
- return this.fwd.get(key);
62
- }
63
- /**
64
- * Reverse lookup of {@link BidirIndex.get}. Returns the matching key for
65
- * given `id` or undefined if the ID is not known.
66
- *
67
- * @param id
68
- */
69
- getID(id) {
70
- return this.rev.get(id);
71
- }
72
- /**
73
- * Indexes given `key` and assigns & returns a new ID. If `key` is already
74
- * known/indexed, returns its existing ID.
75
- *
76
- * @param key
77
- */
78
- add(key) {
79
- let id = this.fwd.get(key);
80
- if (id === void 0) {
81
- this.fwd.set(key, this.nextID);
82
- this.rev.set(this.nextID, key);
83
- id = this.nextID++;
84
- }
85
- return id;
86
- }
87
- /**
88
- * Batch version of {@link BidirIndex.add}. Indexes all given keys and
89
- * returns array of their corresponding IDs.
90
- *
91
- * @param keys
92
- */
93
- addAll(keys) {
94
- const res = [];
95
- for (let k of keys) {
96
- res.push(this.add(k));
97
- }
98
- return res;
99
- }
100
- /**
101
- * Removes bi-directional mapping for given `key` from the index. Returns
102
- * true if successful.
103
- *
104
- * @param key
105
- */
106
- delete(key) {
107
- return __delete(this.fwd, this.rev, key);
108
- }
109
- /**
110
- * Removes bi-directional mapping for given `id` from the index. Returns
111
- * true if successful.
112
- *
113
- * @param id
114
- */
115
- deleteID(id) {
116
- return __delete(this.rev, this.fwd, id);
117
- }
118
- /**
119
- * Batch version of {@link BidirIndex.delete}.
120
- *
121
- * @param keys
122
- */
123
- deleteAll(keys) {
124
- for (let k of keys) this.delete(k);
125
- }
126
- /**
127
- * Batch version of {@link BidirIndex.deleteID}.
128
- *
129
- * @param ids
130
- */
131
- deleteAllIDs(ids) {
132
- for (let id of ids) this.deleteID(id);
133
- }
134
- /**
135
- * Returns array of IDs for all given keys. If `fail` is true (default:
136
- * false), throws error if any of the given keys is unknown/unindexed (use
137
- * {@link BidirIndex.add} or {@link BidirIndex.addAll} first).
138
- *
139
- * @param keys
140
- * @param fail
141
- */
142
- getAll(keys, fail = false) {
143
- return __iterate(this.fwd, keys, fail);
144
- }
145
- /**
146
- * Returns array of matching keys for all given IDs. If `fail` is true
147
- * (default: false), throws error if any of the given IDs is
148
- * unknown/unindexed (use {@link BidirIndex.add} or
149
- * {@link BidirIndex.addAll} first).
150
- *
151
- * @param ids
152
- * @param fail
153
- */
154
- getAllIDs(ids, fail = false) {
155
- return __iterate(this.rev, ids, fail);
156
- }
157
- /**
158
- * Returns a compact JSON serializable version of the index. Use
159
- * {@link bidirIndexFromJSON} to instantiate an index from such a JSON
160
- * serialization.
161
- */
162
- toJSON() {
163
- return {
164
- pairs: [...this.entries()],
165
- nextID: this.nextID
166
- };
167
- }
168
- }
169
- const __delete = (fwd, rev, key) => {
170
- const val = fwd.get(key);
171
- if (val !== void 0) {
172
- fwd.delete(key);
173
- rev.delete(val);
174
- return true;
175
- }
176
- return false;
177
- };
178
- const __iterate = (index, keys, fail) => {
179
- const res = [];
180
- for (let k of keys) {
181
- const val = index.get(k);
182
- if (val === void 0) {
183
- if (fail) throw new Error(`unknwon key/ID: ${k}`);
184
- } else {
185
- res.push(val);
186
- }
187
- }
188
- return res;
189
- };
190
- const defBidirIndex = (keys, opts) => new BidirIndex(keys, opts);
191
- const bidirIndexFromJSON = (src, map) => {
192
- const $src = typeof src === "string" ? JSON.parse(src) : src;
193
- const res = new BidirIndex(null, { map, start: $src.nextID });
194
- $src.pairs.forEach(([k, id]) => {
195
- res.fwd.set(k, id);
196
- res.rev.set(id, k);
197
- });
198
- return res;
199
- };
200
- export {
201
- BidirIndex,
202
- bidirIndexFromJSON,
203
- defBidirIndex
204
- };
1
+ export * from "./api.js";
2
+ export * from "./bidir-index.js";
3
+ export * from "./encode.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/bidir-index",
3
- "version": "1.1.19",
3
+ "version": "1.2.0",
4
4
  "description": "Bi-directional index mapping arbitrary keys to numeric IDs & vice versa",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -39,13 +39,15 @@
39
39
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
40
40
  },
41
41
  "devDependencies": {
42
- "esbuild": "^0.25.2",
43
- "typedoc": "^0.28.2",
42
+ "esbuild": "^0.25.3",
43
+ "typedoc": "^0.28.3",
44
44
  "typescript": "^5.8.3"
45
45
  },
46
46
  "keywords": [
47
47
  "bidirectional",
48
48
  "datastructure",
49
+ "decode",
50
+ "encode",
49
51
  "identifier",
50
52
  "invert",
51
53
  "iterator",
@@ -70,6 +72,15 @@
70
72
  "exports": {
71
73
  ".": {
72
74
  "default": "./index.js"
75
+ },
76
+ "./api": {
77
+ "default": "./api.js"
78
+ },
79
+ "./bidir-index": {
80
+ "default": "./bidir-index.js"
81
+ },
82
+ "./encode": {
83
+ "default": "./encode.js"
73
84
  }
74
85
  },
75
86
  "thi.ng": {
@@ -78,5 +89,5 @@
78
89
  ],
79
90
  "year": 2022
80
91
  },
81
- "gitHead": "c464b6948f92cba90c2ea75b59203dad894fb450\n"
92
+ "gitHead": "4354686a6fb1f82c09ea48f92f87786191b231a0\n"
82
93
  }