@mark1russell7/collections 0.9.1 → 0.9.3

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/build/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { compose as compose$1 } from "./core/layers.js";
2
+ import { _ as split, a as insert, b as summaryOf, c as locate, d as remove, f as search, g as splice, h as slice, i as height, l as of, m as size, n as at, o as isEmpty, p as set, r as concat$1, s as leaves, t as append, u as prepend, v as splitAt, x as toArray$2, y as summary } from "./functions.js";
2
3
  import { none as none$1, some as some$1, toOptional, tryCatch } from "@mark1russell7/optional";
3
4
  // src/core/policies.ts
4
5
  /**
@@ -3079,8 +3080,7 @@ var TreeSet = class TreeSet {
3079
3080
  return modified;
3080
3081
  }
3081
3082
  retainAll(elements) {
3082
- const toRetain = /* @__PURE__ */ new Set();
3083
- for (const element of elements) toRetain.add(element);
3083
+ const toRetain = this.setOf(elements);
3084
3084
  let modified = false;
3085
3085
  for (const element of Array.from(this)) if (!toRetain.has(element)) {
3086
3086
  this.remove(element);
@@ -3102,8 +3102,7 @@ var TreeSet = class TreeSet {
3102
3102
  compare: this._compare,
3103
3103
  eq: this._eq
3104
3104
  });
3105
- const otherSet = /* @__PURE__ */ new Set();
3106
- for (const element of other) otherSet.add(element);
3105
+ const otherSet = this.setOf(other);
3107
3106
  for (const element of this) if (otherSet.has(element)) result.add(element);
3108
3107
  return result;
3109
3108
  }
@@ -3112,8 +3111,7 @@ var TreeSet = class TreeSet {
3112
3111
  compare: this._compare,
3113
3112
  eq: this._eq
3114
3113
  });
3115
- const otherSet = /* @__PURE__ */ new Set();
3116
- for (const element of other) otherSet.add(element);
3114
+ const otherSet = this.setOf(other);
3117
3115
  for (const element of this) if (!otherSet.has(element)) result.add(element);
3118
3116
  return result;
3119
3117
  }
@@ -3123,16 +3121,27 @@ var TreeSet = class TreeSet {
3123
3121
  eq: this._eq
3124
3122
  });
3125
3123
  for (const element of this) result.add(element);
3126
- for (const element of other) if (result.has(element)) result.remove(element);
3124
+ for (const element of this.setOf(other)) if (result.has(element)) result.remove(element);
3127
3125
  else result.add(element);
3128
3126
  return result;
3129
3127
  }
3130
3128
  isSubsetOf(other) {
3131
- const otherSet = /* @__PURE__ */ new Set();
3132
- for (const element of other) otherSet.add(element);
3129
+ const otherSet = this.setOf(other);
3133
3130
  for (const element of this) if (!otherSet.has(element)) return false;
3134
3131
  return true;
3135
3132
  }
