gila/src/kernel/log.rs

93 lines
2.4 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 Default for Logger {
fn default() -> Self {
Self::new()
}
}
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) {
// Nobody is EVER allowed to call log with the Disabled log level. It is a placeholder.
if level == LogLevel::Disabled {
// Nothing
} else 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, <crate::log::LogLevel as TryFrom<u8>>::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, <crate::log::LogLevel as TryFrom<u8>>::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 {}),
}
}
}