1use serde::{Serialize, Deserialize};
7use chrono::{Local, DateTime};
8
9use crate::{
10 LogType, Error,
11 colors::{Color, color_text},
12 config::LogStruct,
13};
14
15#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize,
39 Deserialize)]
40pub struct LogFormatter {
41 pub(crate) log_header_color_enabled: bool,
42
43 pub(crate) debug_color: Color,
44 pub(crate) info_color: Color,
45 pub(crate) warning_color: Color,
46 pub(crate) error_color: Color,
47 pub(crate) fatal_color: Color,
48
49 pub(crate) debug_header: String,
50 pub(crate) info_header: String,
51 pub(crate) warning_header: String,
52 pub(crate) error_header: String,
53 pub(crate) fatal_header: String,
54
55 pub(crate) log_format: String,
56 pub(crate) datetime_format: String,
57
58 #[serde(skip)]
59 pub(crate) show_datetime: Option<bool>,
60}
61
62impl LogFormatter {
63 pub(crate) fn get_datetime_formatted(&mut self, datetime: &DateTime<Local>) -> String {
64 match self.show_datetime {
65 Some(b) => {
66 match b {
67 true => {
68 return datetime.format(&self.datetime_format)
69 .to_string();
70 },
71 false => {
72 return String::new();
73 },
74 }
75
76 },
77 None => {
78 match self.log_format.contains("%d") {
79 true => {
80 self.show_datetime = Some(true);
81 return datetime.format(&self.datetime_format)
82 .to_string();
83 },
84 false => {
85 self.show_datetime = Some(false);
86 return String::new();
87 },
88 }
89 }
90 }
91 }
92
93 pub(crate) fn log_header_color(&self, log_type: LogType) -> Color {
94 match log_type {
95 LogType::Debug => self.debug_color.clone(),
96 LogType::Info => self.info_color.clone(),
97 LogType::Warning => self.warning_color.clone(),
98 LogType::Err => self.error_color.clone(),
99 LogType::FatalError => self.fatal_color.clone(),
100 }
101 }
102
103 pub(crate) fn colorify(&self, text: &str, color: Color) -> String {
104 if self.log_header_color_enabled {
105 return color_text(text, color);
106 }
107 return text.to_string()
108 }
109
110 pub(crate) fn get_log_type_header(&self, log_type: LogType) -> String {
111 match log_type {
112 LogType::Debug => {
113 return self.colorify(&self.debug_header,
114 self.log_header_color(log_type))
115 }
116 LogType::Info => {
117 return self.colorify(&self.info_header,
118 self.log_header_color(log_type))
119 }
120 LogType::Warning => {
121 return self.colorify(&self.warning_header,
122 self.log_header_color(log_type))
123 }
124 LogType::Err => {
125 return self.colorify(&self.error_header,
126 self.log_header_color(log_type))
127 }
128 LogType::FatalError => {
129 return self.colorify(&self.fatal_header,
130 self.log_header_color(log_type))
131 }
132 }
133 }
134
135 pub(crate) fn get_log_headers(&mut self, log: &LogStruct)
136 -> (String, String) {
137 let header = self.get_log_type_header(log.log_type);
138 let datetime = self.get_datetime_formatted(&log.datetime);
139 return (header, datetime);
140 }
141
142 pub fn format_log(&mut self, log: &LogStruct) -> String {
152 let headers = self.get_log_headers(log);
153 let mut result = String::new();
154 let mut char_iter = self
155 .log_format.char_indices().peekable();
156
157 while let Some((_, c)) = char_iter.next() {
158 match c {
159 '%' => {
160 if let Some((_, nc)) = char_iter.peek() {
161 match nc {
162 'h' => result += &headers.0,
163 'd' => result += &headers.1,
164 'm' => result += &log.message,
165 _ => result += &nc.to_string(),
166 }
167 char_iter.next();
168 }
169 }
170 _ => {
171 result += &c.to_string();
172 }
173 }
174 }
175
176 result += "\n";
177 return result
178 }
179
180 pub fn enable_log_header_color(&mut self) {
182 self.log_header_color_enabled = true;
183 }
184
185 pub fn disable_log_header_color(&mut self) {
187 self.log_header_color_enabled = false;
188 }
189
190 pub fn set_debug_color<I: Into<Color>>(&mut self, color: I) {
192 self.debug_color = color.into();
193 }
194
195 pub fn set_info_color<I: Into<Color>>(&mut self, color: I) {
197 self.info_color = color.into();
198 }
199
200 pub fn set_warning_color<I: Into<Color>>(&mut self, color: I) {
202 self. warning_color = color.into();
203 }
204
205 pub fn set_error_color<I: Into<Color>>(&mut self, color: I) {
207 self.error_color = color.into();
208 }
209
210 pub fn set_fatal_color<I: Into<Color>>(&mut self, color: I) {
212 self.fatal_color = color.into();
213 }
214
215 pub fn set_debug_header(&mut self, header: &str) {
217 self.debug_header = header.to_string();
218 }
219
220 pub fn set_info_header(&mut self, header: &str) {
222 self.info_header = header.to_string();
223 }
224
225 pub fn set_warning_header(&mut self, header: &str) {
227 self.warning_header = header.to_string();
228 }
229
230 pub fn set_error_header(&mut self, header: &str) {
232 self.error_header = header.to_string();
233 }
234
235 pub fn set_fatal_header(&mut self, header: &str) {
237 self.fatal_header = header.to_string();
238 }
239
240 pub fn set_datetime_format(&mut self, format: &str) {
242 self.datetime_format = String::from(format);
243 self.show_datetime = None;
244 }
245
246 pub fn set_log_format(&mut self, format: &str) -> Result<(), Error> {
271 if format.contains("%m") {
272 self.log_format = String::from(format);
273 Ok(())
274 }
275 else {
276 Err(Error::new("Expected a message placeholder!"))
277 }
278 }
279}
280
281impl Default for LogFormatter {
282 fn default() -> LogFormatter {
283 let log_format = String::from("[%h] %m");
284 LogFormatter {
285 log_header_color_enabled: true,
286
287 debug_color: Color::Blue,
288 info_color: Color::Green,
289 warning_color: Color::Yellow,
290 error_color: Color::Red,
291 fatal_color: Color::Magenta,
292
293 debug_header: String::from("DBG"),
294 info_header: String::from("INF"),
295 warning_header: String::from("WAR"),
296 error_header: String::from("ERR"),
297 fatal_header: String::from("FATAL"),
298
299 log_format: log_format.clone(),
300 datetime_format: String::from("%Y-%m-%d %H:%M:%S"),
301
302 show_datetime: None,
303 }
304 }
305}