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