/*
* Copyright 2015, 2017 Tagir Valeev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package one.util.streamex;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.DoublePredicate;
import java.util.function.IntPredicate;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
* @author Tagir Valeev
*/
/* package */ class Java9Specific extends VersionSpecific {
private static final MethodHandle[][] JDK9_METHODS = initJdk9Methods();
private static final int IDX_STREAM = 0;
private static final int IDX_INT_STREAM = 1;
private static final int IDX_LONG_STREAM = 2;
private static final int IDX_DOUBLE_STREAM = 3;
private static final int IDX_TAKE_WHILE = 0;
private static final int IDX_DROP_WHILE = 1;
static MethodHandle[][] initJdk9Methods() {
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
MethodType[] types = {MethodType.methodType(Stream.class, Predicate.class),
MethodType.methodType(IntStream.class, IntPredicate.class),
MethodType.methodType(LongStream.class, LongPredicate.class),
MethodType.methodType(DoubleStream.class, DoublePredicate.class)};
MethodHandle[][] methods = new MethodHandle[types.length][];
try {
int i = 0;
for (MethodType type : types) {
methods[i++] = new MethodHandle[]{
lookup.findVirtual(type.returnType(), "takeWhile", type),
lookup.findVirtual(type.returnType(), "dropWhile", type)
};
}
} catch (NoSuchMethodException | IllegalAccessException e) {
return null;
}
return methods;
}
@Override
@SuppressWarnings("unchecked")
<T, S extends AbstractStreamEx<T, S>> S callWhile(AbstractStreamEx<T, S> stream, Predicate<? super T> predicate, boolean drop) {
try {
return stream.supply((Stream<T>) JDK9_METHODS[IDX_STREAM][drop ? IDX_DROP_WHILE : IDX_TAKE_WHILE]
.invokeExact(stream.stream(), predicate));
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new InternalError(e);
}
}
@Override
final IntStreamEx callWhile(IntStreamEx stream, IntPredicate predicate, boolean drop) {
try {
return new IntStreamEx((IntStream) JDK9_METHODS[IDX_INT_STREAM][drop ? IDX_DROP_WHILE : IDX_TAKE_WHILE]
.invokeExact(stream.stream(), predicate), stream.context);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new InternalError(e);
}
}
@Override
final LongStreamEx callWhile(LongStreamEx stream, LongPredicate predicate, boolean drop) {
try {
return new LongStreamEx((LongStream) JDK9_METHODS[IDX_LONG_STREAM][drop ? IDX_DROP_WHILE : IDX_TAKE_WHILE]
.invokeExact(stream.stream(), predicate), stream.context);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new InternalError(e);
}
}
@Override
final DoubleStreamEx callWhile(DoubleStreamEx stream, DoublePredicate predicate, boolean drop) {
try {
return new DoubleStreamEx((DoubleStream) JDK9_METHODS[IDX_DOUBLE_STREAM][drop ? IDX_DROP_WHILE : IDX_TAKE_WHILE]
.invokeExact(stream.stream(), predicate), stream.context);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new InternalError(e);
}
}
@Override
IntStream ofChars(CharSequence seq) {
return seq.chars();
}
}