@FunctionalInterface
public interface RethrowChain<X extends Throwable, Y extends Throwable>
    extends Function<X, Optional<Y>> {
  public static <Y extends Throwable> RethrowChain<Throwable, Y> castTo(Class<? extends Y> clazz) {
    return e -> Optional.ofNullable(clazz.isInstance(e) ? clazz.cast(e) : null);
  }

  default public RethrowChain<X, Y> connect(RethrowChain<X, Y> link) {
    Objects.requireNonNull(link);
    return x -> {
      Optional<Y> y = apply(x);
      if (y.isPresent()) {
        return y;
      }

      return link.apply(x);
    };
  }

  default public <Z extends Throwable> RethrowChain<X, Z> rethrow(
      Function<? super Y, ? extends Z> mapper) {
    Objects.requireNonNull(mapper);
    return x -> apply(x).map(mapper);
  }

  default public Function<X, Y> finish() {
    return finish(x -> {
      throw new AssertionError(x);
    });
  }

  default public Function<X, Y> finish(Function<? super X, ? extends Y> unhandledException) {
    Objects.requireNonNull(unhandledException);
    return x -> {
      return apply(x).orElseGet(() -> {
        if (x instanceof RuntimeException) {
          throw (RuntimeException) x;
        } else if (x instanceof Error) {
          throw (Error) x;
        }

        return unhandledException.apply(x);
      });
    };
  }
} @FunctionalInterface
public interface ThrowingBiConsumer<T, U, X extends Throwable> {
  public void accept(T t, U u) throws X;

  default public BiConsumer<T, U> fallbackTo(BiConsumer<? super T, ? super U> fallback) {
    return fallbackTo(fallback, null);
  }

