You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.0 KiB
131 lines
3.0 KiB
use std::cell::RefCell;
|
|
use std::cmp::min;
|
|
use std::io::stderr;
|
|
use std::io::Write;
|
|
|
|
// The log crate defines
|
|
// 1 - Error, 2 - Warn, 3 - Info, 4 - Debug, 5 - Trace
|
|
pub type Level = usize;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Entry<S>(pub Level, pub S);
|
|
|
|
pub trait Logger {
|
|
fn write<S: AsRef<str> + Into<String>>(&self, level: Level, msg: S)
|
|
where
|
|
Self: Sized;
|
|
fn writeln<S: AsRef<str> + Into<String>>(&self, level: Level, msg: S)
|
|
where
|
|
Self: Sized;
|
|
fn info<S: AsRef<str> + Into<String>>(&self, msg: S)
|
|
where
|
|
Self: Sized,
|
|
{
|
|
self.writeln(3, msg)
|
|
}
|
|
fn debug<S: AsRef<str> + Into<String>>(&self, msg: S)
|
|
where
|
|
Self: Sized,
|
|
{
|
|
self.writeln(4, msg)
|
|
}
|
|
fn trace<S: AsRef<str> + Into<String>>(&self, msg: S)
|
|
where
|
|
Self: Sized,
|
|
{
|
|
self.writeln(5, msg)
|
|
}
|
|
fn put<S: AsRef<str> + Into<String>>(&self, entries: impl IntoIterator<Item = Entry<S>>) -> usize
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut c = 0;
|
|
for item in entries {
|
|
self.writeln(item.0, item.1);
|
|
c += 1;
|
|
}
|
|
c
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct StdErrLogger {
|
|
line_started: RefCell<bool>,
|
|
}
|
|
|
|
impl Logger for StdErrLogger {
|
|
fn write<S: AsRef<str> + Into<String>>(&self, _level: Level, msg: S) {
|
|
*self.line_started.borrow_mut() = true;
|
|
write!(&mut stderr(), "{}", msg.as_ref()).unwrap();
|
|
}
|
|
fn writeln<S: AsRef<str> + Into<String>>(&self, _level: Level, msg: S) {
|
|
if self.line_started.replace(false) {
|
|
writeln!(&mut stderr()).unwrap();
|
|
}
|
|
writeln!(&mut stderr(), "{}", msg.as_ref()).unwrap();
|
|
}
|
|
}
|
|
impl Drop for StdErrLogger {
|
|
fn drop(&mut self) {
|
|
if *self.line_started.borrow() == true {
|
|
writeln!(&mut stderr()).unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct FilteringLogger<'a, L> {
|
|
logger: &'a L,
|
|
max_level: Level,
|
|
}
|
|
|
|
impl<'a, L> FilteringLogger<'a, L> {
|
|
pub fn new(logger: &'a L, max_level: Level) -> Self {
|
|
Self { logger, max_level }
|
|
}
|
|
}
|
|
|
|
impl<'a, L: Logger> Logger for FilteringLogger<'a, L> {
|
|
fn write<S: AsRef<str> + Into<String>>(&self, level: Level, str: S) {
|
|
if level <= self.max_level {
|
|
self.logger.write(level, str)
|
|
}
|
|
}
|
|
fn writeln<S: AsRef<str> + Into<String>>(&self, level: Level, str: S) {
|
|
if level <= self.max_level {
|
|
self.logger.writeln(level, str)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct StoringLogger {
|
|
log: RefCell<Vec<Entry<String>>>,
|
|
}
|
|
|
|
impl StoringLogger {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn release(self) -> Vec<Entry<String>> {
|
|
self.log.into_inner()
|
|
}
|
|
}
|
|
|
|
impl Logger for StoringLogger {
|
|
fn write<S: AsRef<str> + Into<String>>(&self, level: Level, line: S) {
|
|
let mut log = self.log.borrow_mut();
|
|
let entry = log
|
|
.pop()
|
|
.map(|e| Entry(min(e.0, level), e.1 + line.as_ref()))
|
|
.unwrap_or_else(|| Entry(level, line.into()));
|
|
log.push(entry);
|
|
}
|
|
fn writeln<S: AsRef<str> + Into<String>>(&self, level: Level, line: S) {
|
|
self.log.borrow_mut().push(Entry(level, line.into()));
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {}
|