zlsrs 0.1.6

Rust 标准库扩展工具集,提供更便捷的使用方式
Documentation
/// # zerror 错误处理
///
/// 错误处理模块,提供了一些便捷的错误处理工具函数。
///
/// ## 特点
///
/// - 提供通用的错误捕获函数
/// - 支持 panic 和 Error 的统一处理
/// - 简化错误处理流程
///
/// ## 示例
///
/// ```rust
/// use zlsrs::zerror::try_catch;
///
/// fn main() {
///     // 捕获可能发生的错误
///     let result = try_catch(|| {
///         // 这里是可能产生错误的代码
///         if true {
///             Ok(())
///         } else {
///             Err("发生错误".into())
///         }
///     });
///     
///     match result {
///         Ok(_) => println!("执行成功"),
///         Err(e) => println!("捕获到错误: {}", e),
///     }
/// }
/// ```
use std::panic::{self, UnwindSafe};

/// 错误类型
pub type Error = Box<dyn std::error::Error>;

/// 结果类型
pub type Result<T> = std::result::Result<T, Error>;

/// 恐慌错误类型
#[derive(Debug)]
struct PanicError(String);

impl std::fmt::Display for PanicError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl std::error::Error for PanicError {}

/// 通用错误捕获函数,可以同时处理 panic 和 Result 类型的错误。
///
/// # 功能
///
/// - 捕获函数执行过程中的 panic
/// - 处理 Result 类型的错误
/// - 将所有错误统一转换为 String 类型
///
/// # 参数
///
/// * `f` - 需要执行的闭包函数,该函数返回 Result 类型
///
/// # 返回值
///
/// 返回 `Result<(), String>` 类型:
/// - `Ok(())` 表示执行成功
/// - `Err(String)` 包含错误信息的字符串
///
/// # 示例
///
/// ```rust
/// use zlsrs::zerror::try_catch;
///
/// // 处理正常的 Result 错误
/// let result = try_catch(|| {
///     Err("测试错误".into())
/// });
/// assert!(result.is_err());
///
/// // 处理 panic
/// let result = try_catch(|| {
///     panic!("发生 panic");
///     #[allow(unreachable_code)]
///     Ok(())
/// });
/// assert!(result.is_err());
/// ```
pub fn try_catch<F>(f: F) -> Result<()>
where
    F: FnOnce() -> Result<()> + UnwindSafe,
{
    match panic::catch_unwind(f) {
        Ok(result) => match result {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        },
        Err(panic) => {
            let panic_msg = panic
                .downcast_ref::<String>()
                .map(|s| s.as_str())
                .or_else(|| panic.downcast_ref::<&str>().copied())
                .map(|s| s.to_string())
                .unwrap_or_else(|| format!("{:?}", panic));
            Err(Box::new(PanicError(panic_msg)))
        }
    }
}