  default public BiConsumer<T, U> fallbackTo(BiConsumer<? super T, ? super U> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingBiConsumer<T, U, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingBiConsumer<T, U, Y>
      orTry(ThrowingBiConsumer<? super T, ? super U, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingBiConsumer<T, U, Y> orTry(
      ThrowingBiConsumer<? super T, ? super U, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (t, u) -> {
      ThrowingRunnable<X> s = () -> accept(t, u);
      s.orTry(() -> f.accept(t, u), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingBiConsumer<T, U, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t, u) -> {
      ThrowingRunnable<X> s = () -> accept(t, u);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingBiFunction<T, U, R, X extends Throwable> {
  public R apply(T t, U u) throws X;

  default public BiFunction<T, U, R>
      fallbackTo(BiFunction<? super T, ? super U, ? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public BiFunction<T, U, R> fallbackTo(
      BiFunction<? super T, ? super U, ? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingBiFunction<T, U, R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingBiFunction<T, U, R, Y>
      orTry(ThrowingBiFunction<? super T, ? super U, ? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingBiFunction<T, U, R, Y> orTry(
      ThrowingBiFunction<? super T, ? super U, ? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (t, u) -> {
      ThrowingSupplier<R, X> s = () -> apply(t, u);
      return s.orTry(() -> f.apply(t, u), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingBiFunction<T, U, R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t, u) -> {
      ThrowingSupplier<R, X> s = () -> apply(t, u);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingBinaryOperator<T, X extends Throwable>
    extends ThrowingBiFunction<T, T, T, X> {
  @Override
  default BiFunction<T, T, T> fallbackTo(BiFunction<? super T, ? super T, ? extends T> fallback) {
    return ThrowingBiFunction.super.fallbackTo(fallback)::apply;
  }

  @Override
  default BiFunction<T, T, T> fallbackTo(BiFunction<? super T, ? super T, ? extends T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    return ThrowingBiFunction.super.fallbackTo(fallback, thrown)::apply;
  }

  @Override
  default <Y extends Throwable> ThrowingBiFunction<T, T, T, Y> orTry(
      ThrowingBiFunction<? super T, ? super T, ? extends T, ? extends Y> f) {
    return ThrowingBiFunction.super.orTry(f)::apply;
  }

  @Override
  default <Y extends Throwable> ThrowingBiFunction<T, T, T, Y> orTry(
      ThrowingBiFunction<? super T, ? super T, ? extends T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return ThrowingBiFunction.super.orTry(f, thrown)::apply;
  }

  @Override
  default public <Y extends Throwable> ThrowingBinaryOperator<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return ThrowingBiFunction.super.rethrow(x, mapper)::apply;
  }
} @FunctionalInterface
public interface ThrowingComparator<T, X extends Throwable> {
  public int compare(T o1, T o2) throws X;

  default public Comparator<T> fallbackTo(Comparator<T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Comparator<T> fallbackTo(Comparator<T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingComparator<T, Nothing> t = fallback::compare;
    return orTry(t, thrown)::compare;
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> orTry(
      ThrowingComparator<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> orTry(
      ThrowingComparator<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (o1, o2) -> {
      ThrowingSupplier<Integer, X> s = () -> compare(o1, o2);
      return s.orTry(() -> f.compare(o1, o2), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingComparator<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (o1, o2) -> {
      ThrowingSupplier<Integer, X> s = () -> compare(o1, o2);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingConsumer<T, X extends Throwable> {
  public void accept(T t) throws X;

  default public Consumer<T> fallbackTo(Consumer<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Consumer<T> fallbackTo(Consumer<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingConsumer<T, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y>
      orTry(ThrowingConsumer<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y> orTry(
      ThrowingConsumer<? super T, ? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.orTry(() -> f.accept(t), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingConsumer<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleBinaryOperator<X extends Throwable> {
  public double applyAsDouble(double left, double right) throws X;

  default public DoubleBinaryOperator fallbackTo(DoubleBinaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleBinaryOperator fallbackTo(DoubleBinaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleBinaryOperator<Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingDoubleBinaryOperator<Y>
      orTry(ThrowingDoubleBinaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleBinaryOperator<Y> orTry(
      ThrowingDoubleBinaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return (t1, t2) -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t1, t2);
      return s.orTry(() -> f.applyAsDouble(t1, t2), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleBinaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t1, t2) -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t1, t2);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleConsumer<X extends Throwable> {
  void accept(double value) throws X;

  default public DoubleConsumer fallbackTo(DoubleConsumer fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleConsumer fallbackTo(DoubleConsumer fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleConsumer<Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingDoubleConsumer<Y>
      orTry(ThrowingDoubleConsumer<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleConsumer<Y>
      orTry(ThrowingDoubleConsumer<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.orTry(() -> f.accept(t), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleConsumer<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleFunction<R, X extends Throwable> {
  public R apply(double value) throws X;

  default public DoubleFunction<R> fallbackTo(DoubleFunction<? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleFunction<R> fallbackTo(DoubleFunction<? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleFunction<R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingDoubleFunction<R, Y>
      orTry(ThrowingDoubleFunction<? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleFunction<R, Y> orTry(
      ThrowingDoubleFunction<? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.orTry(() -> f.apply(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleFunction<R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.rethrow(x, mapper).get();
    };
  }

  default public <RR> ThrowingDoubleFunction<RR, X>
      andThen(ThrowingFunction<? super R, ? extends RR, ? extends X> after) {
    Objects.requireNonNull(after);
    return d -> after.apply(apply(d));
  }
} @FunctionalInterface
public interface ThrowingDoublePredicate<X extends Throwable> {
  public boolean test(double value) throws X;

  default public DoublePredicate fallbackTo(DoublePredicate fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoublePredicate fallbackTo(DoublePredicate fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoublePredicate<Nothing> t = fallback::test;
    return orTry(t, thrown)::test;
  }

  default public <Y extends Throwable> ThrowingDoublePredicate<Y>
      orTry(ThrowingDoublePredicate<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoublePredicate<Y>
      orTry(ThrowingDoublePredicate<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.orTry(() -> f.test(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoublePredicate<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleToIntFunction<X extends Throwable> {
  public int applyAsInt(double value) throws X;

  default public DoubleToIntFunction fallbackTo(DoubleToIntFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleToIntFunction fallbackTo(DoubleToIntFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleToIntFunction<Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingDoubleToIntFunction<Y>
      orTry(ThrowingDoubleToIntFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleToIntFunction<Y> orTry(
      ThrowingDoubleToIntFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.orTry(() -> f.applyAsInt(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleToIntFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleToLongFunction<X extends Throwable> {
  public long applyAsLong(double value) throws X;

  default public DoubleToLongFunction fallbackTo(DoubleToLongFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleToLongFunction fallbackTo(DoubleToLongFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleToLongFunction<Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingDoubleToLongFunction<Y>
      orTry(ThrowingDoubleToLongFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleToLongFunction<Y> orTry(
      ThrowingDoubleToLongFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.orTry(() -> f.applyAsLong(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleToLongFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingDoubleUnaryOperator<X extends Throwable> {
  public double applyAsDouble(double operand) throws X;

  default public DoubleUnaryOperator fallbackTo(DoubleUnaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public DoubleUnaryOperator fallbackTo(DoubleUnaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingDoubleUnaryOperator<Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingDoubleUnaryOperator<Y>
      orTry(ThrowingDoubleUnaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingDoubleUnaryOperator<Y> orTry(
      ThrowingDoubleUnaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.orTry(() -> f.applyAsDouble(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingDoubleUnaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingFunction<T, R, X extends Throwable> {
  public R apply(T t) throws X;

  default public Function<T, R> fallbackTo(Function<? super T, ? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Function<T, R> fallbackTo(Function<? super T, ? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingFunction<T, R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y>
      orTry(ThrowingFunction<? super T, ? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y> orTry(
      ThrowingFunction<? super T, ? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.orTry(() -> f.apply(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingFunction<T, R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.rethrow(x, mapper).get();
    };
  }

  default public <RR> ThrowingFunction<T, RR, X>
      andThen(ThrowingFunction<? super R, ? extends RR, ? extends X> after) {
    Objects.requireNonNull(after);
    return t -> after.apply(apply(t));
  }
} @FunctionalInterface
public interface ThrowingIntBinaryOperator<X extends Throwable> {
  public int applyAsInt(int left, int right) throws X;

  default public IntBinaryOperator fallbackTo(IntBinaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntBinaryOperator fallbackTo(IntBinaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntBinaryOperator<Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingIntBinaryOperator<Y>
      orTry(ThrowingIntBinaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntBinaryOperator<Y> orTry(
      ThrowingIntBinaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return (t1, t2) -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t1, t2);
      return s.orTry(() -> f.applyAsInt(t1, t2), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntBinaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t1, t2) -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t1, t2);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingIntConsumer<X extends Throwable> {
  void accept(int value) throws X;

  default public IntConsumer fallbackTo(IntConsumer fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntConsumer fallbackTo(IntConsumer fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntConsumer<Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingIntConsumer<Y>
      orTry(ThrowingIntConsumer<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntConsumer<Y>
      orTry(ThrowingIntConsumer<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.orTry(() -> f.accept(t), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingIntConsumer<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingIntFunction<R, X extends Throwable> {
  public R apply(int value) throws X;

  default public IntFunction<R> fallbackTo(IntFunction<? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntFunction<R> fallbackTo(IntFunction<? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntFunction<R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingIntFunction<R, Y>
      orTry(ThrowingIntFunction<? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntFunction<R, Y> orTry(
      ThrowingIntFunction<? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.orTry(() -> f.apply(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntFunction<R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.rethrow(x, mapper).get();
    };
  }

  default public <RR> ThrowingIntFunction<RR, X>
      andThen(ThrowingFunction<? super R, ? extends RR, ? extends X> after) {
    Objects.requireNonNull(after);
    return i -> after.apply(apply(i));
  }
} @FunctionalInterface
public interface ThrowingIntPredicate<X extends Throwable> {
  public boolean test(int value) throws X;

  default public IntPredicate fallbackTo(IntPredicate fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntPredicate fallbackTo(IntPredicate fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntPredicate<Nothing> t = fallback::test;
    return orTry(t, thrown)::test;
  }

  default public <Y extends Throwable> ThrowingIntPredicate<Y>
      orTry(ThrowingIntPredicate<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntPredicate<Y>
      orTry(ThrowingIntPredicate<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.orTry(() -> f.test(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntPredicate<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingIntToDoubleFunction<X extends Throwable> {
  public double applyAsDouble(int value) throws X;

  default public IntToDoubleFunction fallbackTo(IntToDoubleFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntToDoubleFunction fallbackTo(IntToDoubleFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntToDoubleFunction<Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingIntToDoubleFunction<Y>
      orTry(ThrowingIntToDoubleFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntToDoubleFunction<Y> orTry(
      ThrowingIntToDoubleFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.orTry(() -> f.applyAsDouble(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntToDoubleFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingIntToLongFunction<X extends Throwable> {
  public long applyAsLong(int value) throws X;

  default public IntToLongFunction fallbackTo(IntToLongFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntToLongFunction fallbackTo(IntToLongFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntToLongFunction<Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingIntToLongFunction<Y>
      orTry(ThrowingIntToLongFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntToLongFunction<Y> orTry(
      ThrowingIntToLongFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.orTry(() -> f.applyAsLong(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntToLongFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingIntUnaryOperator<X extends Throwable> {
  public int applyAsInt(int operand) throws X;

  default public IntUnaryOperator fallbackTo(IntUnaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public IntUnaryOperator fallbackTo(IntUnaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingIntUnaryOperator<Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingIntUnaryOperator<Y>
      orTry(ThrowingIntUnaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingIntUnaryOperator<Y>
      orTry(ThrowingIntUnaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.orTry(() -> f.applyAsInt(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingIntUnaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingLongBinaryOperator<X extends Throwable> {
  public long applyAsLong(long left, long right) throws X;

  default public LongBinaryOperator fallbackTo(LongBinaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongBinaryOperator fallbackTo(LongBinaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongBinaryOperator<Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingLongBinaryOperator<Y>
      orTry(ThrowingLongBinaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongBinaryOperator<Y> orTry(
      ThrowingLongBinaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return (t1, t2) -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t1, t2);
      return s.orTry(() -> f.applyAsLong(t1, t2), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongBinaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t1, t2) -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t1, t2);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingLongConsumer<X extends Throwable> {
  void accept(long value) throws X;

  default public LongConsumer fallbackTo(LongConsumer fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongConsumer fallbackTo(LongConsumer fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongConsumer<Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingLongConsumer<Y>
      orTry(ThrowingLongConsumer<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongConsumer<Y>
      orTry(ThrowingLongConsumer<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.orTry(() -> f.accept(t), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingLongConsumer<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingRunnable<X> s = () -> accept(t);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingLongFunction<R, X extends Throwable> {
  public R apply(long value) throws X;

  default public LongFunction<R> fallbackTo(LongFunction<? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongFunction<R> fallbackTo(LongFunction<? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongFunction<R, Nothing> t = fallback::apply;
    return orTry(t, thrown)::apply;
  }

  default public <Y extends Throwable> ThrowingLongFunction<R, Y>
      orTry(ThrowingLongFunction<? extends R, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongFunction<R, Y> orTry(
      ThrowingLongFunction<? extends R, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.orTry(() -> f.apply(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongFunction<R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<R, X> s = () -> apply(t);
      return s.rethrow(x, mapper).get();
    };
  }

  default public <RR> ThrowingLongFunction<RR, X>
      andThen(ThrowingFunction<? super R, ? extends RR, ? extends X> after) {
    Objects.requireNonNull(after);
    return l -> after.apply(apply(l));
  }
} @FunctionalInterface
public interface ThrowingLongPredicate<X extends Throwable> {
  public boolean test(long value) throws X;

  default public LongPredicate fallbackTo(LongPredicate fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongPredicate fallbackTo(LongPredicate fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongPredicate<Nothing> t = fallback::test;
    return orTry(t, thrown)::test;
  }

  default public <Y extends Throwable> ThrowingLongPredicate<Y>
      orTry(ThrowingLongPredicate<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongPredicate<Y>
      orTry(ThrowingLongPredicate<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.orTry(() -> f.test(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongPredicate<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingLongToDoubleFunction<X extends Throwable> {
  public double applyAsDouble(long value) throws X;

  default public LongToDoubleFunction fallbackTo(LongToDoubleFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongToDoubleFunction fallbackTo(LongToDoubleFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongToDoubleFunction<Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingLongToDoubleFunction<Y>
      orTry(ThrowingLongToDoubleFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongToDoubleFunction<Y> orTry(
      ThrowingLongToDoubleFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.orTry(() -> f.applyAsDouble(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongToDoubleFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingLongToIntFunction<X extends Throwable> {
  public int applyAsInt(long value) throws X;

  default public LongToIntFunction fallbackTo(LongToIntFunction fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongToIntFunction fallbackTo(LongToIntFunction fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongToIntFunction<Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingLongToIntFunction<Y>
      orTry(ThrowingLongToIntFunction<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongToIntFunction<Y> orTry(
      ThrowingLongToIntFunction<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.orTry(() -> f.applyAsInt(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongToIntFunction<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingLongUnaryOperator<X extends Throwable> {
  public long applyAsLong(long operand) throws X;

  default public LongUnaryOperator fallbackTo(LongUnaryOperator fallback) {
    return fallbackTo(fallback, null);
  }

  default public LongUnaryOperator fallbackTo(LongUnaryOperator fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingLongUnaryOperator<Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingLongUnaryOperator<Y>
      orTry(ThrowingLongUnaryOperator<? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingLongUnaryOperator<Y> orTry(
      ThrowingLongUnaryOperator<? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.orTry(() -> f.applyAsLong(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingLongUnaryOperator<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingObjDoubleConsumer<T, X extends Throwable> {
  public void accept(T t, double value) throws X;

  default public ObjDoubleConsumer<T> fallbackTo(ObjDoubleConsumer<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ObjDoubleConsumer<T> fallbackTo(ObjDoubleConsumer<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingObjDoubleConsumer<T, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingObjDoubleConsumer<T, Y>
      orTry(ThrowingObjDoubleConsumer<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingObjDoubleConsumer<T, Y> orTry(
      ThrowingObjDoubleConsumer<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.orTry(() -> f.accept(t, v), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingObjDoubleConsumer<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingObjIntConsumer<T, X extends Throwable> {
  public void accept(T t, int value) throws X;

  default public ObjIntConsumer<T> fallbackTo(ObjIntConsumer<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ObjIntConsumer<T> fallbackTo(ObjIntConsumer<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingObjIntConsumer<T, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingObjIntConsumer<T, Y>
      orTry(ThrowingObjIntConsumer<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingObjIntConsumer<T, Y> orTry(
      ThrowingObjIntConsumer<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.orTry(() -> f.accept(t, v)).run();
    };
  }

  default public <Y extends Throwable> ThrowingObjIntConsumer<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingObjLongConsumer<T, X extends Throwable> {
  public void accept(T t, long value) throws X;

  default public ObjLongConsumer<T> fallbackTo(ObjLongConsumer<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ObjLongConsumer<T> fallbackTo(ObjLongConsumer<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingObjLongConsumer<T, Nothing> t = fallback::accept;
    return orTry(t, thrown)::accept;
  }

  default public <Y extends Throwable> ThrowingObjLongConsumer<T, Y>
      orTry(ThrowingObjLongConsumer<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingObjLongConsumer<T, Y> orTry(
      ThrowingObjLongConsumer<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.orTry(() -> f.accept(t, v), thrown).run();
    };
  }

  default public <Y extends Throwable> ThrowingObjLongConsumer<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return (t, v) -> {
      ThrowingRunnable<X> s = () -> accept(t, v);
      s.rethrow(x, mapper).run();
    };
  }
} @FunctionalInterface
public interface ThrowingPredicate<T, X extends Throwable> {
  public boolean test(T t) throws X;

  default public Predicate<T> fallbackTo(Predicate<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Predicate<T> fallbackTo(Predicate<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingPredicate<T, Nothing> t = fallback::test;
    return orTry(t, thrown)::test;
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y>
      orTry(ThrowingPredicate<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y> orTry(
      ThrowingPredicate<? super T, ? extends Y> f, @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.orTry(() -> f.test(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingPredicate<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Boolean, X> s = () -> test(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingRunnable<X extends Throwable> {
  public void run() throws X;

  default public Runnable fallbackTo(Runnable fallback) {
    ThrowingRunnable<Nothing> t = fallback::run;
    return orTry(t)::run;
  }

  default public <Y extends Throwable> ThrowingRunnable<Y> orTry(ThrowingRunnable<? extends Y> r) {
    return orTry(r, null);
  }

  default public <Y extends Throwable> ThrowingRunnable<Y> orTry(ThrowingRunnable<? extends Y> r,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingSupplier<Void, X> s1 = () -> {
      run();
      return null;
    };
    return s1.orTry(() -> {
      r.run();
      return null;
    }, thrown)::get;
  }

  default public <Y extends Throwable> ThrowingRunnable<Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    ThrowingSupplier<Void, X> s1 = () -> {
      run();
      return null;
    };
    return s1.rethrow(x, mapper)::get;
  }
} @FunctionalInterface
public interface ThrowingSupplier<R, X extends Throwable> {
  public R get() throws X;

  default public Supplier<R> fallbackTo(Supplier<? extends R> fallback) {
    return fallbackTo(fallback, null);
  }

  default public Supplier<R> fallbackTo(Supplier<? extends R> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingSupplier<R, Nothing> t = fallback::get;
    return orTry(t, thrown)::get;
  }

  default public <Y extends Throwable> ThrowingSupplier<R, Y>
      orTry(ThrowingSupplier<? extends R, ? extends Y> supplier) {
    return orTry(supplier, null);
  }

  default public <Y extends Throwable> ThrowingSupplier<R, Y> orTry(
      ThrowingSupplier<? extends R, ? extends Y> supplier,
      @Nullable Consumer<? super Throwable> thrown) {
    Objects.requireNonNull(supplier, "supplier");
    return () -> {
      try {
        return get();
      } catch (Throwable x) {
        if (thrown != null) {
          thrown.accept(x);
        }

        try {
          return supplier.get();
        } catch (Throwable y) {
          y.addSuppressed(x);
          throw y;
        }
      }
    };
  }

  default public <Y extends Throwable> ThrowingSupplier<R, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    Function<Throwable, ? extends Y> rethrower = RethrowChain.castTo(x).rethrow(mapper).finish();
    return () -> {
      try {
        return get();
      } catch (Throwable t) {
        throw rethrower.apply(t);
      }
    };
  }
} @FunctionalInterface
public interface ThrowingToDoubleFunction<T, X extends Throwable> {
  public double applyAsDouble(T value) throws X;

  default public ToDoubleFunction<T> fallbackTo(ToDoubleFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToDoubleFunction<T> fallbackTo(ToDoubleFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToDoubleFunction<T, Nothing> t = fallback::applyAsDouble;
    return orTry(t, thrown)::applyAsDouble;
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y>
      orTry(ThrowingToDoubleFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y> orTry(
      ThrowingToDoubleFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.orTry(() -> f.applyAsDouble(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToDoubleFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Double, X> s = () -> applyAsDouble(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingToIntFunction<T, X extends Throwable> {
  public int applyAsInt(T value) throws X;

  default public ToIntFunction<T> fallbackTo(ToIntFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToIntFunction<T> fallbackTo(ToIntFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToIntFunction<T, Nothing> t = fallback::applyAsInt;
    return orTry(t, thrown)::applyAsInt;
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y>
      orTry(ThrowingToIntFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y> orTry(
      ThrowingToIntFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.orTry(() -> f.applyAsInt(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToIntFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Integer, X> s = () -> applyAsInt(t);
      return s.rethrow(x, mapper).get();
    };
  }
} @FunctionalInterface
public interface ThrowingToLongFunction<T, X extends Throwable> {
  public long applyAsLong(T value) throws X;

  default public ToLongFunction<T> fallbackTo(ToLongFunction<? super T> fallback) {
    return fallbackTo(fallback, null);
  }

  default public ToLongFunction<T> fallbackTo(ToLongFunction<? super T> fallback,
      @Nullable Consumer<? super Throwable> thrown) {
    ThrowingToLongFunction<T, Nothing> t = fallback::applyAsLong;
    return orTry(t, thrown)::applyAsLong;
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y>
      orTry(ThrowingToLongFunction<? super T, ? extends Y> f) {
    return orTry(f, null);
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y> orTry(
      ThrowingToLongFunction<? super T, ? extends Y> f,
      @Nullable Consumer<? super Throwable> thrown) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.orTry(() -> f.applyAsLong(t), thrown).get();
    };
  }

  default public <Y extends Throwable> ThrowingToLongFunction<T, Y> rethrow(Class<X> x,
      Function<? super X, ? extends Y> mapper) {
    return t -> {
      ThrowingSupplier<Long, X> s = () -> applyAsLong(t);
      return s.rethrow(x, mapper).get();
    };
  }
}
import java.util.Comparator;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjDoubleConsumer;
import java.util.function.ObjIntConsumer;
import java.util.function.ObjLongConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import name.falgout.jeffrey.throwing.RethrowChain;
import name.falgout.jeffrey.throwing.ThrowingBiConsumer;
import name.falgout.jeffrey.throwing.ThrowingBiFunction;
import name.falgout.jeffrey.throwing.ThrowingBinaryOperator;
import name.falgout.jeffrey.throwing.ThrowingComparator;
import name.falgout.jeffrey.throwing.ThrowingConsumer;
import name.falgout.jeffrey.throwing.ThrowingDoubleBinaryOperator;
import name.falgout.jeffrey.throwing.ThrowingDoubleConsumer;
import name.falgout.jeffrey.throwing.ThrowingDoubleFunction;
import name.falgout.jeffrey.throwing.ThrowingDoublePredicate;
import name.falgout.jeffrey.throwing.ThrowingDoubleToIntFunction;
import name.falgout.jeffrey.throwing.ThrowingDoubleToLongFunction;
import name.falgout.jeffrey.throwing.ThrowingDoubleUnaryOperator;
import name.falgout.jeffrey.throwing.ThrowingFunction;
import name.falgout.jeffrey.throwing.ThrowingIntBinaryOperator;
import name.falgout.jeffrey.throwing.ThrowingIntConsumer;
import name.falgout.jeffrey.throwing.ThrowingIntFunction;
import name.falgout.jeffrey.throwing.ThrowingIntPredicate;
import name.falgout.jeffrey.throwing.ThrowingIntToDoubleFunction;
import name.falgout.jeffrey.throwing.ThrowingIntToLongFunction;
import name.falgout.jeffrey.throwing.ThrowingIntUnaryOperator;
import name.falgout.jeffrey.throwing.ThrowingLongBinaryOperator;
import name.falgout.jeffrey.throwing.ThrowingLongConsumer;
import name.falgout.jeffrey.throwing.ThrowingLongFunction;
import name.falgout.jeffrey.throwing.ThrowingLongPredicate;
import name.falgout.jeffrey.throwing.ThrowingLongToDoubleFunction;
import name.falgout.jeffrey.throwing.ThrowingLongToIntFunction;
import name.falgout.jeffrey.throwing.ThrowingLongUnaryOperator;
import name.falgout.jeffrey.throwing.ThrowingObjDoubleConsumer;
import name.falgout.jeffrey.throwing.ThrowingObjIntConsumer;
import name.falgout.jeffrey.throwing.ThrowingObjLongConsumer;
import name.falgout.jeffrey.throwing.ThrowingPredicate;
import name.falgout.jeffrey.throwing.ThrowingRunnable;
import name.falgout.jeffrey.throwing.ThrowingSupplier;
import name.falgout.jeffrey.throwing.ThrowingToDoubleFunction;
import name.falgout.jeffrey.throwing.ThrowingToIntFunction;
import name.falgout.jeffrey.throwing.ThrowingToLongFunction;
package name.falgout.jeffrey.throwing.adapter;



public final class ExceptionMasker<X extends Throwable> {
  private static final class MaskedException extends RuntimeException {
    private static final long serialVersionUID = -6116256229712974011L;

    private MaskedException(Throwable cause) {
      super("Uh oh, someone forgot to unmask!", cause);
    }
  }

  public static Throwable unmask(Throwable throwable) {
    if (throwable instanceof MaskedException) {
      return throwable.getCause();
    }

    return throwable;
  }

  private final Class<X> exceptionClass;
  private final Function<Throwable, MaskedException> masker;
  private final Function<MaskedException, X> unmasker;

  public ExceptionMasker(Class<X> exceptionClass) {
    this.exceptionClass = exceptionClass;
    RethrowChain<Throwable, X> caster = RethrowChain.castTo(exceptionClass);
    masker = caster.rethrow(MaskedException::new).finish();
    RethrowChain<MaskedException, X> unmasker = masked -> caster.apply(masked.getCause());
    this.unmasker = unmasker.finish();
  }

  public Class<X> getExceptionClass() {
    return exceptionClass;
  }

  public void maskException(ThrowingRunnable<? extends X> runnable) {
    maskException(() -> {
      runnable.run();
      return null;
    });
  }

  public <R> R maskException(ThrowingSupplier<? extends R, ? extends X> supplier) {
    try {
      return supplier.get();
    } catch (Throwable t) {
      throw masker.apply(t);
    }
  }

  public Runnable mask(ThrowingRunnable<? extends X> runnable) {
    Objects.requireNonNull(runnable);
    return () -> maskException(runnable);
  }

  public <R> Supplier<R> mask(ThrowingSupplier<? extends R, ? extends X> supplier) {
    Objects.requireNonNull(supplier);
    return () -> maskException(supplier);
  }

  public <T> Predicate<T> mask(ThrowingPredicate<? super T, ? extends X> predicate) {
    Objects.requireNonNull(predicate);
    return t -> maskException(() -> predicate.test(t));
  }

  public <T, R> Function<T, R> mask(
      ThrowingFunction<? super T, ? extends R, ? extends X> function) {
    Objects.requireNonNull(function);
    return t -> maskException(() -> function.apply(t));
  }

  public <T> Consumer<T> mask(ThrowingConsumer<? super T, ? extends X> consumer) {