1#![no_std]
4#![deny(warnings, missing_docs)]
5
6use core::{
7 fmt::{self, Write},
8 str::FromStr,
9};
10use spin::Once;
11
12pub extern crate log;
14
15pub trait Console: Sync {
17 fn put_char(&self, c: u8);
19
20 #[inline]
24 fn put_str(&self, s: &str) {
25 for c in s.bytes() {
26 self.put_char(c);
27 }
28 }
29}
30
31static CONSOLE: Once<&'static dyn Console> = Once::new();
33
34pub fn init_console(console: &'static dyn Console) {
36 CONSOLE.call_once(|| console);
37 log::set_logger(&Logger).unwrap();
38}
39
40pub fn set_log_level(env: Option<&str>) {
42 use log::LevelFilter as Lv;
43 log::set_max_level(env.and_then(|s| Lv::from_str(s).ok()).unwrap_or(Lv::Trace));
44}
45
46pub fn test_log() {
48 println!(
49 r"
50 ______ __
51 / ____/___ ____ _________ / /__
52 / / / __ \/ __ \/ ___/ __ \/ / _ \
53/ /___/ /_/ / / / (__ ) /_/ / / __/
54\____/\____/_/ /_/____/\____/_/\___/
55===================================="
56 );
57 log::trace!("LOG TEST >> Hello, world!");
58 log::debug!("LOG TEST >> Hello, world!");
59 log::info!("LOG TEST >> Hello, world!");
60 log::warn!("LOG TEST >> Hello, world!");
61 log::error!("LOG TEST >> Hello, world!");
62 println!();
63}
64
65#[doc(hidden)]
69#[inline]
70pub fn _print(args: fmt::Arguments) {
71 Logger.write_fmt(args).unwrap();
72}
73
74#[macro_export]
76macro_rules! print {
77 ($($arg:tt)*) => {
78 $crate::_print(core::format_args!($($arg)*));
79 }
80}
81
82#[macro_export]
84macro_rules! println {
85 () => ($crate::print!("\n"));
86 ($($arg:tt)*) => {{
87 $crate::_print(core::format_args!($($arg)*));
88 $crate::println!();
89 }}
90}
91
92struct Logger;
94
95impl Write for Logger {
97 #[inline]
98 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
99 let _ = CONSOLE.get().unwrap().put_str(s);
100 Ok(())
101 }
102}
103
104impl log::Log for Logger {
106 #[inline]
107 fn enabled(&self, _metadata: &log::Metadata) -> bool {
108 true
109 }
110
111 #[inline]
112 fn log(&self, record: &log::Record) {
113 use log::Level::*;
114 let color_code: u8 = match record.level() {
115 Error => 31,
116 Warn => 93,
117 Info => 34,
118 Debug => 32,
119 Trace => 90,
120 };
121 println!(
122 "\x1b[{color_code}m[{:>5}] {}\x1b[0m",
123 record.level(),
124 record.args(),
125 );
126 }
127
128 fn flush(&self) {}
129}