@optique/core 1.0.16-dev.2975 → 1.0.16-dev.2983

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.
@@ -22,23 +22,102 @@ function serializePath(path) {
22
22
  if (path.length === 0) return "";
23
23
  return path.map(serializeKey).join("");
24
24
  }
25
+ function height(node$1) {
26
+ return node$1?.height ?? 0;
27
+ }
28
+ function node(key, entry, left, right) {
29
+ return {
30
+ key,
31
+ entry,
32
+ left,
33
+ right,
34
+ height: 1 + Math.max(height(left), height(right))
35
+ };
36
+ }
37
+ function balance(key, entry, left, right) {
38
+ if (height(left) - height(right) > 1 && left != null) {
39
+ const pivot = left.right;
40
+ if (height(pivot) > height(left.left) && pivot != null) return node(pivot.key, pivot.entry, node(left.key, left.entry, left.left, pivot.left), node(key, entry, pivot.right, right));
41
+ return node(left.key, left.entry, left.left, node(key, entry, left.right, right));
42
+ }
43
+ if (height(right) - height(left) > 1 && right != null) {
44
+ const pivot = right.left;
45
+ if (height(pivot) > height(right.right) && pivot != null) return node(pivot.key, pivot.entry, node(key, entry, left, pivot.left), node(right.key, right.entry, pivot.right, right.right));
46
+ return node(right.key, right.entry, node(key, entry, left, right.left), right.right);
47
+ }
48
+ return node(key, entry, left, right);
49
+ }
50
+ function setEntry(root, key, entry) {
51
+ if (root == null) return node(key, entry, void 0, void 0);
52
+ if (key === root.key) return entry === root.entry ? root : {
53
+ ...root,
54
+ entry
55
+ };
56
+ if (key < root.key) {
57
+ const left = setEntry(root.left, key, entry);
58
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
59
+ }
60
+ const right = setEntry(root.right, key, entry);
61
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
62
+ }
63
+ function popMin(root) {
64
+ if (root.left == null) return [root, root.right];
65
+ const [minimum, left] = popMin(root.left);
66
+ return [minimum, balance(root.key, root.entry, left, root.right)];
67
+ }
68
+ function deleteEntry(root, key) {
69
+ if (root == null) return void 0;
70
+ if (key === root.key) {
71
+ if (root.left == null) return root.right;
72
+ if (root.right == null) return root.left;
73
+ const [successor, right$1] = popMin(root.right);
74
+ return balance(successor.key, successor.entry, root.left, right$1);
75
+ }
76
+ if (key < root.key) {
77
+ const left = deleteEntry(root.left, key);
78
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
79
+ }
80
+ const right = deleteEntry(root.right, key);
81
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
82
+ }
83
+ function inspectNode(root, lower, upper) {
84
+ if (root == null) return {
85
+ size: 0,
86
+ height: 0
87
+ };
88
+ if (lower !== void 0 && root.key <= lower || upper !== void 0 && root.key >= upper) throw new TypeError("Input trace keys are not strictly ordered.");
89
+ const left = inspectNode(root.left, lower, root.key);
90
+ const right = inspectNode(root.right, root.key, upper);
91
+ const actualHeight = 1 + Math.max(left.height, right.height);
92
+ if (root.height !== actualHeight || Math.abs(left.height - right.height) > 1) throw new TypeError("Input trace heights or balance are invalid.");
93
+ return {
94
+ size: 1 + left.size + right.size,
95
+ height: actualHeight
96
+ };
97
+ }
25
98
  var InputTraceImpl = class InputTraceImpl {
26
- #entries;
27
- constructor(entries) {
28
- this.#entries = entries ?? /* @__PURE__ */ new Map();
99
+ #root;
100
+ constructor(root) {
101
+ this.#root = root;
29
102
  }
30
103
  get(path) {
31
- return this.#entries.get(serializePath(path));
104
+ const key = serializePath(path);
105
+ let current = this.#root;
106
+ while (current != null) {
107
+ if (key === current.key) return current.entry;
108
+ current = key < current.key ? current.left : current.right;
109
+ }
110
+ return void 0;
32
111
  }
33
112
  set(path, entry) {
34
- const copy = new Map(this.#entries);
35
- copy.set(serializePath(path), entry);
36
- return new InputTraceImpl(copy);
113
+ return new InputTraceImpl(setEntry(this.#root, serializePath(path), entry));
37
114
  }
38
115
  delete(path) {
39
- const copy = new Map(this.#entries);
40
- copy.delete(serializePath(path));
41
- return new InputTraceImpl(copy);
116
+ return new InputTraceImpl(deleteEntry(this.#root, serializePath(path)));
117
+ }
118
+ static inspect(trace) {
119
+ if (!(trace instanceof InputTraceImpl)) throw new TypeError("Expected an Optique input trace.");
120
+ return inspectNode(trace.#root);
42
121
  }
43
122
  };
44
123
  /**
@@ -67,11 +67,14 @@ interface InputTrace {
67
67
  delete(path: readonly PropertyKey[]): InputTrace;
68
68
  }
69
69
  /**
70
- * Creates a new empty {@link InputTrace}.
70
+ * Checks private tree invariants without exposing mutable nodes.
71
+ * This module is not a package export; the checker is used by internal tests.
71
72
  *
72
- * @returns An empty immutable input trace.
73
+ * @param trace The trace to inspect.
74
+ * @returns Its size and verified height.
75
+ * @throws {TypeError} If the trace is foreign or its tree invariants are invalid.
73
76
  * @internal
74
- * @since 1.0.0
77
+ * @since 1.0.16
75
78
  */
76
79
  //#endregion
77
80
  export { InputTrace };
@@ -67,11 +67,14 @@ interface InputTrace {
67
67
  delete(path: readonly PropertyKey[]): InputTrace;
68
68
  }
69
69
  /**
70
- * Creates a new empty {@link InputTrace}.
70
+ * Checks private tree invariants without exposing mutable nodes.
71
+ * This module is not a package export; the checker is used by internal tests.
71
72
  *
72
- * @returns An empty immutable input trace.
73
+ * @param trace The trace to inspect.
74
+ * @returns Its size and verified height.
75
+ * @throws {TypeError} If the trace is foreign or its tree invariants are invalid.
73
76
  * @internal
74
- * @since 1.0.0
77
+ * @since 1.0.16
75
78
  */
76
79
  //#endregion
77
80
  export { InputTrace };
@@ -21,23 +21,102 @@ function serializePath(path) {
21
21
  if (path.length === 0) return "";
22
22
  return path.map(serializeKey).join("");
23
23
  }
24
+ function height(node$1) {
25
+ return node$1?.height ?? 0;
26
+ }
27
+ function node(key, entry, left, right) {
28
+ return {
29
+ key,
30
+ entry,
31
+ left,
32
+ right,
33
+ height: 1 + Math.max(height(left), height(right))
34
+ };
35
+ }
36
+ function balance(key, entry, left, right) {
37
+ if (height(left) - height(right) > 1 && left != null) {
38
+ const pivot = left.right;
39
+ if (height(pivot) > height(left.left) && pivot != null) return node(pivot.key, pivot.entry, node(left.key, left.entry, left.left, pivot.left), node(key, entry, pivot.right, right));
40
+ return node(left.key, left.entry, left.left, node(key, entry, left.right, right));
41
+ }
42
+ if (height(right) - height(left) > 1 && right != null) {
43
+ const pivot = right.left;
44
+ if (height(pivot) > height(right.right) && pivot != null) return node(pivot.key, pivot.entry, node(key, entry, left, pivot.left), node(right.key, right.entry, pivot.right, right.right));
45
+ return node(right.key, right.entry, node(key, entry, left, right.left), right.right);
46
+ }
47
+ return node(key, entry, left, right);
48
+ }
49
+ function setEntry(root, key, entry) {
50
+ if (root == null) return node(key, entry, void 0, void 0);
51
+ if (key === root.key) return entry === root.entry ? root : {
52
+ ...root,
53
+ entry
54
+ };
55
+ if (key < root.key) {
56
+ const left = setEntry(root.left, key, entry);
57
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
58
+ }
59
+ const right = setEntry(root.right, key, entry);
60
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
61
+ }
62
+ function popMin(root) {
63
+ if (root.left == null) return [root, root.right];
64
+ const [minimum, left] = popMin(root.left);
65
+ return [minimum, balance(root.key, root.entry, left, root.right)];
66
+ }
67
+ function deleteEntry(root, key) {
68
+ if (root == null) return void 0;
69
+ if (key === root.key) {
70
+ if (root.left == null) return root.right;
71
+ if (root.right == null) return root.left;
72
+ const [successor, right$1] = popMin(root.right);
73
+ return balance(successor.key, successor.entry, root.left, right$1);
74
+ }
75
+ if (key < root.key) {
76
+ const left = deleteEntry(root.left, key);
77
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
78
+ }
79
+ const right = deleteEntry(root.right, key);
80
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
81
+ }
82
+ function inspectNode(root, lower, upper) {
83
+ if (root == null) return {
84
+ size: 0,
85
+ height: 0
86
+ };
87
+ if (lower !== void 0 && root.key <= lower || upper !== void 0 && root.key >= upper) throw new TypeError("Input trace keys are not strictly ordered.");
88
+ const left = inspectNode(root.left, lower, root.key);
89
+ const right = inspectNode(root.right, root.key, upper);
90
+ const actualHeight = 1 + Math.max(left.height, right.height);
91
+ if (root.height !== actualHeight || Math.abs(left.height - right.height) > 1) throw new TypeError("Input trace heights or balance are invalid.");
92
+ return {
93
+ size: 1 + left.size + right.size,
94
+ height: actualHeight
95
+ };
96
+ }
24
97
  var InputTraceImpl = class InputTraceImpl {
25
- #entries;
26
- constructor(entries) {
27
- this.#entries = entries ?? /* @__PURE__ */ new Map();
98
+ #root;
99
+ constructor(root) {
100
+ this.#root = root;
28
101
  }
29
102
  get(path) {
30
- return this.#entries.get(serializePath(path));
103
+ const key = serializePath(path);
104
+ let current = this.#root;
105
+ while (current != null) {
106
+ if (key === current.key) return current.entry;
107
+ current = key < current.key ? current.left : current.right;
108
+ }
109
+ return void 0;
31
110
  }
32
111
  set(path, entry) {
33
- const copy = new Map(this.#entries);
34
- copy.set(serializePath(path), entry);
35
- return new InputTraceImpl(copy);
112
+ return new InputTraceImpl(setEntry(this.#root, serializePath(path), entry));
36
113
  }
37
114
  delete(path) {
38
- const copy = new Map(this.#entries);
39
- copy.delete(serializePath(path));
40
- return new InputTraceImpl(copy);
115
+ return new InputTraceImpl(deleteEntry(this.#root, serializePath(path)));
116
+ }
117
+ static inspect(trace) {
118
+ if (!(trace instanceof InputTraceImpl)) throw new TypeError("Expected an Optique input trace.");
119
+ return inspectNode(trace.#root);
41
120
  }
42
121
  };
43
122
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.16-dev.2975",
3
+ "version": "1.0.16-dev.2983",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",