lib.rs
#![no_std]
extern crate alloc;
use alloc::string::{String, ToString};
use core::fmt::Write;
use lazy_static::lazy_static;
use tracing_core::Subscriber;
use tracing_subscriber::Layer;
use uart_16550::SerialPort;
use x86_64::instructions::interrupts;
lazy_static! {
pub static ref SERIAL1: spin::Mutex<SerialPort> = {
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
serial_port.init();
spin::Mutex::new(serial_port)
};
}
/// Tracing subscriber that does nothing
// TODO: figure out how to use standard library so can replace with actual subscribers
pub struct MockSubscriber;
/// A layer that prints all events to the serial console
pub struct SerialLayer;
/// Simple visitor that formats any fields attached to spans
struct PrintVisitor(String);
impl<S> Layer<S> for SerialLayer
where
S: tracing_core::Subscriber,
{
fn on_event(
&self,
event: &tracing_core::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let metadata = event.metadata();
let mut msg = metadata.level().to_string();
// Attach any location context
if let Some(location) = metadata.file().or(metadata.module_path()) {
msg.push(' ');
msg.push_str(location);
if let Some(line) = metadata.line() {
msg.push(':');
msg.push_str(&line.to_string());
}
}
let mut visitor = PrintVisitor(String::new());
event.record(&mut visitor);
msg.push_str(&visitor.0);
msg.push('\n');
interrupts::without_interrupts(|| {
SERIAL1
.lock()
.write_str(&msg)
.expect("Printing to serial failed");
});
}
}
impl tracing::field::Visit for PrintVisitor {
fn record_debug(&mut self, field: &tracing_core::Field, value: &dyn core::fmt::Debug) {
self.0.push(' ');
if field.name() != "message" {
self.0.push_str(field.name());
self.0.push('=');
}
write!(self.0, "{:#?}", value).unwrap();
}
}
impl Subscriber for MockSubscriber {
fn enabled(&self, _metadata: &tracing_core::Metadata<'_>) -> bool {
true
}
fn new_span(&self, _span: &tracing_core::span::Attributes<'_>) -> tracing_core::span::Id {
tracing_core::span::Id::from_u64(0)
}
fn record(&self, _span: &tracing_core::span::Id, _values: &tracing_core::span::Record<'_>) {
()
}
fn record_follows_from(
&self,
_span: &tracing_core::span::Id,
_follows: &tracing_core::span::Id,
) {
()
}
fn event(&self, _event: &tracing_core::Event<'_>) {
()
}
fn enter(&self, _span: &tracing_core::span::Id) {
()
}
fn exit(&self, _span: &tracing_core::span::Id) {
()
}
}