use crate::proto::console::text::Output;
use core::fmt::{self, Write};
use core::ptr::NonNull;
pub struct Logger {
writer: Option<NonNull<Output<'static>>>,
}
impl Logger {
pub unsafe fn new(output: &mut Output) -> Self {
Logger {
writer: NonNull::new(output as *const _ as *mut _),
}
}
pub fn disable(&mut self) {
self.writer = None;
}
}
impl<'boot> log::Log for Logger {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
self.writer.is_some()
}
fn log(&self, record: &log::Record) {
if let Some(mut ptr) = self.writer {
let writer = unsafe { ptr.as_mut() };
DecoratedLog::write(writer, record.level(), record.args()).unwrap();
}
}
fn flush(&self) {
}
}
unsafe impl Sync for Logger {}
unsafe impl Send for Logger {}
struct DecoratedLog<'writer, W: fmt::Write> {
writer: &'writer mut W,
log_level: log::Level,
at_line_start: bool,
}
impl<'writer, W: fmt::Write> DecoratedLog<'writer, W> {
fn write(writer: &'writer mut W, log_level: log::Level, args: &fmt::Arguments) -> fmt::Result {
let mut decorated_writer = Self {
writer,
log_level,
at_line_start: true,
};
writeln!(decorated_writer, "{}", *args)
}
}
impl<'writer, W: fmt::Write> fmt::Write for DecoratedLog<'writer, W> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let mut lines = s.lines();
let first = lines.next().unwrap_or("");
if self.at_line_start {
write!(self.writer, "{}: ", self.log_level)?;
self.at_line_start = false;
}
write!(self.writer, "{}", first)?;
for line in lines {
write!(self.writer, "\n{}: {}", self.log_level, line)?;
}
if let Some('\n') = s.chars().next_back() {
writeln!(self.writer)?;
self.at_line_start = true;
}
Ok(())
}
}