package xapi.fu;
import java.util.function.Function;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 07/11/15.
*/
@SuppressWarnings("unchecked") // yes, this api will let you do terrible things. Don't do terrible things.
public interface In1Out1<I, O> extends Rethrowable, Lambda {
O io(I in);
default O apply(Out1<I> supplier) {
return io(supplier.out1());
}
default int accept(int position, In1<O> callback, Object... values) {
final I in = (I) values[position++];
final O out = io(in);
callback.in(out);
return position;
}
default Function<I, O> toFunction() {
return this::io;
}
static <I, O> In1Out1<I, O> of(In1Out1<I, O> lambda) {
return lambda;
}
static <I, O> In1Out1<I, O> ofDeferred(Out1<O> supplier) {
return ignored->supplier.out1();
}
static <I, O> In1Out1<I, O> ofImmediate(Out1<O> supplier) {
return of(supplier.out1());
}
static <I, O> In1Out1<I, O> of(O value) {
return ignored->value;
}
static <I, O> In1Out1<I, O> of(In1<I> in, Out1<O> out) {
return i-> {
in.in(i);
@SuppressWarnings("redundant") // let debuggers have a look. JIT can inline
final O o = out.out1();
return o;
};
}
/**
* This method just exists to give you somewhere to create a lambda that will rethrow exceptions.
*/
static <I, O> In1Out1<I, O> unsafe(In1Out1Unsafe<I, O> of) {
return of;
}
default Out1<O> supply(I in) {
return () -> io(in);
}
default Out1<O> supplyDeferred(Out1<I> in) {
return () -> io(in.out1());
}
default Out1<O> supplyImmediate(Out1<I> in) {
return supply(in.out1());
}
default In1<I> adapt(In1<O> into) {
return i->into.in(io(i));
}
default In1<I> ignoreOutput() {
return this::io;
}
interface In1Out1Unsafe <I, O> extends In1Out1<I, O>, Rethrowable{
O ioUnsafe(I in) throws Throwable;
default O io(I in) {
try {
return this.ioUnsafe(in);
} catch (Throwable e) {
throw rethrow(e);
}
}
}
default <To> In1Out1<I,To> mapOut(In1Out1<O, To> mapper) {
return in-> {
final O o = this.io(in);
return mapper.io(o);
};
}
default <To> In1Out1<To,O> mapIn(In1Out1<To, I> mapper) {
return to-> {
final I i1 = mapper.io(to);
return this.io(i1);
};
}
static <I, T, O> In1Out1<I, O> ofMapped(In1Out1<I, T> mapper, In1Out1<T, O> job) {
return mapper.mapOut(job);
}
}