ciphercore_utils/
execute_main.rs

1//! Wrapper for a main function to run CipherCore
2use log::error;
3use std::fmt::Display;
4use std::process;
5use std::result::Result;
6
7/// Executes CipherCore code such that all the internal errors are properly formatted and logged.
8///
9/// # Arguments
10///
11/// `f` - closure without arguments containing CipherCore code and returning `Result<()>`
12pub fn execute_main<T, E>(f: T)
13where
14    T: FnOnce() -> Result<(), E> + std::panic::UnwindSafe,
15    E: Display,
16{
17    let result = std::panic::catch_unwind(|| {
18        let result = f();
19        if let Err(e) = result {
20            error!("CipherCore Error:\n{e}");
21            process::exit(1);
22        }
23    });
24    process_result(result);
25}
26
27#[doc(hidden)]
28pub fn extract_panic_message(e: Box<dyn std::any::Any + Send>) -> Option<String> {
29    match e.downcast::<String>() {
30        Ok(panic_msg) => Some(*panic_msg),
31        Err(e) => match e.downcast::<&str>() {
32            Ok(panic_msg) => Some((*panic_msg).to_owned()),
33            Err(_) => None,
34        },
35    }
36}
37
38#[doc(hidden)]
39pub fn process_result<R>(result: std::thread::Result<R>) {
40    if let Err(e) = result {
41        match extract_panic_message(e) {
42            Some(panic_msg) => error!("panic: {}", panic_msg),
43            None => error!("panic of unknown type"),
44        }
45        process::exit(1);
46    }
47}