use std::fmt;
use std::fs::OpenOptions;
use std::io::prelude::*;
use str_util::empty_string;
const TAGS: [&str; 4] = ["[info]", "[debug]", "[warning]", "[error]"];
const CLEAR_THRESHOLD: usize = 8192;
#[derive(Debug, Clone)]
struct Entry {
level: usize,
message: String,
}
impl Entry {
#[inline]
fn new(level: usize, message: String) -> Entry {
Entry {
level: level,
message: message,
}
}
#[inline]
fn render(&self) -> String {
format!("{} {}", TAGS[self.level], self.message)
}
}
#[derive(Debug)]
pub struct Log {
log: Vec<Entry>,
write_status: u32,
log_file: String,
}
impl Log {
#[inline]
pub fn new() -> Log {
Log {
log: Vec::new(),
write_status: 0,
log_file: empty_string(),
}
}
#[inline]
fn add_entry(&mut self, level: usize, message: String) {
if self.log.len() > CLEAR_THRESHOLD {
self.clear();
}
let entry = Entry::new(level, message);
let log_len: usize = self.log.len();
self.log.push(entry.clone());
match self.write_status {
1 => {
println!("{}", entry.render());
}
2 => {
self.save_entry(log_len);
}
3 => {
println!("{}", entry.render());
self.save_entry(log_len);
}
_ => {}
}
}
fn save_entry(&self, index: usize) {
let entry: String = self.log[index].render();
let mut handle = OpenOptions::new()
.write(true)
.append(true)
.create(true)
.open(&self.log_file)
.unwrap();
let _ = writeln!(&mut handle, "{}", entry);
}
#[inline]
pub fn set_log_file(&mut self, log_path: String) {
self.log_file = log_path;
}
#[inline]
pub fn info(&mut self, message: String) {
self.add_entry(0, message);
}
#[inline]
pub fn debug(&mut self, message: String) {
self.add_entry(1, message);
}
#[inline]
pub fn warning(&mut self, message: String) {
self.add_entry(2, message);
}
#[inline]
pub fn error(&mut self, message: String) {
self.add_entry(3, message);
}
#[inline]
pub fn set_write(&mut self, mode: u32) {
self.write_status = mode;
}
#[inline]
pub fn clear(&mut self) {
self.log.clear();
}
pub fn render(&self) -> Vec<String> {
let mut textlog: Vec<String> = Vec::new();
for entry in &self.log {
textlog.push(format!("{} {}", TAGS[entry.level], entry.message));
}
textlog
}
}
impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "{}", &self.render())?;
Ok(())
}
}
impl fmt::Display for Log {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for line in &self.render() {
writeln!(f, "{}", line)?;
}
Ok(())
}
}