@NotNull
  public static FairDiffIterable compare(@NotNull CharSequence text1,
                                         @NotNull CharSequence text2,
                                         @NotNull CancellationChecker indicator) {
    indicator.checkCanceled();

    int[] codePoints1 = getAllCodePoints(text1);
    int[] codePoints2 = getAllCodePoints(text2);

    FairDiffIterable iterable = diff(codePoints1, codePoints2, indicator);

    int offset1 = 0;
    int offset2 = 0;
    ChangeBuilder builder = new ChangeBuilder(text1.length(), text2.length());
    for (Pair<Range, Boolean> pair : iterateAll(iterable)) {
      Range range = pair.first;
      boolean equals = pair.second;

      int end1 = offset1 + countChars(codePoints1, range.start1, range.end1);
      int end2 = offset2 + countChars(codePoints2, range.start2, range.end2);

      if (equals) {
        builder.markEqual(offset1, offset2, end1, end2);
      }

      offset1 = end1;
      offset2 = end2;
    }
    assert offset1 == text1.length();
    assert offset2 == text2.length();

    return fair(builder.finish());
  }
@NotNull
  public static FairDiffIterable compare(@NotNull CharSequence text1,
                                         @NotNull CharSequence text2,
                                         @NotNull CancellationChecker indicator)