gila/src/log.rs

84 lines
2.1 KiB
Rust

use core::fmt::Write;
use crate::memory::alloc;
use alloc::boxed::*;
use alloc::string::*;
use alloc::vec::*;
use spin::Mutex;
/// The logger exists for the entire lifetime of the kernel.
pub static LOGGER: Mutex<Logger> = Mutex::new(Logger::new());
pub struct EnumParseError {}
pub struct Logger {
pub level: LogLevel,
pub subscriber: Vec<Mutex<Box<dyn LogSubscriber + Send + Sync>>>,
}
pub trait LogSubscriber {
fn write(&self, msg: &str);
}
impl Logger {
pub const fn new() -> Self {
Logger {
level: LogLevel::WARNING,
subscriber: Vec::new(),
}
}
/// Calling log will sequentially acquire lock on all logging subscribers
/// to write to them with a formatted log message.
pub fn log(&self, level: LogLevel, msg: &str) {
if level > self.level {
for sub in &self.subscriber {
let mut message = String::new();
write!(&mut message, "{:?}: {}", level, msg).unwrap();
sub.lock().write(&message);
}
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum LogLevel {
DISABLED,
CRITICAL,
ERROR,
WARNING,
INFO,
TRACE,
}
impl TryFrom<u8> for LogLevel {
type Error = EnumParseError;
fn try_from(from: u8) -> Result<Self, Self::Error> {
match from {
0 => Ok(Self::DISABLED),
1 => Ok(Self::CRITICAL),
2 => Ok(Self::ERROR),
3 => Ok(Self::WARNING),
4 => Ok(Self::INFO),
5 => Ok(Self::TRACE),
_ => Err(EnumParseError {}),
}
}
}
impl TryFrom<&str> for LogLevel {
type Error = EnumParseError;
fn try_from(from: &str) -> Result<Self, Self::Error> {
match from.to_ascii_lowercase().as_ref() {
"disabled" => Ok(Self::DISABLED),
"critical" => Ok(Self::CRITICAL),
"error" => Ok(Self::ERROR),
"warning" => Ok(Self::WARNING),
"info" => Ok(Self::INFO),
"trace" => Ok(Self::TRACE),
_ => Err(EnumParseError {}),
}
}
}