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 toggle_log_header_color<I: Into<bool>>(&mut self, enabled: I) {
184 self.log_header_color_enabled = enabled.into();
185 }
186
187 pub fn set_debug_color<I: Into<Color>>(&mut self, color: I) {
189 self.debug_color = color.into();
190 }
191
192 pub fn set_info_color<I: Into<Color>>(&mut self, color: I) {
194 self.info_color = color.into();
195 }
196
197 pub fn set_warning_color<I: Into<Color>>(&mut self, color: I) {
199 self. warning_color = color.into();
200 }
201
202 pub fn set_error_color<I: Into<Color>>(&mut self, color: I) {
204 self.error_color = color.into();
205 }
206
207 pub fn set_fatal_color<I: Into<Color>>(&mut self, color: I) {
209 self.fatal_color = color.into();
210 }
211
212 pub fn set_debug_header(&mut self, header: &str) {
214 self.debug_header = header.to_string();
215 }
216
217 pub fn set_info_header(&mut self, header: &str) {
219 self.info_header = header.to_string();
220 }
221
222 pub fn set_warning_header(&mut self, header: &str) {
224 self.warning_header = header.to_string();
225 }
226
227 pub fn set_error_header(&mut self, header: &str) {
229 self.error_header = header.to_string();
230 }
231
232 pub fn set_fatal_header(&mut self, header: &str) {
234 self.fatal_header = header.to_string();
235 }
236
237 pub fn set_datetime_format(&mut self, format: &str) {
239 self.datetime_format = String::from(format);
240 self.show_datetime = None;
241 }
242
243 pub fn set_log_format(&mut self, format: &str) -> Result<(), Error> {
268 if format.contains("%m") {
269 self.log_format = String::from(format);
270 Ok(())
271 }
272 else {
273 Err(Error::new("Expected a message placeholder!"))
274 }
275 }
276}
277
278impl Default for LogFormatter {
279 fn default() -> LogFormatter {
280 let log_format = String::from("[%h] %m");
281 LogFormatter {
282 log_header_color_enabled: true,
283
284 debug_color: Color::Blue,
285 info_color: Color::Green,
286 warning_color: Color::Yellow,
287 error_color: Color::Red,
288 fatal_color: Color::Magenta,
289
290 debug_header: String::from("DBG"),
291 info_header: String::from("INF"),
292 warning_header: String::from("WAR"),
293 error_header: String::from("ERR"),
294 fatal_header: String::from("FATAL"),
295
296 log_format: log_format.clone(),
297 datetime_format: String::from("%Y-%m-%d %H:%M:%S"),
298
299 show_datetime: None,
300 }
301 }
302}