3133
+ /**
3134
+ * This method makes a set of the elements, with the comparator and the equality of this set.
3135
+ * Before, the set operations used a native `Set`, which compares with `===` and ignores the comparator.
3136
+ */
3137
+ setOf(elements) {
3138
+ const set = new TreeSet({
3139
+ compare: this._compare,
3140
+ eq: this._eq
3141
+ });
3142
+ for (const element of elements) set.add(element);
3143
+ return set;
3144
+ }
3136
3145
  isSupersetOf(other) {
3137
3146
  for (const element of other) if (!this.has(element)) return false;
3138
3147
  return true;
@@ -3633,9 +3642,11 @@ const PRESENT = Symbol("PRESENT");
3633
3642
  var HashSet = class HashSet {
3634
3643
  _map;
3635
3644
  _eq;
3645
+ _hash;
3636
3646
  constructor(options = {}) {
3637
3647
  const { initialCapacity = 16, loadFactor = .75, eq = defaultEq, hash = defaultHash } = options;
3638
3648
  this._eq = eq;
3649
+ this._hash = hash;
3639
3650
  this._map = new HashMap({
3640
3651
  initialCapacity,
3641
3652
  loadFactor,
@@ -3674,16 +3685,9 @@ var HashSet = class HashSet {
3674
3685
  return modified;
3675
3686
  }
3676
3687
  retainAll(other) {
3677
- const toRetain = new globalThis.Set(other);
3688
+ const toRetain = this.setOf(other);
3678
3689
  const toRemove = [];
3679
- for (const element of this) {
3680
- let shouldRetain = false;
3681
- for (const retainElement of toRetain) if (this._eq(element, retainElement)) {
3682
- shouldRetain = true;
3683
- break;
3684
- }
3685
- if (!shouldRetain) toRemove.push(element);
3686
- }
3690
+ for (const element of this) if (!toRetain.contains(element)) toRemove.push(element);
3687
3691
  let modified = false;
3688
3692
  for (const element of toRemove) {
3689
3693
  this.remove(element);
@@ -3712,11 +3716,9 @@ var HashSet = class HashSet {
3712
3716
  * The new set contains only elements present in both sets.
3713
3717
  */
3714
3718
  intersection(other) {
3715
- const result = new HashSet({ eq: this._eq });
3716
- for (const element of this) for (const otherElement of other) if (this._eq(element, otherElement)) {
3717
- result.add(element);
3718
- break;
3719
- }
3719
+ const others = this.setOf(other);
3720
+ const result = this.empty();
3721
+ for (const element of this) if (others.contains(element)) result.add(element);
3720
3722
  return result;
3721
3723
  }
3722
3724
  /**
@@ -3733,8 +3735,9 @@ var HashSet = class HashSet {
3733
3735
  * The new set contains elements in either set but not in both.
3734
3736
  */
3735
3737
  symmetricDifference(other) {
3736
- const result = this.union(other);
3737
- const inter = this.intersection(other);
3738
+ const others = this.setOf(other);
3739
+ const result = this.union(others);
3740
+ const inter = this.intersection(others);
3738
3741
  result.removeAll(inter);
3739
3742
  return result;
3740
3743
  }
@@ -3743,8 +3746,7 @@ var HashSet = class HashSet {
3743
3746
  * All elements in this set are also in the other set.
3744
3747
  */
3745
3748
  isSubsetOf(other) {
3746
- const otherSet = new HashSet({ eq: this._eq });
3747
- otherSet.addAll(other);
3749
+ const otherSet = this.setOf(other);
3748
3750
  for (const element of this) if (!otherSet.contains(element)) return false;
3749
3751
  return true;
3750
3752
  }
@@ -3777,9 +3779,23 @@ var HashSet = class HashSet {
3777
3779
  * This method makes a shallow copy of this set.
3778
3780
  */
3779
3781
  clone() {
3780
- const clone = new HashSet({ eq: this._eq });
3781
- clone.addAll(this);
3782
- return clone;
3782
+ return this.setOf(this);
3783
+ }
3784
+ /**
3785
+ * This method makes an empty set with the equality and the hash function of this set.
3786
+ * Before, the inner sets kept only the equality, so they did not find an element with a custom hash.
3787
+ */
3788
+ empty() {
3789
+ return new HashSet({
3790
+ eq: this._eq,
3791
+ hash: this._hash
3792
+ });
3793
+ }
3794
+ /** This method makes a set of the elements, with the equality and the hash function of this set. */
3795
+ setOf(elements) {
3796
+ const set = this.empty();
3797
+ set.addAll(elements);
3798
+ return set;
3783
3799
  }
3784
3800
  /**
3785
3801
  * This method gives statistics about the underlying hash table.
@@ -4060,283 +4076,81 @@ function priorityQueue(optionsOrElementsOrComparator) {
4060
4076
  return new PriorityQueue(optionsOrElementsOrComparator);
4061
4077
  }
4062
4078
  // src/impl/summary-tree.ts
4063
- function heightOf(tree) {
4064
- return tree === null ? 0 : tree.height;
4065
- }
4066
- function sizeOf(tree) {
4067
- return tree === null ? 0 : tree.size;
4068
- }
4069
- /** The functions that make and join nodes for one monoid. */
4070
- var Builder = class {
4071
- spec;
4072
- constructor(spec) {
4073
- this.spec = spec;
4074
- }
4075
- summaryOf(tree) {
4076
- return tree === null ? this.spec.monoid.empty : tree.summary;
4077
- }
4078
- /** This function makes a node. Give `inner` only when it is the summary of `left` and `own`, to save one `combine`. */
4079
- node(left, leaf, own, right, inner) {
4080
- if (inner === void 0) inner = left === null ? own : this.spec.monoid.combine(left.summary, own);
4081
- return {
4082
- left,
4083
- leaf,
4084
- own,
4085
- inner,
4086
- right,
4087
- height: 1 + Math.max(heightOf(left), heightOf(right)),
4088
- size: sizeOf(left) + 1 + sizeOf(right),
4089
- summary: right === null ? inner : this.spec.monoid.combine(inner, right.summary)
4090
- };
4091
- }
4092
- /** This function copies a node with a new right subtree. It keeps the summary `inner`, so it calls `combine` once at most. */
4093
- withRight(n, right) {
4094
- return this.node(n.left, n.leaf, n.own, right, n.inner);
4095
- }
4096
- rotateLeft(n) {
4097
- const r = n.right;
4098
- return this.node(this.withRight(n, r.left), r.leaf, r.own, r.right);
4099
- }
4100
- rotateRight(n) {
4101
- const l = n.left;
4102
- return this.withRight(l, this.node(l.right, n.leaf, n.own, n.right));
4103
- }
4104
- /** This function joins a tree that is higher by more than 1 with a leaf and a lower tree on its right. */
4105
- joinRight(left, leaf, own, right) {
4106
- const c = left.right;
4107
- if (heightOf(c) <= heightOf(right) + 1) {
4108
- const t = this.node(c, leaf, own, right);
4109
- if (t.height <= heightOf(left.left) + 1) return this.withRight(left, t);
4110
- return this.rotateLeft(this.withRight(left, this.rotateRight(t)));
4111
- }
4112
- const t = this.joinRight(c, leaf, own, right);
4113
- const joined = this.withRight(left, t);
4114
- return t.height <= heightOf(left.left) + 1 ? joined : this.rotateLeft(joined);
4115
- }
4116
- /** This function joins a lower tree on the left with a leaf and a tree that is higher by more than 1. */
4117
- joinLeft(left, leaf, own, right, inner) {
4118
- const c = right.left;
4119
- if (heightOf(c) <= heightOf(left) + 1) {
4120
- const t = this.node(left, leaf, own, c, inner);
4121
- if (t.height <= heightOf(right.right) + 1) return this.node(t, right.leaf, right.own, right.right);
4122
- return this.rotateRight(this.node(this.rotateLeft(t), right.leaf, right.own, right.right));
4123
- }
4124
- const t = this.joinLeft(left, leaf, own, c, inner);
4125
- const joined = this.node(t, right.leaf, right.own, right.right);
4126
- return t.height <= heightOf(right.right) + 1 ? joined : this.rotateRight(joined);
4127
- }
4128
- /**
4129
- * This function gives the tree of the leaves of `left`, then `leaf`, then the leaves of `right`. Give `inner` only
4130
- * when it is the summary of `left` and `own`.
4131
- */
4132
- join(left, leaf, own, right, inner) {
4133
- if (heightOf(left) > heightOf(right) + 1) return this.joinRight(left, leaf, own, right);
4134
- if (heightOf(right) > heightOf(left) + 1) return this.joinLeft(left, leaf, own, right, inner);
4135
- return this.node(left, leaf, own, right, inner);
4136
- }
4137
- /** This function removes the last leaf of a tree, and gives the rest and the node of that leaf. */
4138
- splitLast(tree) {
4139
- if (tree.right === null) return [tree.left, tree];
4140
- const [rest, last] = this.splitLast(tree.right);
4141
- return [this.join(tree.left, tree.leaf, tree.own, rest, tree.inner), last];
4142
- }
4143
- concat(left, right) {
4144
- if (left === null) return right;
4145
- if (right === null) return left;
4146
- const [rest, last] = this.splitLast(left);
4147
- return this.join(rest, last.leaf, last.own, right);
4148
- }
4149
- /** This function splits a tree into its first `index` leaves and the other leaves. */
4150
- splitAt(tree, index) {
4151
- if (tree === null) return [null, null];
4152
- const before = sizeOf(tree.left);
4153
- if (index <= before) {
4154
- const [a, b] = this.splitAt(tree.left, index);
4155
- return [a, this.join(b, tree.leaf, tree.own, tree.right)];
4156
- }
4157
- const [a, b] = this.splitAt(tree.right, index - before - 1);
4158
- return [this.join(tree.left, tree.leaf, tree.own, a, tree.inner), b];
4159
- }
4160
- /** This function splits a tree before the first leaf whose prefix summary, after `acc`, satisfies the predicate. */
4161
- splitBy(tree, predicate, acc) {
4162
- if (tree === null) return [null, null];
4163
- const { combine } = this.spec.monoid;
4164
- const throughLeft = tree.left === null ? acc : combine(acc, tree.left.summary);
4165
- if (tree.left !== null && predicate(throughLeft)) {
4166
- const [a, b] = this.splitBy(tree.left, predicate, acc);
4167
- return [a, this.join(b, tree.leaf, tree.own, tree.right)];
4168
- }
4169
- const throughLeaf = combine(throughLeft, tree.own);
4170
- if (predicate(throughLeaf)) return [tree.left, this.join(null, tree.leaf, tree.own, tree.right)];
4171
- const [a, b] = this.splitBy(tree.right, predicate, throughLeaf);
4172
- return [this.join(tree.left, tree.leaf, tree.own, a, tree.inner), b];
4173
- }
4174
- /** This function replaces the leaf at an index in the tree. It copies only the path to the leaf. */
4175
- replaceAt(tree, index, leaf, own) {
4176
- const before = sizeOf(tree.left);
4177
- if (index === before) return this.node(tree.left, leaf, own, tree.right);
4178
- if (index < before) return this.node(this.replaceAt(tree.left, index, leaf, own), tree.leaf, tree.own, tree.right);
4179
- return this.withRight(tree, this.replaceAt(tree.right, index - before - 1, leaf, own));
4180
- }
4181
- /** This function puts one leaf before the leaf at an index. It copies only the path, and `join` keeps the balance. */
4182
- insertAt(tree, index, leaf, own) {
4183
- if (tree === null) return this.node(null, leaf, own, null);
4184
- const before = sizeOf(tree.left);
4185
- if (index <= before) return this.join(this.insertAt(tree.left, index, leaf, own), tree.leaf, tree.own, tree.right);
4186
- return this.join(tree.left, tree.leaf, tree.own, this.insertAt(tree.right, index - before - 1, leaf, own), tree.inner);
4187
- }
4188
- /**
4189
- * This function replaces the leaf at an index with one or more leaves. It descends once.
4190
- * At the node of the leaf, it puts the first new leaf in the node.
4191
- * It puts the other new leaves at the start of the right subtree of that node.
4192
- */
4193
- replaceSpan(tree, index, leaves) {
4194
- const before = sizeOf(tree.left);
4195
- if (index < before) return this.join(this.replaceSpan(tree.left, index, leaves), tree.leaf, tree.own, tree.right);
4196
- if (index > before) return this.join(tree.left, tree.leaf, tree.own, this.replaceSpan(tree.right, index - before - 1, leaves), tree.inner);
4197
- let right = tree.right;
4198
- for (let i = 1; i < leaves.length; i++) right = this.insertAt(right, i - 1, leaves[i], this.spec.measure(leaves[i]));
4199
- return this.join(tree.left, leaves[0], this.spec.measure(leaves[0]), right);
4200
- }
4201
- /** This function removes the leaf at an index. It copies only the path, and `join` keeps the balance. */
4202
- removeAt(tree, index) {
4203
- const before = sizeOf(tree.left);
4204
- if (index === before) return this.concat(tree.left, tree.right);
4205
- if (index < before) return this.join(this.removeAt(tree.left, index), tree.leaf, tree.own, tree.right);
4206
- return this.join(tree.left, tree.leaf, tree.own, this.removeAt(tree.right, index - before - 1), tree.inner);
4207
- }
4208
- /** This function gives the leaf at an index of the tree. The index must be in the tree. */
4209
- leafAt(tree, index) {
4210
- let node = tree;
4211
- for (;;) {
4212
- const before = sizeOf(node.left);
4213
- if (index === before) return node.leaf;
4214
- if (index < before) node = node.left;
4215
- else {
4216
- index -= before + 1;
4217
- node = node.right;
4218
- }
4219
- }
4220
- }
4221
- /** This function joins the leaves at `index` and `index + 1` when `spec.merge` gives one leaf for them. */
4222
- seam(tree, index) {
4223
- const { merge } = this.spec;
4224
- if (merge === void 0 || tree === null || index < 0 || index + 1 >= tree.size) return tree;
4225
- const merged = merge(this.leafAt(tree, index), this.leafAt(tree, index + 1));
4226
- if (merged === void 0) return tree;
4227
- return this.removeAt(this.replaceAt(tree, index, merged, this.spec.measure(merged)), index + 1);
4228
- }
4229
- /** This function makes a balanced tree of the leaves `items[lo]` to `items[hi - 1]`. */
4230
- build(items, lo, hi) {
4231
- if (lo >= hi) return null;
4232
- const mid = lo + hi >>> 1;
4233
- const leaf = items[mid];
4234
- return this.node(this.build(items, lo, mid), leaf, this.spec.measure(leaf), this.build(items, mid + 1, hi));
4235
- }
4236
- };
4237
- /** The largest number of removed and inserted leaves for which `splice` copies paths instead of splitting the tree. */
4238
- const SMALL_EDIT = 8;
4239
- /** The builders of each spec. Each spec has one builder, so that two trees of the same spec can be joined. */
4240
- const builders = /* @__PURE__ */ new WeakMap();
4241
- function builderOf(spec) {
4242
- let builder = builders.get(spec);
4243
- if (builder === void 0) {
4244
- builder = new Builder(spec);
4245
- builders.set(spec, builder);
4246
- }
4247
- return builder;
4248
- }
4249
- function* walk(tree) {
4250
- const stack = [];
4251
- let node = tree;
4252
- while (node !== null || stack.length > 0) {
4253
- while (node !== null) {
4254
- stack.push(node);
4255
- node = node.left;
4256
- }
4257
- const top = stack.pop();
4258
- yield top.leaf;
4259
- node = top.right;
4260
- }
4261
- }
4262
- /** This function gives the index of a leaf, with a negative index counted from the end, or -1 when it is not in the tree. */
4263
- function indexOf(index, size) {
4264
- if (!Number.isInteger(index)) return -1;
4265
- const at = index < 0 ? size + index : index;
4266
- return at >= 0 && at < size ? at : -1;
4267
- }
4268
- function clamp$1(value, size) {
4269
- if (Number.isNaN(value)) return 0;
4270
- const whole = Math.trunc(value);
4271
- return whole < 0 ? Math.max(0, size + whole) : Math.min(whole, size);
4272
- }
4079
+ /**
4080
+ * SummaryTree: the class form of the summary tree, a persistent sequence of leaves with a summary of each part.
4081
+ *
4082
+ * The class wraps the plain functions of the entry `@mark1russell7/collections/summary-tree`. Its `record` is the
4083
+ * plain record that those functions take. A bundle that uses the class keeps each of its methods, so a program that
4084
+ * calls only a few operations imports the functions instead.
4085
+ *
4086
+ * @example
4087
+ * // The number of leaves and the total length of the strings
4088
+ * const spec = {
4089
+ * monoid: { empty: { count: 0, length: 0 }, combine: (a, b) => ({ count: a.count + b.count, length: a.length + b.length }) },
4090
+ * measure: (leaf: string) => ({ count: 1, length: leaf.length }),
4091
+ * };
4092
+ * const tree = summaryTree(spec, ["ab", "cde", "f"]);
4093
+ * tree.summary; // { count: 3, length: 6 }
4094
+ * const [left, right] = tree.split((prefix) => prefix.length > 2); // left: ["ab"], right: ["cde", "f"]
4095
+ */
4273
4096
  /**
4274
4097
  * A persistent sequence of leaves with a summary of each part. Make one with `summaryTree`. Each method that changes
4275
4098
  * the sequence gives a new tree.
4276
4099
  */
4277
4100
  var SummaryTree = class SummaryTree {
4278
- builder;
4279
- root;
4280
- constructor(builder, root) {
4281
- this.builder = builder;
4282
- this.root = root;
4101
+ /** The plain record of the tree: its spec and its root. The functions of the entry `./summary-tree` take it. */
4102
+ record;
4103
+ constructor(record) {
4104
+ this.record = record;
4283
4105
  }
4284
4106
  /** This function makes a tree of a spec from leaves, as `summaryTree` does. */
4285
4107
  static of(spec, leaves = []) {
4286
- const builder = builderOf(spec);
4287
- const items = [...leaves];
4288
- return new SummaryTree(builder, builder.build(items, 0, items.length));
4108
+ return new SummaryTree(of(spec, leaves));
4289
4109
  }
4290
- wrap(root) {
4291
- return root === this.root ? this : new SummaryTree(this.builder, root);
4110
+ /** This function wraps a plain record of the entry `./summary-tree` in a tree. It does not copy the nodes. */
4111
+ static fromRecord(record) {
4112
+ return new SummaryTree(record);
4292
4113
  }
4293
- treeOf(leaves) {
4294
- if (leaves instanceof SummaryTree) {
4295
- if (leaves.builder !== this.builder) throw new TypeError("SummaryTree: the two trees have different specs");
4296
- return leaves.root;
4297
- }
4298
- const items = [...leaves];
4299
- return this.builder.build(items, 0, items.length);
4114
+ wrap(record) {
4115
+ return record === this.record ? this : new SummaryTree(record);
4300
4116
  }
4301
4117
  /** The spec of the tree: its monoid and its measure. */
4302
4118
  get spec() {
4303
- return this.builder.spec;
4119
+ return this.record.spec;
4304
4120
  }
4305
4121
  /** The number of leaves. */
4306
4122
  get size() {
4307
- return sizeOf(this.root);
4123
+ return size(this.record);
4308
4124
  }
4309
4125
  get isEmpty() {
4310
- return this.root === null;
4126
+ return isEmpty(this.record);
4311
4127
  }
4312
4128
  /** The summary of all the leaves, in their order. An empty tree has the summary `monoid.empty`. */
4313
4129
  get summary() {
4314
- return this.builder.summaryOf(this.root);
4130
+ return summary(this.record);
4315
4131
  }
4316
4132
  /** The height of the tree: 0 for an empty tree. The height is at most 1.45 log2(size + 2). */
4317
4133
  get height() {
4318
- return heightOf(this.root);
4134
+ return height(this.record);
4319
4135
  }
4320
4136
  /**
4321
4137
  * This function gives the leaf at an index, or `undefined` when the index is not in the tree. A negative index counts
4322
4138
  * from the end, as `Array.prototype.at` does.
4323
4139
  */
4324
4140
  at(index) {
4325
- index = indexOf(index, this.size);
4326
- return index === -1 ? void 0 : this.builder.leafAt(this.root, index);
4141
+ return at(this.record, index);
4327
4142
  }
4328
4143
  /** This function gives the summary of the leaves from `start` to `end`, with `end` not included. */
4329
4144
  summaryOf(start = 0, end = this.size) {
4330
- return this.slice(start, end).summary;
4145
+ return summaryOf(this.record, start, end);
4331
4146
  }
4332
4147
  /** This function gives the tree of the leaves of this tree, then the leaves of `other`. The two trees must have the same spec. */
4333
4148
  concat(other) {
4334
- const joined = this.builder.concat(this.root, this.treeOf(other));
4335
- return this.wrap(this.builder.seam(joined, this.size - 1));
4149
+ return this.wrap(concat$1(this.record, recordOf(other)));
4336
4150
  }
4337
4151
  /** This function splits the tree into its first `index` leaves and the other leaves. */
4338
4152
  splitAt(index) {
4339
- const [left, right] = this.builder.splitAt(this.root, clamp$1(index, this.size));
4153
+ const [left, right] = splitAt(this.record, index);
4340
4154
  return [this.wrap(left), this.wrap(right)];
4341
4155
  }
4342
4156
  /**
@@ -4345,7 +4159,7 @@ var SummaryTree = class SummaryTree {
4345
4159
  * prefix. When no prefix satisfies it, the right tree is empty.
4346
4160
  */
4347
4161
  split(predicate) {
4348
- const [left, right] = this.builder.splitBy(this.root, predicate, this.builder.spec.monoid.empty);
4162
+ const [left, right] = split(this.record, predicate);
4349
4163
  return [this.wrap(left), this.wrap(right)];
4350
4164
  }
4351
4165
  /**
@@ -4353,27 +4167,7 @@ var SummaryTree = class SummaryTree {
4353
4167
  * nothing. It gives `undefined` when no prefix satisfies the predicate.
4354
4168
  */
4355
4169
  search(predicate) {
4356
- const { combine } = this.builder.spec.monoid;
4357
- let node = this.root;
4358
- let acc = this.builder.spec.monoid.empty;
4359
- let index = 0;
4360
- while (node !== null) {
4361
- const throughLeft = node.left === null ? acc : combine(acc, node.left.summary);
4362
- if (node.left !== null && predicate(throughLeft)) {
4363
- node = node.left;
4364
- continue;
4365
- }
4366
- const through = combine(throughLeft, node.own);
4367
- if (predicate(through)) return {
4368
- index: index + sizeOf(node.left),
4369
- leaf: node.leaf,
4370
- before: throughLeft,
4371
- through
4372
- };
4373
- index += sizeOf(node.left) + 1;
4374
- acc = through;
4375
- node = node.right;
4376
- }
4170
+ return search(this.record, predicate);
4377
4171
  }
4378
4172
  /**
4379
4173
  * This function finds the leaf that holds a position of an additive key, and it calls no `combine`. The key must be
@@ -4386,80 +4180,26 @@ var SummaryTree = class SummaryTree {
4386
4180
  * const at = rope.locate((s) => s.length, 1000);
4387
4181
  */
4388
4182
  locate(key, target) {
4389
- if (!(target >= 0)) return void 0;
4390
- let node = this.root;
4391
- let index = 0;
4392
- let rest = target;
4393
- while (node !== null) {
4394
- if (node.left !== null) {
4395
- const left = key(node.left.summary);
4396
- if (rest < left) {
4397
- node = node.left;
4398
- continue;
4399
- }
4400
- rest -= left;
4401
- index += node.left.size;
4402
- }
4403
- const own = key(node.own);
4404
- if (rest < own) return {
4405
- index,
4406
- leaf: node.leaf,
4407
- offset: rest
4408
- };
4409
- rest -= own;
4410
- index += 1;
4411
- node = node.right;
4412
- }
4183
+ return locate(this.record, key, target);
4413
4184
  }
4414
4185
  /** This function gives the tree of the leaves from `start` to `end`, with `end` not included. A negative index counts from the end. */
4415
4186
  slice(start = 0, end = this.size) {
4416
- const from = clamp$1(start, this.size);
4417
- const to = clamp$1(end, this.size);
4418
- if (to <= from) return this.wrap(null);
4419
- const [, rest] = this.builder.splitAt(this.root, from);
4420
- const [middle] = this.builder.splitAt(rest, to - from);
4421
- return this.wrap(middle);
4187
+ return this.wrap(slice(this.record, start, end));
4422
4188
  }
4423
4189
  /**
4424
4190
  * This function removes `deleteCount` leaves at `start` and puts the leaves of `inserted` there, as
4425
4191
  * `Array.prototype.splice` does. It gives the new tree, not the removed leaves.
4426
4192
  */
4427
4193
  splice(start, deleteCount = this.size, inserted = []) {
4428
- const from = clamp$1(start, this.size);
4429
- const count = Math.max(0, Math.min(Number.isNaN(deleteCount) ? 0 : Math.trunc(deleteCount), this.size - from));
4430
- const builder = this.builder;
4431
- const leaves = inserted instanceof SummaryTree ? void 0 : [...inserted];
4432
- const added = leaves === void 0 ? inserted.size : leaves.length;
4433
- if (count === 0 && added === 0) return this;
4434
- let root = this.root;
4435
- if (leaves !== void 0 && count + added <= SMALL_EDIT) {
4436
- const replaced = Math.min(count, added);
4437
- if (count > 0 && added > count) {
4438
- for (let i = 0; i < count - 1; i++) root = builder.replaceAt(root, from + i, leaves[i], builder.spec.measure(leaves[i]));
4439
- root = builder.replaceSpan(root, from + count - 1, leaves.slice(count - 1));
4440
- } else for (let i = 0; i < added; i++) {
4441
- const leaf = leaves[i];
4442
- const own = builder.spec.measure(leaf);
4443
- root = i < replaced ? builder.replaceAt(root, from + i, leaf, own) : builder.insertAt(root, from + i, leaf, own);
4444
- }
4445
- for (let i = replaced; i < count; i++) root = builder.removeAt(root, from + added);
4446
- } else {
4447
- const middle = leaves === void 0 ? this.treeOf(inserted) : builder.build(leaves, 0, leaves.length);
4448
- const [left, rest] = builder.splitAt(root, from);
4449
- const [, right] = builder.splitAt(rest, count);
4450
- root = builder.concat(builder.concat(left, middle), right);
4451
- }
4452
- if (added > 0) root = builder.seam(root, from + added - 1);
4453
- return this.wrap(builder.seam(root, from - 1));
4194
+ return this.wrap(splice(this.record, start, deleteCount, recordOf(inserted)));
4454
4195
  }
4455
4196
  /** This function puts the leaves of `inserted` before the leaf at `index`. */
4456
4197
  insert(index, inserted) {
4457
- return this.splice(index, 0, inserted);
4198
+ return this.wrap(insert(this.record, index, recordOf(inserted)));
4458
4199
  }
4459
4200
  /** This function removes the leaves from `start` to `end`, with `end` not included. */
4460
4201
  remove(start, end = this.size) {
4461
- const from = clamp$1(start, this.size);
4462
- return this.splice(from, Math.max(0, clamp$1(end, this.size) - from));
4202
+ return this.wrap(remove(this.record, start, end));
4463
4203
  }
4464
4204
  /**
4465
4205
  * This function replaces the leaf at an index. A negative index counts from the end, as `Array.prototype.with` does.
@@ -4467,27 +4207,29 @@ var SummaryTree = class SummaryTree {
4467
4207
  * `spec.merge`.
4468
4208
  */
4469
4209
  set(index, leaf) {
4470
- const at = indexOf(index, this.size);
4471
- return at === -1 ? this : this.wrap(this.builder.replaceAt(this.root, at, leaf, this.builder.spec.measure(leaf)));
4210
+ return this.wrap(set(this.record, index, leaf));
4472
4211
  }
4473
4212
  /** This function adds leaves after the last leaf. */
4474
4213
  append(...leaves) {
4475
- return this.concat(leaves);
4214
+ return this.wrap(append(this.record, ...leaves));
4476
4215
  }
4477
4216
  /** This function adds leaves before the first leaf. */
4478
4217
  prepend(...leaves) {
4479
- const joined = this.builder.concat(this.treeOf(leaves), this.root);
4480
- return this.wrap(this.builder.seam(joined, leaves.length - 1));
4218
+ return this.wrap(prepend(this.record, ...leaves));
4481
4219
  }
4482
4220
  /** This function gives the leaves in their order. */
4483
4221
  [Symbol.iterator]() {
4484
- return walk(this.root);
4222
+ return leaves(this.record);
4485
4223
  }
4486
4224
  /** This function gives the leaves in an array. */
4487
4225
  toArray() {
4488
- return [...walk(this.root)];
4226
+ return toArray$2(this.record);
4489
4227
  }
4490
4228
  };
4229
+ /** This function gives the record of a tree, or the leaves when they are not a tree. */
4230
+ function recordOf(leaves) {
4231
+ return leaves instanceof SummaryTree ? leaves.record : leaves;
4232
+ }
4491
4233
  /**
4492
4234
  * This function makes a persistent tree of leaves with a summary of each part. Use the same `spec` object for each
4493
4235
  * tree that `concat` or `splice` joins.
@@ -4902,6 +4644,7 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
4902
4644
  "merge",
4903
4645
  "putAll",
4904
4646
  "pollOrUndefined",
4647
+ "deleteWhere",
4905
4648
  "ensureCapacity",
4906
4649
  "trimToSize",
4907
4650
  "grow",
@@ -4919,7 +4662,10 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
4919
4662
  "fixAfterInsertion",
4920
4663
  "fixAfterDeletion",
4921
4664
  "rotateLeft",
4922
- "rotateRight"
4665
+ "rotateRight",
4666
+ "moveToHead",
4667
+ "removeNode",
4668
+ "evictLRU"
4923
4669
  ]);
4924
4670
  /** Methods that return a view of the collection: the view is readonly too. */
4925
4671
  const VIEW_METHODS = /* @__PURE__ */ new Set([