fn r#catch()

in key/aziot-key-openssl-engine/src/lib.rs [98:131]


fn r#catch<T>(
    function: Option<fn() -> openssl_errors::Function<Error>>,
    f: impl FnOnce() -> Result<T, Box<dyn std::error::Error>>,
) -> Result<T, ()> {
    match f() {
        Ok(value) => Ok(value),
        Err(err) => {
            // Technically, the order the errors should be put onto the openssl error stack is from root cause to top error.
            // Unfortunately this is backwards from how Rust errors work, since they are top error to root cause.
            //
            // We could do it the right way by collect()ing into a Vec<&dyn Error> and iterating it backwards,
            // but it seems too wasteful to be worth it. So just put them in the wrong order.

            if let Some(function) = function {
                openssl_errors::put_error!(function(), Error::MESSAGE, "{}", err);
            } else {
                log::error!("[aziot-key-openssl-engine] error: {}", err);
            }

            let mut source = err.source();
            while let Some(err) = source {
                if let Some(function) = function {
                    openssl_errors::put_error!(function(), Error::MESSAGE, "{}", err);
                } else {
                    log::error!("[aziot-key-openssl-engine] caused by: {}", err);
                }

                source = err.source();
            }

            Err(())
        }
    }
}