tryMergeDeleteSet = (ds, store) => {
  // try to merge deleted / gc'd items
  // merge from right to left for better efficiecy and so we don't miss any merge targets
  ds.clients.forEach((deleteItems, client) => {
    const structs =
    /** @type {Array<GC|Item>} */
    store.clients.get(client);

    for (let di = deleteItems.length - 1; di >= 0; di--) {
      const deleteItem = deleteItems[di]; // start with merging the item next to the last deleted item

      const mostRightIndexToCheck = math.min(structs.length - 1, 1 + findIndexSS(structs, deleteItem.clock + deleteItem.len - 1));

      for (let si = mostRightIndexToCheck, struct = structs[si]; si > 0 && struct.id.clock >= deleteItem.clock; struct = structs[--si]) {
        tryToMergeWithLeft(structs, si);
      }
    }
  });
}
@param {DeleteSet} ds
@param {StructStore} store