1mod enums;
2mod write_buffer;
3
4pub use enums::{Level, OutputKind};
5pub use write_buffer::WriteBuffer;
6
7use crate::timestamp::get_timestamp;
8use std::collections::HashMap;
9use std::fs::OpenOptions;
10use std::io;
11
12pub struct Logger<'o> {
15 file_options: OpenOptions,
16 level_outputs: HashMap<Level, OutputKind<'o>>,
17 write_buffers: HashMap<OutputKind<'o>, WriteBuffer>,
18 format: String,
19}
20
21impl<'o> Logger<'o> {
22 pub fn new() -> Option<Self> {
30 let mut options = OpenOptions::new();
31 options.write(true).create(true).truncate(true);
32
33 let mut map_level = HashMap::new();
34 map_level.insert(Level::INFO, OutputKind::STDOUT);
35 map_level.insert(Level::DEBUG, OutputKind::STDOUT);
36 map_level.insert(Level::WARNING, OutputKind::STDERR);
37 map_level.insert(Level::ERROR, OutputKind::STDERR);
38
39 let mut stdout = if let Ok(buff) = WriteBuffer::new(&OutputKind::STDOUT, &options) {
40 buff
41 } else {
42 return None;
43 };
44 let mut stderr = if let Ok(buff) = WriteBuffer::new(&OutputKind::STDERR, &options) {
45 buff
46 } else {
47 return None;
48 };
49 stdout.increase_count();
50 stderr.increase_count();
51
52 let mut map_buffer = HashMap::new();
53 map_buffer.insert(OutputKind::STDOUT, stdout);
54 map_buffer.insert(OutputKind::STDERR, stderr);
55
56 let log = Logger {
57 file_options: options,
58 level_outputs: map_level,
59 write_buffers: map_buffer,
60 format: String::from("[%l](%t) - %m"),
61 };
62
63 return Some(log);
64 }
65
66 pub fn config_format<S: ToString + ?Sized>(&mut self, new_format: &S) {
73 self.format = new_format.to_string();
74
75 }
76
77 fn config_output(&mut self, kind: OutputKind<'o>, level: Level) -> io::Result<()> {
88 match self.write_buffers.get_mut(&kind) {
89 None => {
90 let buffer = WriteBuffer::new(&kind, &self.file_options)?;
91 self.write_buffers.insert(kind.clone(), buffer);
92 }
93 Some(buffer) => buffer.increase_count(),
94 };
95 let output = self.level_outputs.get_mut(&level).unwrap();
96 if match self.write_buffers.get_mut(output) {
97 None => false,
98 Some(buffer) => buffer.decrease_count(),
99 } {
100 self.write_buffers.remove(output);
101 }
102 *output = kind;
103 Ok(())
104 }
105
106 pub fn config_info(&mut self, kind: OutputKind<'o>) {
112 if let Err(err) = self.config_output(kind, Level::INFO) {
113 self.error(&format!("Failed to configure INFO: {}", err));
114 }
115 }
116
117 pub fn config_debug(&mut self, kind: OutputKind<'o>) {
123 if let Err(err) = self.config_output(kind, Level::DEBUG) {
124 self.error(&format!("Failed to configure DEBUG: {}", err));
125 }
126 }
127
128 pub fn config_warning(&mut self, kind: OutputKind<'o>) {
134 if let Err(err) = self.config_output(kind, Level::WARNING) {
135 self.error(&format!("Failed to configure WARNING: {}", err));
136 }
137 }
138
139 pub fn config_error(&mut self, kind: OutputKind<'o>) {
145 if let Err(err) = self.config_output(kind, Level::ERROR) {
146 self.error(&format!("Failed to configure ERROR: {}", err));
147 }
148 }
149
150 fn write_log(&mut self, msg: &str, level: Level) {
161 if let Some(buffer) = self
162 .write_buffers
163 .get_mut(self.level_outputs.get(&level).unwrap())
164 {
165 let mut log_msg = self
166 .format
167 .replace("%l", &level.to_string())
168 .replace("%t", &get_timestamp().to_string())
169 .replace("%m", msg);
170 log_msg.push('\n');
171 if let Err(err) = buffer.log(log_msg) {
172 match level {
173 Level::ERROR => {}
174 _ => self.error(&format!("Failed to log to `{}`: {}", level, err)),
175 }
176 };
177 };
178 }
179
180 pub fn info(&mut self, msg: &str) {
186 self.write_log(msg, Level::INFO);
187 }
188
189 pub fn debug(&mut self, msg: &str) {
195 self.write_log(msg, Level::DEBUG);
196 }
197
198 pub fn warning(&mut self, msg: &str) {
204 self.write_log(msg, Level::WARNING);
205 }
206
207 pub fn error(&mut self, msg: &str) {
213 self.write_log(msg, Level::ERROR);
214 }
215}