public final @NotNull JBIterable<@NotNull JBIterable<E>> split(@NotNull Split mode, @NotNull Condition<? super E> separator) {
    return intercept(orig -> {
      Condition<? super E> condition = Stateful.copy(separator);
      return new JBIterator<JBIterable<E>>() {
        JBIterator<E> it;
        E stored;
        int st; // encode transitions: -2:sep->sep, -1:val->sep, 1:sep->val, 2:val->val

        @Override
        protected JBIterable<E> nextImpl() {
          // iterate through the previous result fully before proceeding
          while (it != null && it.advance()) /* no-op */ ;
          it = null;
          // empty case: check hasNext() only if nothing is stored to be compatible with JBIterator#cursor()
          if (stored == null && !orig.hasNext()) {
            if (st < 0 && mode != Split.BEFORE && mode != Split.GROUP) {
              st = 1;
              return empty();
            }
            return stop();
          }
          // general case: add empty between 2 separators in KEEP mode; otherwise go with some state logic
          if (st == -2 && mode == Split.AROUND) {
            st = -1;
            return empty();
          }
          E tmp = stored;
          stored = null;
          return of(tmp).append(once((it = JBIterator.wrap(orig)).takeWhile(e -> {
            boolean sep = condition.value(e);
            int st0 = st;
            st = st0 < 0 && sep ? -2 : st0 > 0 && !sep ? 2 : sep ? -1 : 1;
            boolean result;
            switch (mode) {
              case AFTER:
                result = st != -2 && (st != 1 || st0 == 0);
                break;
              case BEFORE:
                result = st != -2 && st != -1;
                break;
              case AROUND:
                result = st0 >= 0 && st > 0;
                break;
              case GROUP:
                result = st0 >= 0 && st > 0 || st0 <= 0 && st < 0;
                break;
              case OFF:
                result = st > 0;
                break;
              default:
                throw new AssertionError(st);
            }
            stored = !result && mode != Split.OFF ? e : null;
            return result;
          })));
        }
      };
    });
  }
public final @NotNull JBIterable<@NotNull JBIterable<E>> split(@NotNull Split mode, @NotNull Condition<? super E> separator)