easy_err/err.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use std::{error, fmt, fs, io::{self, Write}, path::Path};
use colored::Colorize;
/// 用于统一错误的枚举
///
/// # Examples
/// ```
/// let err = err::Error::custom("Here is a error.");
/// err.report();
/// ```
#[derive(Debug)]
pub enum Error {
/// 用于包装已经实现Error Trait的结构体或枚举
Basic(Box<dyn error::Error>),
/// 用于报告用户自定义的错误信息
Custom(String)
}
impl Error {
/// 产生一个basic变体
///
/// # Examples
/// ```
/// let file = std::fs::File::open("An obvious mistake.").or_else(|err|{Err(crate::err::Error::basic(Box::new(err)))});
/// match file {
/// Ok(_) => println!("Ok!"),
/// Err(err) => {err.report().panic();}
/// }
/// ```
pub fn basic(err: Box<dyn error::Error>) -> Error {
Error::Basic(err)
}
/// 产生一个custom变体
///
/// # Examples
/// ```
/// let custom_err = err::Error::custom("Here is a error.");
/// custom_err.report();
/// ```
pub fn custom<S>(msg: S) -> Error where S:ToString{
Error::Custom(msg.to_string())
}
/// 在标准错误流中输出一条报告信息
///
/// # Examples
/// ```
/// let custom_err = err::Error::custom("Here is a error.");
/// custom_err.report(); // error: Here is a error.
/// ```
pub fn report(&self) -> &Self {
eprintln!("{}", self);
self
}
/// 引发 panic!() 宏
///
/// # Examples
/// ```
/// let custom_err = err::Error::custom("Here is a error.");
/// custom_err.panic(); // error: Here is a error.
/// ```
pub fn panic(&self){
panic!("{}", self);
}
/// 将报告信息输出至文件
///
/// # Params
/// - path: 任何可以转换为 Path 的值
///
/// # Examples
/// ```
/// let custom_err = err::Error::custom("Here is a error.");
/// custom_err.log_to("./log.txt").unwrap();
/// ```
pub fn log_to<P>(&self, path: P) -> Result<&Self, Error> where P: AsRef<Path> {
let mut file = fs::File::create(path)?;
file.write(self.to_string().as_bytes())?;
Ok(self)
}
}
impl From<io::Error> for Error {
fn from(value: io::Error) -> Self {
Error::Basic(Box::new(value))
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Basic(err) => write!(f, "{}: {}", "error".red().bold(), err),
Self::Custom(msg) => write!(f, "{}: {}", "error".red().bold(), msg)
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Basic(err) => Some(err.as_ref()),
Self::Custom(_) => None
}
}
}