private static @NotNull CharSequence concatNodes(@NotNull CharSequence node1, @NotNull CharSequence node2) {
    // All Text instances are maintained balanced:
    //   (head < tail * 2) & (tail < head * 2)
    final int length = node1.length() + node2.length();
    if (length <= BLOCK_SIZE) { // Merges to primitive.
      // module is still targeted to Java 8, so plus-concatenation is compiled via StringBuilder
      // here concat() looks preferred
      //noinspection CallToStringConcatCanBeReplacedByOperator
      return node1.toString().concat(node2.toString());
    }

    // Returns a composite.
    CharSequence head = node1;
    CharSequence tail = node2;

    if (shouldRebalance(head, tail)) {
      // head too small, returns (head + tail/2) + (tail/2)
      do {
        if (((CompositeNode)tail).head.length() > ((CompositeNode)tail).tail.length()) {
          // Rotates to concatenate with smaller part.
          tail = ((CompositeNode)tail).rightRotation();
        }
        head = concatNodes(head, ((CompositeNode)tail).head);
        tail = ((CompositeNode)tail).tail;
      }
      while (shouldRebalance(head, tail));
    }
    else if (shouldRebalance(tail, head)) {
      // tail too small, returns (head/2) + (head/2 concat tail)
      do {
        if (((CompositeNode)head).tail.length() > ((CompositeNode)head).head.length()) {
          // Rotates to concatenate with smaller part.
          head = ((CompositeNode)head).leftRotation();
        }
        tail = concatNodes(((CompositeNode)head).tail, tail);
        head = ((CompositeNode)head).head;
      }
      while (shouldRebalance(tail, head));
    }
    return new CompositeNode(head, tail);
  }
private static @NotNull CharSequence concatNodes(@NotNull CharSequence node1, @NotNull CharSequence node2)