package com.codepoetics.protonpack;
import java.util.Comparator;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Predicate;
class SkipUntilSpliterator<T> implements Spliterator<T> {
static <T> SkipUntilSpliterator<T> over(Spliterator<T> source, Predicate<T> condition) {
return new SkipUntilSpliterator<>(source, condition, false);
}
static <T> SkipUntilSpliterator<T> overInclusive(Spliterator<T> source, Predicate<T> condition) {
return new SkipUntilSpliterator<>(source, condition, true);
}
private final Spliterator<T> source;
private final Predicate<T> condition;
private final boolean inclusive;
private boolean conditionMet = false;
private SkipUntilSpliterator(Spliterator<T> source, Predicate<T> condition, boolean inclusive) {
this.source = source;
this.condition = condition;
this.inclusive = inclusive;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (conditionMet) {
return source.tryAdvance(action);
}
while (!conditionMet && source.tryAdvance(e -> {
if (condition.test(e)) {
if (!inclusive) {
action.accept(e);
}
conditionMet = true;
}
}));
return conditionMet;
}
@Override
public void forEachRemaining(Consumer<? super T> action) {
if (!conditionMet) {
tryAdvance(action);
}
if (conditionMet) {
source.forEachRemaining(action);
}
}
@Override
public Spliterator<T> trySplit() {
return null;
}
@Override
public long estimateSize() {
return conditionMet ? source.estimateSize() : Long.MAX_VALUE;
}
@Override
public int characteristics() {
return source.characteristics() &~ Spliterator.SIZED;
}
@Override
public Comparator<? super T> getComparator() {
return source.getComparator();
}
}