/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.functional.checked;

import net.ranides.assira.trace.ExceptionUtils;

import java.util.function.Consumer;

/**
 * This functional inferface represents {@link Runnable} which could throw checked exception
 *
 * @param <E> E
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public interface CheckedRunnable<E extends Exception> {

    /**
     * Performs operation.
     *
     * @throws E on error
     */
    void run() throws E;

    /**
     * Performs operation.
     * Usafe method: it rethrows checked exceptions, but without declaring them.
     *
     * Please note, that javac does not allow to catch checked exception of specific type if they are not declared.
     * In such situations you can only catch very general "Exception" type.
     */
    default void $run() {
        try {
            run();
        } catch(Exception cause) {
            throw ExceptionUtils.rethrow(cause);
        }
    }

    /**
     * Converts this runnable into sneaky version, which rethrows checked exception, but without declaring it.
     * Please note, that code expecting ordinary Runnable is not prerared for handling checked throws
     * and could work incorrectly when exception happens.
     *
     * @param runnable runnable
     * @param <E> E
     * @return Runnable
     */
    static  <E extends Exception> Runnable sneaky(CheckedRunnable<E> runnable) {
        return runnable::$run;
    }

}
