ignite/log/
log.rs

1use std::fmt;
2use std::fs::OpenOptions;
3use std::io::prelude::*;
4use str_util::empty_string;
5
6/// All possible tags which are applied to log entries.
7const TAGS: [&str; 4] = ["[info]", "[debug]", "[warning]", "[error]"];
8const CLEAR_THRESHOLD: usize = 8192;
9
10/// A complete log entry.
11#[derive(Debug, Clone)]
12struct Entry {
13    level: usize,
14    message: String,
15}
16
17impl Entry {
18    /// Create a new Entry structure.
19    #[inline]
20    fn new(level: usize, message: String) -> Entry {
21        Entry {
22            level: level,
23            message: message,
24        }
25    }
26
27    /// Render the Entry to a String for display.
28    #[inline]
29    fn render(&self) -> String {
30        format!("{} {}", TAGS[self.level], self.message)
31    }
32}
33
34/// A basic log structure containing a vector of entries.
35#[derive(Debug)]
36pub struct Log {
37    log: Vec<Entry>,
38    write_status: u32,
39    log_file: String,
40}
41
42impl Log {
43    /// Create a new Log structure.
44    #[inline]
45    pub fn new() -> Log {
46        Log {
47            log: Vec::new(),
48            write_status: 0,
49            log_file: empty_string(),
50        }
51    }
52
53    /// Add an entry to the log.
54    #[inline]
55    fn add_entry(&mut self, level: usize, message: String) {
56        if self.log.len() > CLEAR_THRESHOLD {
57            self.clear();
58        }
59
60        let entry = Entry::new(level, message);
61        let log_len: usize = self.log.len();
62        self.log.push(entry.clone());
63
64        match self.write_status {
65            1 => {
66                println!("{}", entry.render());
67            }
68            2 => {
69                self.save_entry(log_len);
70            }
71            3 => {
72                println!("{}", entry.render());
73                self.save_entry(log_len);
74            }
75            _ => {}
76        }
77    }
78
79    fn save_entry(&self, index: usize) {
80        let entry: String = self.log[index].render();
81
82        let mut handle = OpenOptions::new()
83            .write(true)
84            .append(true)
85            .create(true)
86            .open(&self.log_file)
87            .unwrap();
88
89        let _ = writeln!(&mut handle, "{}", entry);
90    }
91
92    /// Set the file which log entries will be written to.
93    #[inline]
94    pub fn set_log_file(&mut self, log_path: String) {
95        self.log_file = log_path;
96    }
97
98    #[inline]
99    pub fn info(&mut self, message: String) {
100        self.add_entry(0, message);
101    }
102
103    #[inline]
104    pub fn debug(&mut self, message: String) {
105        self.add_entry(1, message);
106    }
107
108    #[inline]
109    pub fn warning(&mut self, message: String) {
110        self.add_entry(2, message);
111    }
112
113    #[inline]
114    pub fn error(&mut self, message: String) {
115        self.add_entry(3, message);
116    }
117
118    /** Set the write status of the log. This dictates what and how stuff is logged. Must be a value between 0-3. Below
119    is a list of what the values mean. Note that all modes write the log to memory.
120
121    0 # Log entries are written to memory but nothing else.
122
123    1 # Log entries are automatically printed as they are created.
124
125    2 # Log entries are written to a set file as they are created.
126
127    3 # Mode 3 is a combination of mode 1 and 2. */
128    #[inline]
129    pub fn set_write(&mut self, mode: u32) {
130        self.write_status = mode;
131    }
132
133    /// Clear all entries in the log.
134    #[inline]
135    pub fn clear(&mut self) {
136        self.log.clear();
137    }
138
139    /// Render the log to a vector of strings.
140    pub fn render(&self) -> Vec<String> {
141        let mut textlog: Vec<String> = Vec::new();
142
143        for entry in &self.log {
144            textlog.push(format!("{} {}", TAGS[entry.level], entry.message));
145        }
146
147        textlog
148    }
149}
150
151impl fmt::Display for Entry {
152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153        writeln!(f, "{}", &self.render())?;
154        Ok(())
155    }
156}
157
158impl fmt::Display for Log {
159    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160        for line in &self.render() {
161            writeln!(f, "{}", line)?;
162        }
163        Ok(())
164    }
165}