1use std::{error::Error, fmt, io, string::FromUtf8Error, sync::Arc};
4
5#[derive(Default, Debug, Clone)]
7enum ErrorType {
8 #[default]
10 Normal,
11 Fake,
13}
14
15#[derive(Default, Debug)]
17pub struct AppError {
18 pub message: String,
20 pub source: Option<Arc<dyn std::error::Error + Send + Sync>>,
22 error_type: ErrorType,
24}
25
26impl Clone for AppError {
27 fn clone(&self) -> Self {
28 Self {
29 message: self.message.clone(),
30 source: self.source.clone(),
31 error_type: self.error_type.clone(),
32 }
33 }
34}
35
36impl fmt::Display for AppError {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 if let Some(source) = &self.source {
40 write!(f, "{} (caused by: {})", self.message, source)
41 } else {
42 write!(f, "{}", self.message)
43 }
44 }
45}
46
47impl AppError {
48 pub fn new(message: String) -> Self {
50 Self {
51 message,
52 source: None,
53 error_type: ErrorType::Normal,
54 }
55 }
56
57 pub fn new_with_source(source: Arc<dyn std::error::Error + Send + Sync>) -> Self {
59 Self {
60 message: source.to_string(),
61 source: Some(source),
62 error_type: ErrorType::Normal,
63 }
64 }
65
66 pub fn new_fake(message: String) -> Self {
68 Self {
69 message,
70 source: None,
71 error_type: ErrorType::Fake,
72 }
73 }
74
75 pub fn is_fake(&self) -> bool {
77 matches!(self.error_type, ErrorType::Fake)
78 }
79}
80
81impl From<String> for AppError {
82 fn from(message: String) -> Self {
83 Self::new(message)
84 }
85}
86
87impl From<&str> for AppError {
88 fn from(message: &str) -> Self {
89 Self::new(message.to_string())
90 }
91}
92
93impl From<io::Error> for AppError {
94 fn from(error: io::Error) -> Self {
95 Self {
96 message: error.to_string(),
97 source: Some(Arc::new(error)),
98 error_type: ErrorType::Normal,
99 }
100 }
101}
102
103impl From<FromUtf8Error> for AppError {
104 fn from(error: FromUtf8Error) -> Self {
105 Self {
106 message: error.to_string(),
107 source: Some(Arc::new(error)),
108 error_type: ErrorType::Normal,
109 }
110 }
111}
112
113impl Error for AppError {
114 fn source(&self) -> Option<&(dyn Error + 'static)> {
115 self.source.as_ref().map(|arc| {
118 let err: &(dyn Error + 'static) = &**arc;
119 err
120 })
121 }
122}
123
124#[derive(Debug, Default)]
126pub struct ErrorManager {
127 pub errors: Vec<AppError>,
129
130 pub is_open: bool,
132
133 pub was_open: bool,
135}
136
137impl ErrorManager {
138 pub fn new() -> Self {
140 Self {
141 ..Default::default()
142 }
143 }
144
145 pub fn add_error(&mut self, error: AppError) {
147 if error.is_fake() {
148 return;
149 }
150 self.errors.push(error);
151 }
152
153 pub fn handle_error<T>(&mut self, error: Result<T, impl Into<AppError>>) -> Option<T> {
155 match error {
156 Ok(value) => Some(value),
157 Err(e) => {
158 self.add_error(e.into());
159 None
160 }
161 }
162 }
163
164 pub fn title(&self) -> &'static str {
166 "Error window"
167 }
168}