chimes_utils/
errors.rs

1//! copyright © ecdata.cn 2020 - present
2//! 自定义错误信息处理
3//! created by shaipe
4use actix_web::ResponseError;
5use chrono::{DateTime, Local};
6use std::convert::Into;
7use std::error::Error as StdError;
8use std::fmt;
9
10#[derive(Debug)]
11pub enum ErrorKind {
12    Msg(String),
13    Io(::std::io::Error),
14    Custom { code: i32, msg: String },
15}
16
17/// The WechatError type
18#[derive(Debug)]
19pub struct ChimesError {
20    /// Kind of error
21    pub kind: ErrorKind,
22    pub source: Option<Box<dyn StdError>>,
23}
24unsafe impl Sync for ChimesError {}
25unsafe impl Send for ChimesError {}
26
27/// 继承标准接口
28impl StdError for ChimesError {
29    fn source(&self) -> Option<&(dyn StdError + 'static)> {
30        self.source.as_deref()
31    }
32}
33
34/// 格式化显示设置
35impl fmt::Display for ChimesError {
36    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37        match self.kind {
38            ErrorKind::Msg(ref message) => write!(f, "{}", message),
39            ErrorKind::Custom { code, ref msg } => {
40                write!(f, "custom error code: {}, message: {}", code, msg)
41            }
42            ErrorKind::Io(ref e) => write!(f, "{}", e),
43        }
44    }
45}
46
47impl ChimesError {
48    /// Creates generic error
49    pub fn msg(value: impl ToString) -> Self {
50        Self {
51            kind: ErrorKind::Msg(value.to_string()),
52            source: None,
53        }
54    }
55
56    /// Creates generic error with a cause
57    pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
58        Self {
59            kind: ErrorKind::Msg(value.to_string()),
60            source: Some(source.into()),
61        }
62    }
63
64    /// 自定义错误
65    pub fn custom(code: i32, msg: impl ToString) -> Self {
66        Self {
67            kind: ErrorKind::Custom {
68                code,
69                msg: msg.to_string(),
70            },
71            source: None,
72        }
73    }
74
75    /// 自定义错误
76    pub fn custom_err(code: i32, msg: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
77        Self {
78            kind: ErrorKind::Custom {
79                code,
80                msg: msg.to_string(),
81            },
82            source: Some(source.into()),
83        }
84    }
85
86    /// 写入文件到日志
87    // #[allow(dead_code)]
88    pub fn write_to_file(content: String) {
89        use std::fs::OpenOptions;
90        use std::io::prelude::*;
91        let mut name = String::from("logs");
92        // 获取当前应用名称
93        if let Ok(p) = std::env::current_exe() {
94            let s = p.file_name().unwrap().to_str().unwrap();
95            name = String::from(s);
96        }
97
98        let mut file_path = format!("log/{}.log", name);
99        let mut dir_path_str = "log/".to_owned();
100        // 只有非调试模式下才使用下面的配置
101        if !cfg!(debug_assertions) {
102            // 给定了相对顶层路径时不处理
103            if !file_path.starts_with('/') {
104                if let Ok(p) = std::env::current_exe() {
105                    let workdir = format!("{}", p.parent().unwrap().display());
106                    file_path = format!("{}/{}", &workdir, file_path.replace("./", ""));
107                    dir_path_str = format!("{}/{}", &workdir, dir_path_str.replace("./", ""));
108                }
109            }
110        }
111
112        let dir_path = std::path::Path::new(&dir_path_str);
113        if !dir_path.exists() {
114            let _ = std::fs::create_dir_all(dir_path);
115        }
116        // println!("sdsdds{}", file_path);
117        // 以读,写,创建,追加的方式打开文件
118        let file = OpenOptions::new()
119            .read(true)
120            .write(true)
121            .create(true)
122            .append(true)
123            .open(file_path);
124
125        let local: DateTime<Local> = Local::now();
126        let now_str = local.format("%Y-%m-%d %H:%M:%S").to_string();
127
128        // 向文件中写入内容
129        match file {
130            Ok(mut stream) => {
131                stream
132                    .write_all(format!("[{}] {}\n", now_str, content).as_bytes())
133                    .unwrap();
134            }
135            Err(err) => {
136                println!("{:?}", err);
137            }
138        }
139    }
140}
141
142impl ResponseError for ChimesError {}
143
144impl From<ChimesError> for rbatis::Error {
145    fn from(val: ChimesError) -> Self {
146        rbatis::Error::E(val.to_string())
147    }
148}
149
150impl From<rbatis::Error> for ChimesError {
151    fn from(value: rbatis::Error) -> Self {
152        match value {
153            rbatis::Error::E(desc) => Self::msg(desc),
154            rbatis::Error::Deserialize(desc) => Self::msg(desc),
155            rbatis::Error::Database(desc) => Self::msg(desc),
156            _ => Self::msg("Unknown Error".to_string()),
157        }
158    }
159}
160
161/**
162impl From<&str> for ChimesError {
163    fn from(e: &str) -> Self {
164        Self::msg(e)
165    }
166}
167impl From<String> for ChimesError {
168    fn from(e: String) -> Self {
169        Self::msg(e)
170    }
171}
172impl From<::std::io::Error> for ChimesError {
173    fn from(e: ::std::io::Error) -> Self {
174        Self {
175            kind: ErrorKind::Io(e),
176            source: None,
177        }
178    }
179}
180
181impl From<rbatis::Error> for ChimesError {
182    fn from(e: rbatis::Error) -> Self {
183        Self {
184            kind: ErrorKind::Msg(e.to_string()),
185            source: Some(Box::new(e)),
186        }
187    }
188}
189
190impl From<actix_web::Error> for ChimesError {
191    fn from(e: actix_web::Error) -> Self {
192        let resp: Error = e.into();
193        let msg = resp.to_string();
194        let http: HttpResponse = resp.into();
195        Self {
196            kind: ErrorKind::Custom { code: http.status().as_u16() as i32, msg: msg },
197            source: None,
198        }
199    }
200}
201*/
202
203/// 获取错误信息对象
204#[macro_export]
205macro_rules! error {
206    // error! {code: i32, msg: String};
207    (code: $code: expr, msg: $msg: expr) => {{
208        ChimesError::custom($code, $msg)
209    }};
210    // error! {code: i32, msg: String,};
211    (code: $code: expr, msg: $msg: expr,) => {{
212        ChimesError::custom($code, $msg)
213    }};
214
215    // error!("msg {}", msg)
216    ($($arg:tt)*) => {{
217        let content = format!($($arg)*);
218        // println!("content: {}", content);
219        // 调试模式下直接使用println!()
220        ChimesError::msg(content)
221    }};
222}